Merge changes I8f5a756a,I2bac468f,I043dfefa,I2c55f96e into oc-dev

* changes:
  Bluetooth: expand comments on new PHY constants
  Bluetooth: document status value in PHY read/update
  Bluetooth: Add handler parameter to connectGatt
  Get rid of the IAdvertiserCallabck
diff --git a/Android.mk b/Android.mk
index 6134fe2..e58f306 100644
--- a/Android.mk
+++ b/Android.mk
@@ -921,6 +921,7 @@
 # Conscrypt (com.android.org.conscrypt) is an implementation detail and should
 # not be referenced in the documentation.
 framework_docs_LOCAL_DROIDDOC_OPTIONS := \
+    -android \
     -knowntags ./frameworks/base/docs/knowntags.txt \
     -knowntags ./libcore/known_oj_tags.txt \
     -hidePackage com.android.org.conscrypt \
@@ -950,8 +951,8 @@
     -since $(SRC_API_DIR)/24.txt 24 \
     -since $(SRC_API_DIR)/25.txt 25 \
     -since ./frameworks/base/api/current.txt O \
-		-werror -hide 111 -hide 113 \
-		-overview $(LOCAL_PATH)/core/java/overview.html
+    -werror -hide 111 -hide 113 -hide 121 \
+    -overview $(LOCAL_PATH)/core/java/overview.html \
 
 # Allow the support library to add its own droiddoc options.
 include $(LOCAL_PATH)/../support/droiddoc.mk
diff --git a/api/current.txt b/api/current.txt
index c05672f..bd3d07a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8938,7 +8938,7 @@
     field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
     field public static final java.lang.String CARRIER_CONFIG_SERVICE = "carrier_config";
     field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
-    field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companion_device";
+    field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companiondevice";
     field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
     field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
     field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -24779,7 +24779,6 @@
   }
 
   public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
-    ctor public TvContract.WatchNextPrograms();
     field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
     field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
     field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
diff --git a/api/removed.txt b/api/removed.txt
index 73dd096..c132385 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -350,10 +350,6 @@
     field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
   }
 
-  public static final class FontsContract.Columns implements android.provider.BaseColumns {
-    field public static final java.lang.String STYLE = "font_style";
-  }
-
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 719d206..bcbd248 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9443,7 +9443,7 @@
     field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
     field public static final java.lang.String CARRIER_CONFIG_SERVICE = "carrier_config";
     field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
-    field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companion_device";
+    field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companiondevice";
     field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
     field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
     field public static final java.lang.String CONTEXTHUB_SERVICE = "contexthub";
@@ -26777,7 +26777,6 @@
   }
 
   public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
-    ctor public TvContract.WatchNextPrograms();
     field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
     field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
     field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
diff --git a/api/system-removed.txt b/api/system-removed.txt
index ed81363..039cd74 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -344,10 +344,6 @@
     field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
   }
 
-  public static final class FontsContract.Columns implements android.provider.BaseColumns {
-    field public static final java.lang.String STYLE = "font_style";
-  }
-
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index e59ca81..3ee9cb6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -8971,7 +8971,7 @@
     field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
     field public static final java.lang.String CARRIER_CONFIG_SERVICE = "carrier_config";
     field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
-    field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companion_device";
+    field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companiondevice";
     field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
     field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
     field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -24887,7 +24887,6 @@
   }
 
   public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
-    ctor public TvContract.WatchNextPrograms();
     field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
     field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
     field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 73dd096..c132385 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -350,10 +350,6 @@
     field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
   }
 
-  public static final class FontsContract.Columns implements android.provider.BaseColumns {
-    field public static final java.lang.String STYLE = "font_style";
-  }
-
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
   }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 46ce94f..195ba24 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -51,7 +51,6 @@
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Typeface;
 import android.hardware.display.DisplayManagerGlobal;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
@@ -90,6 +89,7 @@
 import android.provider.CallLog;
 import android.provider.ContactsContract;
 import android.provider.Downloads;
+import android.provider.FontsContract;
 import android.provider.Settings;
 import android.security.NetworkSecurityPolicy;
 import android.security.net.config.NetworkSecurityConfigProvider;
@@ -5793,7 +5793,7 @@
         }
 
         // Preload fonts resources
-        Typeface.setApplicationContext(appContext);
+        FontsContract.setApplicationContextForResources(appContext);
         try {
             final ApplicationInfo info =
                     getPackageManager().getApplicationInfo(
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 0676bca..6d87de8 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -20,7 +20,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RawRes;
+import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -103,6 +105,7 @@
      * <p>Output: RESULT_OK if user decided to crop/set the wallpaper, RESULT_CANCEL otherwise
      * Activities that support this intent should specify a MIME filter of "image/*"
      */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_CROP_AND_SET_WALLPAPER =
             "android.service.wallpaper.CROP_AND_SET_WALLPAPER";
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a939eb0..7855b92 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1518,7 +1518,8 @@
      * Service action: Action for a service that device owner and profile owner can optionally
      * own.  If a device owner or a profile owner has such a service, the system tries to keep
      * a bound connection to it, in order to keep their process always running.
-     * The service must not be exported.
+     * The service must be protected with the {@link android.Manifest.permission#BIND_DEVICE_ADMIN}
+     * permission.
      */
     @SdkConstant(SdkConstantType.SERVICE_ACTION)
     public static final String ACTION_DEVICE_ADMIN_SERVICE
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 42ef871..d0ce3cf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3769,7 +3769,7 @@
      * @see #getSystemService
      * @see android.companion.CompanionDeviceManager
      */
-    public static final String COMPANION_DEVICE_SERVICE = "companion_device";
+    public static final String COMPANION_DEVICE_SERVICE = "companiondevice";
 
     /**
      * Use with {@link #getSystemService} to retrieve a
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 9c87ff2..da43fec 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1399,6 +1399,7 @@
      *  <p>Input: nothing
      *  <p>Output: nothing
      */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST";
 
     /**
@@ -2061,6 +2062,7 @@
      * temporary system dialog to dismiss.  Some examples of temporary system
      * dialogs are the notification window-shade and the recent tasks dialog.
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
     /**
      * Broadcast Action: Trigger the download and eventual installation
@@ -2590,6 +2592,7 @@
      * @deprecated replaced by android.os.storage.StorageEventListener
      */
     @Deprecated
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_UMS_CONNECTED = "android.intent.action.UMS_CONNECTED";
 
     /**
@@ -2600,6 +2603,7 @@
      * @deprecated replaced by android.os.storage.StorageEventListener
      */
     @Deprecated
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_UMS_DISCONNECTED = "android.intent.action.UMS_DISCONNECTED";
 
     /**
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index d64f018..c9bce53 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Parcel;
@@ -33,6 +34,8 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Set;
@@ -283,9 +286,22 @@
     private static final int STATE_VERIFIED            = 0x00001000;
 
     private int mVerifyState;
-
+    /** @hide */
+    public static final int VISIBILITY_NONE = 0;
+    /** @hide */
+    public static final int VISIBILITY_EXPLICIT = 1;
+    /** @hide */
+    public static final int VISIBILITY_IMPLICIT = 2;
+    /** @hide */
+    @IntDef(prefix = { "VISIBILITY_" }, value = {
+            VISIBILITY_NONE,
+            VISIBILITY_EXPLICIT,
+            VISIBILITY_IMPLICIT,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface InstantAppVisibility {}
     /** Whether or not the intent filter is visible to instant apps. */
-    private boolean mVisibleToInstantApp;
+    private @InstantAppVisibility int mInstantAppVisibility;
     // These functions are the start of more optimized code for managing
     // the string sets...  not yet implemented.
 
@@ -452,7 +468,7 @@
         }
         mHasPartialTypes = o.mHasPartialTypes;
         mVerifyState = o.mVerifyState;
-        mVisibleToInstantApp = o.mVisibleToInstantApp;
+        mInstantAppVisibility = o.mInstantAppVisibility;
     }
 
     /**
@@ -655,12 +671,24 @@
     }
 
     /** @hide */
-    public void setVisibleToInstantApp(boolean visibleToInstantApp) {
-        mVisibleToInstantApp = visibleToInstantApp;
+    public void setVisibilityToInstantApp(@InstantAppVisibility int visibility) {
+        mInstantAppVisibility = visibility;
+    }
+    /** @hide */
+    public @InstantAppVisibility int getVisibilityToInstantApp() {
+        return mInstantAppVisibility;
     }
     /** @hide */
     public boolean isVisibleToInstantApp() {
-        return mVisibleToInstantApp;
+        return mInstantAppVisibility != VISIBILITY_NONE;
+    }
+    /** @hide */
+    public boolean isExplicitlyVisibleToInstantApp() {
+        return mInstantAppVisibility == VISIBILITY_EXPLICIT;
+    }
+    /** @hide */
+    public boolean isImplicitlyVisibleToInstantApp() {
+        return mInstantAppVisibility == VISIBILITY_IMPLICIT;
     }
 
     /**
@@ -1859,7 +1887,7 @@
         dest.writeInt(mPriority);
         dest.writeInt(mHasPartialTypes ? 1 : 0);
         dest.writeInt(getAutoVerify() ? 1 : 0);
-        dest.writeInt(isVisibleToInstantApp() ? 1 : 0);
+        dest.writeInt(mInstantAppVisibility);
     }
 
     /**
@@ -1928,7 +1956,7 @@
         mPriority = source.readInt();
         mHasPartialTypes = source.readInt() > 0;
         setAutoVerify(source.readInt() > 0);
-        setVisibleToInstantApp(source.readInt() > 0);
+        setVisibilityToInstantApp(source.readInt());
     }
 
     private final boolean findMimeType(String type) {
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index b01e6a1..0be0885 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.annotation.IntDef;
+import android.content.Intent;
 import android.content.res.Configuration;
 import android.content.res.Configuration.NativeConfig;
 import android.os.Parcel;
@@ -412,17 +413,33 @@
     public static final int FLAG_ALWAYS_FOCUSABLE = 0x40000;
 
     /**
-     * Bit in {@link #flags} indicating if the activity is visible to ephemeral applications.
+     * Bit in {@link #flags} indicating if the activity is visible to instant
+     * applications. The activity is visible if it's either implicitly or
+     * explicitly exposed.
      * @hide
      */
-    public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000;
+    public static final int FLAG_VISIBLE_TO_INSTANT_APP = 0x100000;
+
+    /**
+     * Bit in {@link #flags} indicating if the activity is implicitly visible
+     * to instant applications. Implicitly visible activities are those that
+     * implement certain intent-filters:
+     * <ul>
+     * <li>action {@link Intent#CATEGORY_BROWSABLE}</li>
+     * <li>action {@link Intent#ACTION_SEND}</li>
+     * <li>action {@link Intent#ACTION_SENDTO}</li>
+     * <li>action {@link Intent#ACTION_SEND_MULTIPLE}</li>
+     * </ul>
+     * @hide
+     */
+    public static final int FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP = 0x200000;
 
     /**
      * Bit in {@link #flags} indicating if the activity supports picture-in-picture mode.
      * See {@link android.R.attr#supportsPictureInPicture}.
      * @hide
      */
-    public static final int FLAG_SUPPORTS_PICTURE_IN_PICTURE = 0x200000;
+    public static final int FLAG_SUPPORTS_PICTURE_IN_PICTURE = 0x400000;
 
     /**
      * @hide Bit in {@link #flags}: If set, this component will only be seen
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ecaf7eb..d2468d9 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -461,12 +461,20 @@
 
     /**
      * Internal {@link PackageInfo} flag: include only components that are exposed to
-     * ephemeral apps.
+     * instant apps. Matched components may have been either explicitly or implicitly
+     * exposed.
      * @hide
      */
     public static final int MATCH_VISIBLE_TO_INSTANT_APP_ONLY = 0x01000000;
 
     /**
+     * Internal {@link PackageInfo} flag: include only components that have been
+     * explicitly exposed to instant apps.
+     * @hide
+     */
+    public static final int MATCH_EXPLICITLY_VISIBLE_ONLY = 0x02000000;
+
+    /**
      * Internal flag used to indicate that a system component has done their
      * homework and verified that they correctly handle packages and components
      * that come and go over time. In particular:
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 8609351..e4db0f0 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -4271,7 +4271,7 @@
         boolean visibleToEphemeral =
                 sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
         if (visibleToEphemeral) {
-            a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+            a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
             owner.visibleToInstantApps = true;
         }
 
@@ -4313,9 +4313,17 @@
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
-                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
+                final int visibility = visibleToEphemeral
+                        ? IntentFilter.VISIBILITY_EXPLICIT
+                        : !receiver && isImplicitlyExposedIntent(intent)
+                                ? IntentFilter.VISIBILITY_IMPLICIT
+                                : IntentFilter.VISIBILITY_NONE;
+                intent.setVisibilityToInstantApp(visibility);
                 if (intent.isVisibleToInstantApp()) {
-                    a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+                    a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
+                }
+                if (intent.isImplicitlyVisibleToInstantApp()) {
+                    a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
                 }
                 if (LOG_UNSAFE_BROADCASTS && receiver
                         && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) {
@@ -4346,9 +4354,17 @@
                     owner.preferredActivityFilters.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
-                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
+                final int visibility = visibleToEphemeral
+                        ? IntentFilter.VISIBILITY_EXPLICIT
+                        : !receiver && isImplicitlyExposedIntent(intent)
+                                ? IntentFilter.VISIBILITY_IMPLICIT
+                                : IntentFilter.VISIBILITY_NONE;
+                intent.setVisibilityToInstantApp(visibility);
                 if (intent.isVisibleToInstantApp()) {
-                    a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+                    a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
+                }
+                if (intent.isImplicitlyVisibleToInstantApp()) {
+                    a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
                 }
             } else if (parser.getName().equals("meta-data")) {
                 if ((a.metaData = parseMetaData(res, parser, a.metaData,
@@ -4358,16 +4374,18 @@
                 // we don't have an attribute [or it's false], but, we have meta-data
                 if (!visibleToEphemeral && a.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
                     visibleToEphemeral = true; // set in case there are more intent filters
-                    a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+                    a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
+                    a.info.flags &= ~ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
                     owner.visibleToInstantApps = true;
                     // cycle through any filters already seen
                     for (int i = a.intents.size() - 1; i >= 0; --i) {
-                        a.intents.get(i).setVisibleToInstantApp(true /*visibleToInstantApp*/);
+                        a.intents.get(i)
+                                .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                     }
                     if (owner.preferredActivityFilters != null) {
                         for (int i = owner.preferredActivityFilters.size() - 1; i >= 0; --i) {
                             owner.preferredActivityFilters.get(i)
-                                    .setVisibleToInstantApp(true /*visibleToInstantApp*/);
+                                    .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                         }
                     }
                 }
@@ -4645,7 +4663,7 @@
 
         // TODO add visibleToInstantApps attribute to activity alias
         final boolean visibleToEphemeral =
-                ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0);
+                ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
 
         sa.recycle();
 
@@ -4673,13 +4691,20 @@
                             + mArchiveSourcePath + " "
                             + parser.getPositionDescription());
                 } else {
-                    intent.setVisibleToInstantApp(
-                            visibleToEphemeral || isImplicitlyExposedIntent(intent));
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
+                final int visibility = visibleToEphemeral
+                        ? IntentFilter.VISIBILITY_EXPLICIT
+                        : isImplicitlyExposedIntent(intent)
+                                ? IntentFilter.VISIBILITY_IMPLICIT
+                                : IntentFilter.VISIBILITY_NONE;
+                intent.setVisibilityToInstantApp(visibility);
                 if (intent.isVisibleToInstantApp()) {
-                    a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+                    a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
+                }
+                if (intent.isImplicitlyVisibleToInstantApp()) {
+                    a.info.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
                 }
             } else if (parser.getName().equals("meta-data")) {
                 if ((a.metaData=parseMetaData(res, parser, a.metaData,
@@ -4822,7 +4847,7 @@
         final boolean visibleToEphemeral =
                 sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
         if (visibleToEphemeral) {
-            p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+            p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
             owner.visibleToInstantApps = true;
         }
 
@@ -4874,12 +4899,11 @@
                         intent, outError)) {
                     return false;
                 }
-                outInfo.intents.add(intent);
-                // adjust provider flags when we implicitly expose it via a browsable filter
-                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
-                if (intent.isVisibleToInstantApp()) {
-                    outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+                if (visibleToEphemeral) {
+                    intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
+                    outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                 }
+                outInfo.intents.add(intent);
 
             } else if (parser.getName().equals("meta-data")) {
                 if ((outInfo.metaData=parseMetaData(res, parser,
@@ -4889,11 +4913,12 @@
                 // we don't have an attribute [or it's false], but, we have meta-data
                 if (!visibleToEphemeral && outInfo.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
                     visibleToEphemeral = true; // set in case there are more intent filters
-                    outInfo.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+                    outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                     owner.visibleToInstantApps = true;
                     // cycle through any filters already seen
                     for (int i = outInfo.intents.size() - 1; i >= 0; --i) {
-                        outInfo.intents.get(i).setVisibleToInstantApp(true /*visibleToInstantApp*/);
+                        outInfo.intents.get(i)
+                                .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                     }
                 }
 
@@ -5149,7 +5174,7 @@
         boolean visibleToEphemeral =
                 sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
         if (visibleToEphemeral) {
-            s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+            s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
             owner.visibleToInstantApps = true;
         }
 
@@ -5180,10 +5205,9 @@
                         intent, outError)) {
                     return null;
                 }
-                // adjust activity flags when we implicitly expose it via a browsable filter
-                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
-                if (intent.isVisibleToInstantApp()) {
-                    s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+                if (visibleToEphemeral) {
+                    intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
+                    s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                 }
                 s.intents.add(intent);
             } else if (parser.getName().equals("meta-data")) {
@@ -5194,11 +5218,12 @@
                 // we don't have an attribute [or it's false], but, we have meta-data
                 if (!visibleToEphemeral && s.metaData.getBoolean(META_DATA_INSTANT_APPS)) {
                     visibleToEphemeral = true; // set in case there are more intent filters
-                    s.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
+                    s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
                     owner.visibleToInstantApps = true;
                     // cycle through any filters already seen
                     for (int i = s.intents.size() - 1; i >= 0; --i) {
-                        s.intents.get(i).setVisibleToInstantApp(true /*visibleToInstantApp*/);
+                        s.intents.get(i)
+                                .setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
                     }
                 }
             } else {
diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java
index 8c21563..91dc06e 100644
--- a/core/java/android/content/pm/ProviderInfo.java
+++ b/core/java/android/content/pm/ProviderInfo.java
@@ -79,7 +79,7 @@
      * Bit in {@link #flags} indicating if the provider is visible to ephemeral applications.
      * @hide
      */
-    public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000;
+    public static final int FLAG_VISIBLE_TO_INSTANT_APP = 0x100000;
 
     /**
      * Bit in {@link #flags}: If set, a single instance of the provider will
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index f0766be..c683ea5 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -59,7 +59,7 @@
      * Bit in {@link #flags} indicating if the service is visible to ephemeral applications.
      * @hide
      */
-    public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000;
+    public static final int FLAG_VISIBLE_TO_INSTANT_APP = 0x100000;
 
     /**
      * Bit in {@link #flags}: If set, a single instance of the service will
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index f5ad5cc..51506b0 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -285,17 +285,22 @@
                 }
                 // Initialize a client for data_injection.
                 if (sInjectEventQueue == null) {
-                    sInjectEventQueue = new InjectEventQueue(mMainLooper, this,
-                            mContext.getPackageName());
+                    try {
+                        sInjectEventQueue = new InjectEventQueue(
+                                mMainLooper, this, mContext.getPackageName());
+                    } catch (RuntimeException e) {
+                        Log.e(TAG, "Cannot create InjectEventQueue: " + e);
+                    }
                 }
+                return sInjectEventQueue != null;
             } else {
                 // If data injection is being disabled clean up the native resources.
                 if (sInjectEventQueue != null) {
                     sInjectEventQueue.dispose();
                     sInjectEventQueue = null;
                 }
+                return true;
             }
-            return true;
         }
     }
 
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 7bfb5d0..211d54d 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -135,7 +135,7 @@
 
      /** @hide */
      @Retention(RetentionPolicy.SOURCE)
-     @IntDef(
+     @IntDef(prefix = {"TEMPLATE_"}, value =
          {TEMPLATE_PREVIEW,
           TEMPLATE_STILL_CAPTURE,
           TEMPLATE_RECORD,
@@ -757,7 +757,7 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(
+    @IntDef(prefix = {"SESSION_OPERATION_MODE"}, value =
             {SESSION_OPERATION_MODE_NORMAL,
              SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED,
              SESSION_OPERATION_MODE_VENDOR_START})
@@ -808,10 +808,9 @@
      * create a builder specific for that device and template and override the
      * settings as desired, instead.</p>
      *
-     * @param templateType An enumeration selecting the use case for this
-     * request; one of the CameraDevice.TEMPLATE_ values. Not all template
-     * types are supported on every device. See the documentation for each
-     * template type for details.
+     * @param templateType An enumeration selecting the use case for this request. Not all template
+     * types are supported on every device. See the documentation for each template type for
+     * details.
      * @return a builder for a capture request, initialized with default
      * settings for that template, and no output streams
      *
@@ -969,7 +968,7 @@
 
         /** @hide */
         @Retention(RetentionPolicy.SOURCE)
-        @IntDef(
+        @IntDef(prefix = {"ERROR_"}, value =
             {ERROR_CAMERA_IN_USE,
              ERROR_MAX_CAMERAS_IN_USE,
              ERROR_CAMERA_DISABLED,
@@ -1052,8 +1051,7 @@
          * this happens. Further attempts at recovery are error-code specific.</p>
          *
          * @param camera The device reporting the error
-         * @param error The error code, one of the
-         *     {@code StateCallback.ERROR_*} values.
+         * @param error The error code.
          *
          * @see #ERROR_CAMERA_IN_USE
          * @see #ERROR_MAX_CAMERAS_IN_USE
diff --git a/core/java/android/hardware/camera2/CaptureFailure.java b/core/java/android/hardware/camera2/CaptureFailure.java
index 8bb33f1..fbe0839 100644
--- a/core/java/android/hardware/camera2/CaptureFailure.java
+++ b/core/java/android/hardware/camera2/CaptureFailure.java
@@ -51,7 +51,7 @@
 
      /** @hide */
      @Retention(RetentionPolicy.SOURCE)
-     @IntDef(
+     @IntDef(prefix = {"REASON_"}, value =
          {REASON_ERROR,
           REASON_FLUSHED })
      public @interface FailureReason {};
@@ -119,7 +119,7 @@
      * Determine why the request was dropped, whether due to an error or to a user
      * action.
      *
-     * @return int One of {@code REASON_*} integer constants.
+     * @return int The reason code.
      *
      * @see #REASON_ERROR
      * @see #REASON_FLUSHED
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index ae92457..b2a2aaf 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -17,9 +17,9 @@
 
 package android.hardware.usb;
 
-import com.android.internal.util.Preconditions;
-
 import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
@@ -30,6 +30,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.util.Preconditions;
+
 import java.util.HashMap;
 
 /**
@@ -109,6 +111,7 @@
      * for the attached device
      * </ul>
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_USB_DEVICE_ATTACHED =
             "android.hardware.usb.action.USB_DEVICE_ATTACHED";
 
@@ -121,6 +124,7 @@
      * for the detached device
      * </ul>
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_USB_DEVICE_DETACHED =
             "android.hardware.usb.action.USB_DEVICE_DETACHED";
 
@@ -133,6 +137,7 @@
      * for the attached accessory
      * </ul>
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_USB_ACCESSORY_ATTACHED =
             "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";
 
@@ -145,6 +150,7 @@
      * for the attached accessory that was detached
      * </ul>
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_USB_ACCESSORY_DETACHED =
             "android.hardware.usb.action.USB_ACCESSORY_DETACHED";
 
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index cb85eef..db84b6f 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.util.Log;
 
@@ -67,6 +69,7 @@
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_DROPBOX_ENTRY_ADDED =
         "android.intent.action.DROPBOX_ENTRY_ADDED";
 
diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java
index b31b295..42d5ce1 100644
--- a/core/java/android/provider/Contacts.java
+++ b/core/java/android/provider/Contacts.java
@@ -18,6 +18,8 @@
 
 import com.android.internal.R;
 
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -2164,6 +2166,7 @@
              * @deprecated Do not use. This is not supported.
              */
             @Deprecated
+            @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
             public static final String FILTER_CONTACTS_ACTION =
                     "com.android.contacts.action.FILTER_CONTACTS";
 
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b4f19d8..5408e13 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -17,6 +17,8 @@
 package android.provider;
 
 import android.accounts.Account;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.app.Activity;
 import android.content.BroadcastReceiver;
@@ -8401,6 +8403,7 @@
          * Action used to launch the system contacts application and bring up a QuickContact dialog
          * for the provided {@link Contacts} entry.
          */
+        @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
         public static final String ACTION_QUICK_CONTACT =
                 "android.provider.action.QUICK_CONTACT";
 
@@ -8924,6 +8927,7 @@
          * @see #METADATA_ACCOUNT_TYPE
          * @see #METADATA_MIMETYPE
          */
+        @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
         public static final String ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS =
                 "android.provider.action.VOICE_SEND_MESSAGE_TO_CONTACTS";
 
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index e68c7bb..bcd1b6b 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -105,14 +105,6 @@
          */
         public static final String VARIATION_SETTINGS = "font_variation_settings";
         /**
-         * DO NOT USE THIS COLUMN.
-         * This column is kept for preventing demo apps.
-         * TODO: Remove once nobody uses this column.
-         * @hide
-         * @removed
-         */
-        public static final String STYLE = "font_style";
-        /**
          * Constant used to request data from a font provider. The cursor returned from the query
          * should have this column populated with the int weight for the resulting font. This value
          * should be between 100 and 900. The most common values are 400 for regular weight and 700
@@ -159,38 +151,24 @@
         public static final int RESULT_CODE_MALFORMED_QUERY = 3;
     }
 
-    /**
-     * Constant used to identify the List of {@link ParcelFileDescriptor} item in the Bundle
-     * returned to the ResultReceiver in getFont.
-     * @hide
-     */
-    public static final String PARCEL_FONT_RESULTS = "font_results";
-    // Error codes internal to the system, which can not come from a provider. To keep the number
-    // space open for new provider codes, these should all be negative numbers.
-    /** @hide */
-    public static final int RESULT_CODE_PROVIDER_NOT_FOUND = -1;
-    /** @hide */
-    public static final int RESULT_CODE_WRONG_CERTIFICATES = -2;
-    // Note -3 is used by Typeface to indicate the font failed to load.
+    private static final Object sLock = new Object();
+    @GuardedBy("sLock")
+    private static Handler sHandler;
+    @GuardedBy("sLock")
+    private static HandlerThread sThread;
+    @GuardedBy("sLock")
+    private static Set<String> sInQueueSet;
 
-    private static final int THREAD_RENEWAL_THRESHOLD_MS = 10000;
-
-    private final Context mContext;
-    private final PackageManager mPackageManager;
-    private final Object mLock = new Object();
-    @GuardedBy("mLock")
-    private Handler mHandler;
-    @GuardedBy("mLock")
-    private HandlerThread mThread;
-    @GuardedBy("mLock")
-    private Set<String> mInQueueSet;
+    private volatile static Context sContext;  // set once in setApplicationContextForResources
 
     private static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16);
 
+    private FontsContract() {
+    }
+
     /** @hide */
-    public FontsContract(Context context) {
-        mContext = context.getApplicationContext();
-        mPackageManager = mContext.getPackageManager();
+    public static void setApplicationContextForResources(Context context) {
+        sContext = context.getApplicationContext();
     }
 
     /**
@@ -323,24 +301,27 @@
         }
     }
 
+    private static final int THREAD_RENEWAL_THRESHOLD_MS = 10000;
+
     // We use a background thread to post the content resolving work for all requests on. This
     // thread should be quit/stopped after all requests are done.
-    private final Runnable mReplaceDispatcherThreadRunnable = new Runnable() {
+    // TODO: Factor out to other class. Consider to switch MessageQueue.IdleHandler.
+    private static final Runnable sReplaceDispatcherThreadRunnable = new Runnable() {
         @Override
         public void run() {
-            synchronized (mLock) {
-                if (mThread != null) {
-                    mThread.quitSafely();
-                    mThread = null;
-                    mHandler = null;
-                    mInQueueSet = null;
+            synchronized (sLock) {
+                if (sThread != null) {
+                    sThread.quitSafely();
+                    sThread = null;
+                    sHandler = null;
+                    sInQueueSet = null;
                 }
             }
         }
     };
 
     /** @hide */
-    public Typeface getFontOrWarmUpCache(FontRequest request) {
+    public static Typeface getFontOrWarmUpCache(FontRequest request) {
         final String id = request.getIdentifier();
         Typeface cachedTypeface = sTypefaceCache.get(id);
         if (cachedTypeface != null) {
@@ -350,25 +331,25 @@
         // Unfortunately the typeface is not available at this time, but requesting from the font
         // provider takes too much time. For now, request the font data to ensure it is in the cache
         // next time and return.
-        synchronized (mLock) {
-            if (mHandler == null) {
-                mThread = new HandlerThread("fonts", Process.THREAD_PRIORITY_BACKGROUND);
-                mThread.start();
-                mHandler = new Handler(mThread.getLooper());
-                mInQueueSet = new ArraySet<String>();
+        synchronized (sLock) {
+            if (sHandler == null) {
+                sThread = new HandlerThread("fonts", Process.THREAD_PRIORITY_BACKGROUND);
+                sThread.start();
+                sHandler = new Handler(sThread.getLooper());
+                sInQueueSet = new ArraySet<>();
             }
-            if (mInQueueSet.contains(id)) {
+            if (sInQueueSet.contains(id)) {
                 return null;  // Already requested.
             }
-            mInQueueSet.add(id);
-            mHandler.post(() -> {
-                synchronized (mLock) {
-                    mInQueueSet.remove(id);
+            sInQueueSet.add(id);
+            sHandler.post(() -> {
+                synchronized (sLock) {
+                    sInQueueSet.remove(id);
                 }
                 try {
-                    FontFamilyResult result = fetchFonts(mContext, null, request);
+                    FontFamilyResult result = fetchFonts(sContext, null, request);
                     if (result.getStatusCode() == FontFamilyResult.STATUS_OK) {
-                        Typeface typeface = buildTypeface(mContext, null, result.getFonts());
+                        Typeface typeface = buildTypeface(sContext, null, result.getFonts());
                         if (typeface != null) {
                             sTypefaceCache.put(id, typeface);
                         }
@@ -377,8 +358,8 @@
                     // Ignore.
                 }
             });
-            mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable);
-            mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS);
+            sHandler.removeCallbacks(sReplaceDispatcherThreadRunnable);
+            sHandler.postDelayed(sReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS);
         }
         return null;
     }
@@ -391,12 +372,12 @@
          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
          * provider was not found on the device.
          */
-        public static final int FAIL_REASON_PROVIDER_NOT_FOUND = RESULT_CODE_PROVIDER_NOT_FOUND;
+        public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1;
         /**
          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
          * provider must be authenticated and the given certificates do not match its signature.
          */
-        public static final int FAIL_REASON_WRONG_CERTIFICATES = RESULT_CODE_WRONG_CERTIFICATES;
+        public static final int FAIL_REASON_WRONG_CERTIFICATES = -2;
         /**
          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
          * returned by the provider was not loaded properly.
@@ -767,7 +748,7 @@
                 .build();
         try (Cursor cursor = context.getContentResolver().query(uri, new String[] { Columns._ID,
                         Columns.FILE_ID, Columns.TTC_INDEX, Columns.VARIATION_SETTINGS,
-                        Columns.STYLE, Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE },
+                        Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE },
                 "query = ?", new String[] { request.getQuery() }, null, cancellationSignal);) {
             // TODO: Should we restrict the amount of fonts that can be returned?
             // TODO: Write documentation explaining that all results should be from the same family.
@@ -780,7 +761,6 @@
                 final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS);
                 final int weightColumnIndex = cursor.getColumnIndex(Columns.WEIGHT);
                 final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC);
-                final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE);
                 while (cursor.moveToNext()) {
                     int resultCode = resultCodeColumnIndex != -1
                             ? cursor.getInt(resultCodeColumnIndex) : Columns.RESULT_CODE_OK;
@@ -797,17 +777,11 @@
                         long id = cursor.getLong(fileIdColumnIndex);
                         fileUri = ContentUris.withAppendedId(fileBaseUri, id);
                     }
-                    // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column.
                     int weight;
                     boolean italic;
                     if (weightColumnIndex != -1 && italicColumnIndex != -1) {
                         weight = cursor.getInt(weightColumnIndex);
                         italic = cursor.getInt(italicColumnIndex) == 1;
-                    } else if (styleColumnIndex != -1) {
-                        final int style = cursor.getInt(styleColumnIndex);
-                        weight = (style & Typeface.BOLD) != 0 ?
-                                Typeface.Builder.BOLD_WEIGHT : Typeface.Builder.NORMAL_WEIGHT;
-                        italic = (style & Typeface.ITALIC) != 0;
                     } else {
                         weight = Typeface.Builder.NORMAL_WEIGHT;
                         italic = false;
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 93adf83..13e1e26 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -1498,6 +1498,7 @@
              * May also contain the extra EXTRA_MAX_BYTES.
              * @see #EXTRA_MAX_BYTES
              */
+            @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
             public static final String RECORD_SOUND_ACTION =
                     "android.provider.MediaStore.RECORD_SOUND";
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 69371be..cbd41c3 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6943,6 +6943,7 @@
             ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
             ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
             ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
+            AUTOFILL_SERVICE,
             ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
             ENABLED_ACCESSIBILITY_SERVICES,
             ENABLED_NOTIFICATION_LISTENERS,
diff --git a/core/java/android/util/MergedConfiguration.java b/core/java/android/util/MergedConfiguration.java
index d94af8a..68d0309 100644
--- a/core/java/android/util/MergedConfiguration.java
+++ b/core/java/android/util/MergedConfiguration.java
@@ -21,6 +21,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.io.PrintWriter;
+
 /**
  * Container that holds global and override config and their merge product.
  * Merged configuration updates automatically whenever global or override configs are updated via
@@ -41,6 +43,10 @@
         setConfiguration(globalConfig, overrideConfig);
     }
 
+    public MergedConfiguration(Configuration globalConfig) {
+        setGlobalConfiguration(globalConfig);
+    }
+
     public MergedConfiguration(MergedConfiguration mergedConfiguration) {
         setConfiguration(mergedConfiguration.getGlobalConfiguration(),
                 mergedConfiguration.getOverrideConfiguration());
@@ -93,6 +99,36 @@
     }
 
     /**
+     * Update global configurations.
+     * Merged configuration will automatically be updated.
+     * @param globalConfig New global configuration.
+     */
+    public void setGlobalConfiguration(Configuration globalConfig) {
+        mGlobalConfig.setTo(globalConfig);
+        updateMergedConfig();
+    }
+
+    /**
+     * Update override configurations.
+     * Merged configuration will automatically be updated.
+     * @param overrideConfig New override configuration.
+     */
+    public void setOverrideConfiguration(Configuration overrideConfig) {
+        mOverrideConfig.setTo(overrideConfig);
+        updateMergedConfig();
+    }
+
+    public void setTo(MergedConfiguration config) {
+        setConfiguration(config.mGlobalConfig, config.mOverrideConfig);
+    }
+
+    public void unset() {
+        mGlobalConfig.unset();
+        mOverrideConfig.unset();
+        updateMergedConfig();
+    }
+
+    /**
      * @return Stored global configuration value.
      */
     @NonNull
@@ -119,4 +155,14 @@
         mMergedConfig.setTo(mGlobalConfig);
         mMergedConfig.updateFrom(mOverrideConfig);
     }
+
+    @Override
+    public String toString() {
+        return "{mGlobalConfig=" + mGlobalConfig + " mOverrideConfig=" + mOverrideConfig + "}";
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + "mGlobalConfig=" + mGlobalConfig);
+        pw.println(prefix + "mOverrideConfig=" + mOverrideConfig);
+    }
 }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1977ef5..b7834823 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5823,34 +5823,6 @@
     }
 
     /**
-     * Quick invalidation method that simply transforms the dirty rect into the parent's
-     * coordinate system, pruning the invalidation if the parent has already been invalidated.
-     *
-     * @hide
-     */
-    protected ViewParent damageChildInParent(int left, int top, final Rect dirty) {
-        if ((mPrivateFlags & PFLAG_DRAWN) != 0
-                || (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) != 0) {
-            dirty.offset(left - mScrollX, top - mScrollY);
-            if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0) {
-                dirty.union(0, 0, mRight - mLeft, mBottom - mTop);
-            }
-
-            if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0 ||
-                    dirty.intersect(0, 0, mRight - mLeft, mBottom - mTop)) {
-
-                if (!getMatrix().isIdentity()) {
-                    transformRect(dirty);
-                }
-
-                return mParent;
-            }
-        }
-
-        return null;
-    }
-
-    /**
      * Offset a rectangle that is in a descendant's coordinate
      * space into our coordinate space.
      * @param descendant A descendant of this view
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index f061370..21123c1 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -330,20 +330,20 @@
 
         @Override
         public void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
-            if (mHostView != null && mHostView.getParent() != null) {
-                mHostView.getParent().onDescendantInvalidated(mHostView, target);
-            }
-        }
+            if (mHostView != null) {
+                if (mHostView instanceof ViewGroup) {
+                    // Propagate invalidate through the host...
+                    ((ViewGroup) mHostView).onDescendantInvalidated(mHostView, target);
 
-        /**
-         * @hide
-         */
-        @Override
-        protected ViewParent damageChildInParent(int left, int top, Rect dirty) {
-            if (mHostView instanceof ViewGroup) {
-                return ((ViewGroup) mHostView).damageChildInParent(left, top, dirty);
+                    // ...and also this view, since it will hold the descendant, and must later
+                    // propagate the calls to update display lists if dirty
+                    super.onDescendantInvalidated(child, target);
+                } else {
+                    // Can't use onDescendantInvalidated because host isn't a ViewGroup - fall back
+                    // to invalidating.
+                    invalidate();
+                }
             }
-            return null;
         }
 
         @Override
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 869ef71..74f22b3 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -37,19 +37,38 @@
 import java.util.List;
 
 /**
- * A concrete BaseAdapter that is backed by an array of arbitrary
- * objects.  By default this class expects that the provided resource id references
- * a single TextView.  If you want to use a more complex layout, use the constructors that
- * also takes a field id.  That field id should reference a TextView in the larger layout
- * resource.
- *
- * <p>However the TextView is referenced, it will be filled with the toString() of each object in
- * the array. You can add lists or arrays of custom objects. Override the toString() method
- * of your objects to determine what text will be displayed for the item in the list.
- *
- * <p>To use something other than TextViews for the array display, for instance, ImageViews,
- * or to have some of data besides toString() results fill the views,
- * override {@link #getView(int, View, ViewGroup)} to return the type of view you want.
+ * You can use this adapter to provide views for an {@link AdapterView},
+ * Returns a view for each object in a collection of data objects you
+ * provide, and can be used with list-based user interface widgets such as
+ * {@link ListView} or {@link Spinner}.
+ * <p>
+ * By default, the array adapter creates a view by calling {@link Object#toString()} on each
+ * data object in the collection you provide, and places the result in a TextView.
+ * You may also customize what type of view is used for the data object in the collection.
+ * To customize what type of view is used for the data object,
+ * override {@link #getView(int, View, ViewGroup)}
+ * and inflate a view resource.
+ * For a code example, see
+ * the <a href="https://developer.android.com/samples/CustomChoiceList/index.html">
+ * CustomChoiceList</a> sample.
+ * </p>
+ * <p>
+ * For an example of using an array adapter with a ListView, see the
+ * <a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">
+ * Adapter Views</a> guide.
+ * </p>
+ * <p>
+ * For an example of using an array adapter with a Spinner, see the
+ * <a href="{@docRoot}guide/topics/ui/controls/spinner.html">Spinners</a> guide.
+ * </p>
+ * <p class="note"><strong>Note:</strong>
+ * If you are considering using array adapter with a ListView, consider using
+ * {@link android.support.v7.widget.RecyclerView} instead.
+ * RecyclerView offers similar features with better performance and more flexibility than
+ * ListView provides.
+ * See the
+ * <a href="https://developer.android.com/guide/topics/ui/layout/recyclerview.html">
+ * Recycler View</a> guide.</p>
  */
 public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
     /**
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 12e35a1..569fe01 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -67,11 +67,77 @@
 
 
 /**
- * A view that shows items in a vertically scrolling list. The items
- * come from the {@link ListAdapter} associated with this view.
+ * <p>Displays a vertically-scrollable collection of views, where each view is positioned
+ * immediatelybelow the previous view in the list.  For a more modern, flexible, and performant
+ * approach to displaying lists, use {@link android.support.v7.widget.RecyclerView}.</p>
  *
- * <p>See the <a href="{@docRoot}guide/topics/ui/layout/listview.html">List View</a>
- * guide.</p>
+ * <p>To display a list, you can include a list view in your layout XML file:</p>
+ *
+ * <pre>&lt;ListView
+ *      android:id="@+id/list_view"
+ *      android:layout_width="match_parent"
+ *      android:layout_height="match_parent" /&gt;</pre>
+ *
+ * <p>A list view is an <a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">
+ * adapter view</a> that does not know the details, such as type and contents, of the views it
+ * contains. Instead list view requests views on demand from a {@link ListAdapter} as needed,
+ * such as to display new views as the user scrolls up or down.</p>
+ *
+ * <p>In order to display items in the list, call {@link #setAdapter(ListAdapter adapter)}
+ * to associate an adapter with the list.  For a simple example, see the discussion of filling an
+ * adapter view with text in the
+ * <a href="{@docRoot}guide/topics/ui/declaring-layout.html#FillingTheLayout">
+ * Layouts</a> guide.</p>
+ *
+ * <p>To display a more custom view for each item in your dataset, implement a ListAdapter.
+ * For example, extend {@link BaseAdapter} and create and configure the view for each data item in
+ * {@code getView(...)}:</p>
+ *
+ *  <pre>private class MyAdapter extends BaseAdapter {
+ *
+ *      // override other abstract methods here
+ *
+ *      &#64;Override
+ *      public View getView(int position, View convertView, ViewGroup container) {
+ *          if (convertView == null) {
+ *              convertView = getLayoutInflater().inflate(R.layout.list_item, container, false);
+ *          }
+ *
+ *          ((TextView) convertView.findViewById(android.R.id.text1))
+ *                  .setText(getItem(position));
+ *          return convertView;
+ *      }
+ *  }</pre>
+ *
+ * <p class="note">ListView attempts to reuse view objects in order to improve performance and
+ * avoid a lag in response to user scrolls.  To take advantage of this feature, check if the
+ * {@code convertView} provided to {@code getView(...)} is null before creating or inflating a new
+ * view object.  See
+ * <a href="{@docRoot}training/improving-layouts/smooth-scrolling.html">
+ * Making ListView Scrolling Smooth</a> for more ways to ensure a smooth user experience.</p>
+ *
+ * <p>For a more complete example of creating a custom adapter, see the
+ * <a href="{@docRoot}samples/CustomChoiceList/index.html">
+ *     Custom Choice List</a> sample app.</p>
+ *
+ * <p>To specify an action when a user clicks or taps on a single list item, see
+ * <a href="{@docRoot}guide/topics/ui/declaring-layout.html#HandlingUserSelections">
+ *     Handling click events</a>.</p>
+ *
+ * <p>To learn how to populate a list view with a CursorAdapter, see the discussion of filling an
+ * adapter view with text in the
+ * <a href="{@docRoot}guide/topics/ui/declaring-layout.html#FillingTheLayout">
+ * Layouts</a> guide.
+ * See <a href="{@docRoot}guide/topics/ui/layout/listview.html">
+ *     Using a Loader</a>
+ * to learn how to avoid blocking the main thread when using a cursor.</p>
+ *
+ * <p class="note">Note, many examples use {@link android.app.ListActivity ListActivity}
+ * or {@link android.app.ListFragment ListFragment}
+ * to display a list view. Instead, favor the more flexible approach when writing your own app:
+ * use a more generic Activity subclass or Fragment subclass and add a list view to the layout
+ * or view hierarchy directly.  This approach gives you more direct control of the
+ * list view and adapter.</p>
  *
  * @attr ref android.R.styleable#ListView_entries
  * @attr ref android.R.styleable#ListView_divider
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index d046996..f1b19e17 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -427,6 +427,11 @@
     String8 clientName(packageUtf.c_str());
     sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
 
+    if (queue == NULL) {
+        jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");
+        return 0;
+    }
+
     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
     if (messageQueue == NULL) {
         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3e11368..3898cae 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2332,10 +2332,18 @@
         <attr name="importantForAutofill">
             <!-- Let the Android System use its heuristics to determine if the view is important for autofill. -->
             <flag name="auto" value="0" />
-            <!-- Hint the Android System that this view is important for autofill. -->
+            <!-- Hint the Android System that this view is important for autofill,
+                  and its children (if any) will be traversed.. -->
             <flag name="yes" value="0x1" />
-            <!-- Hint the Android System that this view is *not* important for autofill. -->
+            <!-- Hint the Android System that this view is *not* important for autofill,
+                  but its children (if any) will be traversed.. -->
             <flag name="no" value="0x2" />
+            <!-- Hint the Android System that this view is important for autofill,
+                 but its children (if any) will not be traversed. -->
+            <flag name="yesExcludeDescendants" value="0x4" />
+            <!-- Hint the Android System that this view is *not* important for autofill,
+                 and its children (if any) will not be traversed. -->
+            <flag name="noExcludeDescendants" value="0x8" />
         </attr>
 
         <!-- Boolean that controls whether a view can take focus while in touch mode.
diff --git a/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java b/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java
new file mode 100644
index 0000000..654474c
--- /dev/null
+++ b/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference;
+
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PreferenceIconSpaceTest {
+
+    private TestPreference mPreference;
+
+    @Mock
+    private ViewGroup mViewGroup;
+    @Mock
+    private ImageView mIconView;
+    @Mock
+    private View mImageFrame;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mViewGroup.findViewById(com.android.internal.R.id.icon_frame))
+                .thenReturn(mImageFrame);
+        when(mViewGroup.findViewById(com.android.internal.R.id.icon))
+                .thenReturn(mIconView);
+
+        mPreference = new TestPreference(InstrumentationRegistry.getTargetContext());
+    }
+
+    @Test
+    public void bindView_iconSpaceReserved_shouldReserveIconSpace() {
+        mPreference.setIconSpaceReserved(true);
+        mPreference.bindView(mViewGroup);
+
+        verify(mIconView).setVisibility(View.INVISIBLE);
+        verify(mImageFrame).setVisibility(View.INVISIBLE);
+    }
+
+    @Test
+    public void bindView_iconSpaceNotReserved_shouldNotReserveIconSpace() {
+        mPreference.setIconSpaceReserved(false);
+        mPreference.bindView(mViewGroup);
+
+        verify(mIconView).setVisibility(View.GONE);
+        verify(mImageFrame).setVisibility(View.GONE);
+    }
+
+    @Test
+    public void bindView_hasIcon_shouldDisplayIcon() {
+        mPreference.setIcon(new ColorDrawable(Color.BLACK));
+        mPreference.bindView(mViewGroup);
+
+        verify(mIconView).setVisibility(View.VISIBLE);
+        verify(mImageFrame).setVisibility(View.VISIBLE);
+    }
+
+    private static class TestPreference extends Preference {
+
+        public TestPreference(Context context) {
+            super(context);
+        }
+
+        public void bindView(View view) {
+            onBindView(view);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 38ab865..4586940 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -37,7 +37,8 @@
 
 /** Tests that ensure appropriate settings are backed up. */
 @RunWith(AndroidJUnit4.class)
-@Presubmit
+// TODO(b/37684646): Can re-enable pre-submit once test is fixed.
+//@Presubmit
 @SmallTest
 public class SettingsBackupTest {
 
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 42fd5d8..aedf6a7 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -27,7 +27,6 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.Context;
 import android.content.res.AssetManager;
 import android.graphics.FontListParser;
 import android.graphics.fonts.FontRequest;
@@ -99,8 +98,6 @@
     static Typeface[] sDefaults;
     private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache =
             new LongSparseArray<>(3);
-    @GuardedBy("sLock")
-    private static FontsContract sFontsContract;
 
     /**
      * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
@@ -221,7 +218,7 @@
                 // default font instead (nothing we can do now).
                 FontRequest request = new FontRequest(providerEntry.getAuthority(),
                         providerEntry.getPackage(), providerEntry.getQuery(), certs);
-                Typeface typeface = sFontsContract.getFontOrWarmUpCache(request);
+                Typeface typeface = FontsContract.getFontOrWarmUpCache(request);
                 return typeface == null ? DEFAULT : typeface;
             }
 
@@ -277,19 +274,6 @@
     }
 
     /**
-     * Set the application context so we can generate font requests from the provider. This should
-     * be called from ActivityThread when the application binds, as we preload fonts.
-     * @hide
-     */
-    public static void setApplicationContext(Context context) {
-        synchronized (sLock) {
-            if (sFontsContract == null) {
-                sFontsContract = new FontsContract(context);
-            }
-        }
-    }
-
-    /**
      * A builder class for creating new Typeface instance.
      *
      * <p>
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 5c64566..ea804d0 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -17,7 +17,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SdkConstant;
 import android.annotation.WorkerThread;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.app.Service;
@@ -199,12 +201,14 @@
      * {@link Build.VERSION_CODES#N_MR1} will only receive this broadcast if they register for it
      * at runtime.
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_STORAGE_CHANGED = "android.security.STORAGE_CHANGED";
 
     /**
      * Broadcast Action: Indicates the contents of the keychain has changed. Sent when a KeyChain
      * entry is added, modified or removed.
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_KEYCHAIN_CHANGED = "android.security.action.KEYCHAIN_CHANGED";
 
     /**
@@ -216,6 +220,7 @@
      * <li>A CA is added or removed from the trust store</li>
      * </ul>
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_TRUST_STORE_CHANGED =
             "android.security.action.TRUST_STORE_CHANGED";
 
@@ -223,6 +228,7 @@
      * Broadcast Action: Indicates that the access permissions for a private key have changed.
      *
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_KEY_ACCESS_CHANGED =
             "android.security.action.KEY_ACCESS_CHANGED";
 
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 052c018..55b74ed 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -28,6 +28,7 @@
 #include <ui/ColorSpace.h>
 
 #include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <SkBitmap.h>
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 71f9ba25..947adfc 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -19,8 +19,10 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SdkConstant;
 import android.annotation.StringDef;
 import android.annotation.SystemApi;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -90,6 +92,7 @@
      * @hide
      */
     @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_CHANNEL_BROWSABLE_REQUESTED =
             "android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED";
 
@@ -105,6 +108,7 @@
      *     integer.</li>
      * </ul>
      */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_REQUEST_CHANNEL_BROWSABLE =
             "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
 
@@ -119,6 +123,7 @@
      *     <li>{@link #EXTRA_PREVIEW_PROGRAM_ID}: the disabled preview program ID.</li>
      * </ul>
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED =
             "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
 
@@ -133,6 +138,7 @@
      *     <li>{@link #EXTRA_WATCH_NEXT_PROGRAM_ID}: the disabled "watch next" program ID.</li>
      * </ul>
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED =
             "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
 
@@ -146,6 +152,7 @@
      *     <li>{@link #EXTRA_WATCH_NEXT_PROGRAM_ID}: the ID of the new watch next program.</li>
      * </ul>
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT =
             "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
 
@@ -163,6 +170,7 @@
      *         <code>AndroidManifest.xml</code>.</li>
      * </ul>
      */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_INITIALIZE_PROGRAMS =
             "android.media.tv.action.INITIALIZE_PROGRAMS";
 
@@ -2989,6 +2997,8 @@
          */
         public static final String COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS =
                 "last_engagement_time_utc_millis";
+
+        private WatchNextPrograms() {}
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
index 8808988..f516d74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java
@@ -20,7 +20,9 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothProfile;
+import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
 
 import com.android.settingslib.bluetooth.BluetoothEventManager;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -31,10 +33,13 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.List;
 
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
 public class BluetoothControllerImplTest extends SysuiTestCase {
 
     private LocalBluetoothManager mMockBluetoothManager;
@@ -47,7 +52,7 @@
 
     @Before
     public void setup() throws Exception {
-        mTestableLooper = new TestableLooper();
+        mTestableLooper = TestableLooper.get(this);
         mMockBluetoothManager = mDependency.injectMockDependency(LocalBluetoothManager.class);
         mDevices = new ArrayList<>();
         mMockDeviceManager = mock(CachedBluetoothDeviceManager.class);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 45c2054..01ef01b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -411,6 +411,7 @@
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.PinnedStackWindowController;
 import com.android.server.wm.WindowManagerService;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -7818,10 +7819,15 @@
         try {
             synchronized(this) {
                 final ActivityStack stack = ActivityRecord.getStackLocked(token);
-                if (stack == null) {
+                if (stack == null || stack.mStackId != PINNED_STACK_ID) {
                     return false;
                 }
-                return stack.mStackId == PINNED_STACK_ID;
+
+                // If we are animating to fullscreen then we have already dispatched the PIP mode
+                // changed, so we should reflect that check here as well.
+                final PinnedStackWindowController windowController =
+                        ((PinnedActivityStack) stack).getWindowContainerController();
+                return !windowController.isAnimatingBoundsToFullscreen();
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -11255,9 +11261,13 @@
                     holder.provider = null;
                     return holder;
                 }
-                // Don't expose instant app providers
-                if (cpr.appInfo.isInstantApp()) {
-                    return null;
+                // Don't expose providers between normal apps and instant apps
+                try {
+                    if (AppGlobals.getPackageManager()
+                            .resolveContentProvider(name, 0 /*flags*/, userId) == null) {
+                        return null;
+                    }
+                } catch (RemoteException e) {
                 }
 
                 final long origId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index eeedab8..5f55411 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -62,6 +62,8 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.res.Configuration.EMPTY;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
 import static android.os.Build.VERSION_CODES.HONEYCOMB;
@@ -139,6 +141,7 @@
 import android.service.voice.IVoiceInteractionSession;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.MergedConfiguration;
 import android.util.Slog;
 import android.util.TimeUtils;
 import android.view.AppTransitionAnimationSpec;
@@ -240,13 +243,8 @@
     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
     long pauseTime;         // last time we started pausing the activity
     long launchTickTime;    // base time for launch tick messages
-    // TODO: Refactor mLastReportedConfiguration and mLastReportedOverrideConfiguration to use a
-    // MergedConfiguration object for clarity.
-    private Configuration mLastReportedConfiguration; // configuration activity was last running in
-    // Overridden configuration by the activity task
-    // WARNING: Reference points to {@link TaskRecord#getMergedOverrideConfig}, so its internal
-    // state should never be altered directly.
-    private Configuration mLastReportedOverrideConfiguration;
+    // Last configuration reported to the activity in the client process.
+    private MergedConfiguration mLastReportedConfiguration;
     private int mLastReportedDisplayId;
     CompatibilityInfo compat;// last used compatibility mode
     ActivityRecord resultTo; // who started this entry, so will get our reply
@@ -274,11 +272,13 @@
                                         // completed
     boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
     int configChangeFlags;  // which config values have changed
-    boolean keysPaused;     // has key dispatching been paused for it?
+    private boolean keysPaused;     // has key dispatching been paused for it?
     int launchMode;         // the launch mode activity attribute.
     boolean visible;        // does this activity's window need to be shown?
     boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
                                      // might hide this activity?
+    private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
+                                        // process that it is hidden.
     boolean sleeping;       // have we told the activity to sleep?
     boolean nowVisible;     // is this activity's window visible?
     boolean idle;           // has the activity gone idle?
@@ -344,10 +344,7 @@
     /**
      * Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
      */
-    private final Configuration mTmpConfig1 = new Configuration();
-    private final Configuration mTmpConfig2 = new Configuration();
-    private final Configuration mTmpConfig3 = new Configuration();
-    private final Point mTmpPoint = new Point();
+    private final Configuration mTmpConfig = new Configuration();
     private final Rect mTmpBounds = new Rect();
 
     private static String startingWindowStateToString(int state) {
@@ -398,10 +395,9 @@
                 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
-        pw.print(prefix); pw.print("mLastReportedConfiguration=");
-                pw.println(mLastReportedConfiguration);
-        pw.print(prefix); pw.print("mLastReportedOverrideConfiguration=");
-                pw.println(mLastReportedOverrideConfiguration);
+        pw.println(prefix + "mLastReportedConfigurations:");
+        mLastReportedConfiguration.dump(pw, prefix + " ");
+
         pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
         if (!getOverrideConfiguration().equals(EMPTY)) {
             pw.println(prefix + "OverrideConfiguration=" + getOverrideConfiguration());
@@ -523,6 +519,9 @@
                     else TimeUtils.formatDuration(lastVisibleTime, now, pw);
                     pw.println();
         }
+        if (mDeferHidingClient) {
+            pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
+        }
         if (deferRelaunchUntilPaused || configChangeFlags != 0) {
             pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused);
                     pw.print(" configChangeFlags=");
@@ -799,8 +798,7 @@
         resolvedType = _resolvedType;
         componentSpecified = _componentSpecified;
         rootVoiceInteraction = _rootVoiceInteraction;
-        mLastReportedConfiguration = new Configuration(_configuration);
-        mLastReportedOverrideConfiguration = new Configuration();
+        mLastReportedConfiguration = new MergedConfiguration(_configuration);
         resultTo = _resultTo;
         resultWho = _resultWho;
         requestCode = _reqCode;
@@ -1567,22 +1565,31 @@
         return mWindowContainerController.screenshotApplications(getDisplayId(), w, h, scale);
     }
 
-    void setVisibility(boolean visible) {
-        mWindowContainerController.setVisibility(visible, false /* deferHidingClient */);
+    void setDeferHidingClient(boolean deferHidingClient) {
+        if (mDeferHidingClient == deferHidingClient) {
+            return;
+        }
+        mDeferHidingClient = deferHidingClient;
+        if (!mDeferHidingClient && !visible) {
+            // Hiding the client is no longer deferred and the app isn't visible still, go ahead and
+            // update the visibility.
+            setVisibility(false);
+        }
     }
 
-    void setVisible(boolean newVisible) {
-        setVisible(newVisible, false /* deferHidingClient */);
+    void setVisibility(boolean visible) {
+        mWindowContainerController.setVisibility(visible, mDeferHidingClient);
     }
 
     // TODO: Look into merging with #setVisibility()
-    void setVisible(boolean newVisible, boolean deferHidingClient) {
+    void setVisible(boolean newVisible) {
         visible = newVisible;
+        mDeferHidingClient = !visible && mDeferHidingClient;
         if (!visible && mUpdateTaskThumbnailWhenHidden) {
             updateThumbnailLocked(screenshotActivityLocked(), null /* description */);
             mUpdateTaskThumbnailWhenHidden = false;
         }
-        mWindowContainerController.setVisibility(visible, deferHidingClient);
+        setVisibility(visible);
         final ArrayList<ActivityContainer> containers = mChildContainers;
         for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
             final ActivityContainer container = containers.get(containerNdx);
@@ -2195,15 +2202,15 @@
      * global configuration is sent to the client for this activity.
      */
     void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
-        mLastReportedConfiguration.setTo(config);
+        mLastReportedConfiguration.setGlobalConfiguration(config);
     }
 
     /**
-     * Set the last reported merged override configuration to the client. Should be called whenever
+     * Set the last reported configuration to the client. Should be called whenever
      * a new merged configuration is sent to the client for this activity.
      */
-    void setLastReportedMergedOverrideConfiguration(@NonNull Configuration config) {
-        mLastReportedOverrideConfiguration.setTo(config);
+    void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
+        mLastReportedConfiguration.setTo(config);
     }
 
     /** Call when override config was sent to the Window Manager to update internal records. */
@@ -2211,7 +2218,7 @@
     // we should only set this when we actually report to the activity which is what the method
     // setLastReportedMergedOverrideConfiguration() does. Investigate if this is really needed.
     void onOverrideConfigurationSent() {
-        mLastReportedOverrideConfiguration.setTo(getMergedOverrideConfiguration());
+        mLastReportedConfiguration.setOverrideConfiguration(getMergedOverrideConfiguration());
     }
 
     @Override
@@ -2227,18 +2234,20 @@
     }
 
     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
-    private boolean updateOverrideConfiguration() {
+    private void updateOverrideConfiguration() {
+        mTmpConfig.unset();
         computeBounds(mTmpBounds);
         if (mTmpBounds.equals(mBounds)) {
-            return false;
+            return;
         }
+
         mBounds.set(mTmpBounds);
         // Bounds changed...update configuration to match.
-        mTmpConfig1.unset();
-        task.computeOverrideConfiguration(mTmpConfig1, mBounds, null /* insetBounds */,
-                false /* overrideWidth */, false /* overrideHeight */);
-        onOverrideConfigurationChanged(mTmpConfig1);
-        return true;
+        if (!mBounds.isEmpty()) {
+            task.computeOverrideConfiguration(mTmpConfig, mBounds, null /* insetBounds */,
+                    false /* overrideWidth */, false /* overrideHeight */);
+        }
+        onOverrideConfigurationChanged(mTmpConfig);
     }
 
     /**
@@ -2266,12 +2275,12 @@
         int maxActivityHeight = containingAppHeight;
 
         if (containingAppWidth < containingAppHeight) {
-            // Width is the shorter side, so we use that to figure-out what the max. height should
-            // be given the aspect ratio.
+            // Width is the shorter side, so we use that to figure-out what the max. height
+            // should be given the aspect ratio.
             maxActivityHeight = (int) ((maxActivityWidth * maxAspectRatio) + 0.5f);
         } else {
-            // Height is the shorter side, so we use that to figure-out what the max. width should
-            // be given the aspect ratio.
+            // Height is the shorter side, so we use that to figure-out what the max. width
+            // should be given the aspect ratio.
             maxActivityWidth = (int) ((maxActivityHeight * maxAspectRatio) + 0.5f);
         }
 
@@ -2341,9 +2350,8 @@
         // nothing to do.  We test the full configuration instead of the global and merged override
         // configurations because there are cases (like moving a task to the pinned stack) where
         // the combine configurations are equal, but would otherwise differ in the override config
-        mTmpConfig1.setTo(mLastReportedConfiguration);
-        mTmpConfig1.updateFrom(mLastReportedOverrideConfiguration);
-        if (getConfiguration().equals(mTmpConfig1) && !forceNewConfig && !displayChanged) {
+        mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration());
+        if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                     "Configuration & display unchanged in " + this);
             return true;
@@ -2354,18 +2362,12 @@
 
         // Find changes between last reported merged configuration and the current one. This is used
         // to decide whether to relaunch an activity or just report a configuration change.
-        final int changes = getConfigurationChanges(mTmpConfig1);
-
-        // Preserve configuration used to generate this set of configuration changes.
-        mTmpConfig3.setTo(mTmpConfig1);
+        final int changes = getConfigurationChanges(mTmpConfig);
 
         // Update last reported values.
-        final Configuration newGlobalConfig = service.getGlobalConfiguration();
         final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
-        mTmpConfig1.setTo(mLastReportedConfiguration);
-        mTmpConfig2.setTo(mLastReportedOverrideConfiguration);
-        mLastReportedConfiguration.setTo(newGlobalConfig);
-        mLastReportedOverrideConfiguration.setTo(newMergedOverrideConfig);
+        mLastReportedConfiguration.setConfiguration(service.getGlobalConfiguration(),
+                newMergedOverrideConfig);
 
         if (changes == 0 && !forceNewConfig) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
@@ -2399,10 +2401,9 @@
                 "Checking to restart " + info.name + ": changed=0x"
                         + Integer.toHexString(changes) + ", handles=0x"
                         + Integer.toHexString(info.getRealConfigChanged())
-                        + ", newGlobalConfig=" + newGlobalConfig
-                        + ", newMergedOverrideConfig=" + newMergedOverrideConfig);
+                        + ", mLastReportedConfiguration=" + mLastReportedConfiguration);
 
-        if (shouldRelaunchLocked(changes, mTmpConfig3) || forceNewConfig) {
+        if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
             // Aha, the activity isn't handling the change, so DIE DIE DIE.
             configChangeFlags |= changes;
             startFreezingScreenLocked(app, globalChanges);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 1e8a587..728a3b9 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1406,10 +1406,10 @@
                     prev.state = STOPPING;
                 } else if ((!prev.visible && !hasVisibleBehindActivity())
                         || mService.isSleepingOrShuttingDownLocked()) {
+                    // Clear out any deferred client hide we might currently have.
+                    prev.setDeferHidingClient(false);
                     // If we were visible then resumeTopActivities will release resources before
-                    // stopping. Also, set visibility to false to flush any client hide that might have
-                    // been deferred.
-                    prev.setVisibility(false);
+                    // stopping.
                     addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
                 }
             } else {
@@ -2030,7 +2030,8 @@
             // or stopping. This gives it a chance to enter Pip in onPause().
             final boolean deferHidingClient = canEnterPictureInPicture
                     && r.state != STOPPING && r.state != STOPPED;
-            r.setVisible(false, deferHidingClient);
+            r.setDeferHidingClient(deferHidingClient);
+            r.setVisible(false);
 
             switch (r.state) {
                 case STOPPING:
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index fb8c161..bff3ce3 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -162,6 +162,7 @@
 import android.util.ArraySet;
 import android.util.EventLog;
 import android.util.IntArray;
+import android.util.MergedConfiguration;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
@@ -1443,17 +1444,16 @@
             // a Binder interface which would create a new Configuration. Consequently we have to
             // always create a new Configuration here.
 
-            final Configuration globalConfiguration =
-                new Configuration(mService.getGlobalConfiguration());
-            r.setLastReportedGlobalConfiguration(globalConfiguration);
-            final Configuration mergedOverrideConfiguration =
-                new Configuration(r.getMergedOverrideConfiguration());
-            r.setLastReportedMergedOverrideConfiguration(mergedOverrideConfiguration);
+            final MergedConfiguration mergedConfiguration = new MergedConfiguration(
+                    mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
+            r.setLastReportedConfiguration(mergedConfiguration);
 
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                     System.identityHashCode(r), r.info,
-                    globalConfiguration,
-                    mergedOverrideConfiguration, r.compat,
+                    // TODO: Have this take the merged configuration instead of separate global and
+                    // override configs.
+                    mergedConfiguration.getGlobalConfiguration(),
+                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                     r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                     r.persistentState, results, newIntents, !andResume,
                     mService.isNextTransitionForward(), profilerInfo);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 349180f..d08298b 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -1180,7 +1180,7 @@
                 skip = true;
             }
             if (!skip && r.callerInstantApp
-                    && (info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0
+                    && (info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0
                     && r.callingUid != info.activityInfo.applicationInfo.uid) {
                 Slog.w(TAG, "Instant App Denial: receiving "
                         + r.intent
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index faa9934..7bbb1fe 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4074,14 +4074,26 @@
      * action and a {@code android.intent.category.BROWSABLE} category</li>
      * </ul>
      */
+    int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid) {
+        return updateFlagsForResolve(flags, userId, intent, callingUid,
+                false /*includeInstantApps*/, false /*onlyExposedExplicitly*/);
+    }
     int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
             boolean includeInstantApps) {
+        return updateFlagsForResolve(flags, userId, intent, callingUid,
+                includeInstantApps, false /*onlyExposedExplicitly*/);
+    }
+    int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
+            boolean includeInstantApps, boolean onlyExposedExplicitly) {
         // Safe mode means we shouldn't match any third-party components
         if (mSafeMode) {
             flags |= PackageManager.MATCH_SYSTEM_ONLY;
         }
         if (getInstantAppPackageName(callingUid) != null) {
             // But, ephemeral apps see both ephemeral and exposed, non-ephemeral components
+            if (onlyExposedExplicitly) {
+                flags |= PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY;
+            }
             flags |= PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
             flags |= PackageManager.MATCH_INSTANT;
         } else {
@@ -4098,7 +4110,8 @@
                     || isSpecialProcess
                     || mContext.checkCallingOrSelfPermission(
                             android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED;
-            flags &= ~PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
+            flags &= ~(PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY
+                    | PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY);
             if (!allowMatchInstant) {
                 flags &= ~PackageManager.MATCH_INSTANT;
             }
@@ -5659,19 +5672,19 @@
     }
 
     private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
-            int flags, int userId, boolean includeInstantApps) {
+            int flags, int userId, boolean resolveForStart) {
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
 
             if (!sUserManager.exists(userId)) return null;
             final int callingUid = Binder.getCallingUid();
-            flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+            flags = updateFlagsForResolve(flags, userId, intent, callingUid, resolveForStart);
             enforceCrossUserPermission(callingUid, userId,
                     false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
 
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
             final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
-                    flags, userId, includeInstantApps);
+                    flags, userId, resolveForStart);
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             final ResolveInfo bestChoice =
@@ -6208,14 +6221,14 @@
     }
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
-            String resolvedType, int flags, int userId, boolean includeInstantApps) {
+            String resolvedType, int flags, int userId, boolean resolveForStart) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
         final int callingUid = Binder.getCallingUid();
         final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
         enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */,
                 "query intent activities");
+        final String pkgName = intent.getPackage();
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -6224,6 +6237,8 @@
             }
         }
 
+        flags = updateFlagsForResolve(flags, userId, intent, callingUid, resolveForStart,
+                comp != null || pkgName != null /*onlyExposedExplicitly*/);
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
             final ActivityInfo ai = getActivityInfo(comp, flags, userId);
@@ -6236,6 +6251,8 @@
                         (flags & PackageManager.MATCH_INSTANT) != 0;
                 final boolean matchVisibleToInstantAppOnly =
                         (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+                final boolean matchExplicitlyVisibleOnly =
+                        (flags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
                 final boolean isCallerInstantApp =
                         instantAppPkgName != null;
                 final boolean isTargetSameInstantApp =
@@ -6243,8 +6260,14 @@
                 final boolean isTargetInstantApp =
                         (ai.applicationInfo.privateFlags
                                 & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
+                final boolean isTargetVisibleToInstantApp =
+                        (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
+                final boolean isTargetExplicitlyVisibleToInstantApp =
+                        isTargetVisibleToInstantApp
+                        && (ai.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
                 final boolean isTargetHiddenFromInstantApp =
-                        (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
+                        !isTargetVisibleToInstantApp
+                        || (matchExplicitlyVisibleOnly && !isTargetExplicitlyVisibleToInstantApp);
                 final boolean blockResolution =
                         !isTargetSameInstantApp
                         && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
@@ -6263,7 +6286,6 @@
         boolean sortResult = false;
         boolean addEphemeral = false;
         List<ResolveInfo> result;
-        final String pkgName = intent.getPackage();
         final boolean ephemeralDisabled = isEphemeralDisabled();
         synchronized (mPackages) {
             if (pkgName == null) {
@@ -6529,7 +6551,7 @@
             }
             // allow activities that have been explicitly exposed to ephemeral apps
             if (!isEphemeralApp
-                    && ((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
+                    && ((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0)) {
                 continue;
             }
             resolveInfos.remove(i);
@@ -7069,16 +7091,16 @@
     @Override
     public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
         final int callingUid = Binder.getCallingUid();
-        return resolveServiceInternal(
-                intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/);
+        return resolveServiceInternal(intent, resolvedType, flags, userId, callingUid);
     }
 
     private ResolveInfo resolveServiceInternal(Intent intent, String resolvedType, int flags,
-            int userId, int callingUid, boolean includeInstantApps) {
+            int userId, int callingUid) {
         if (!sUserManager.exists(userId)) return null;
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+        flags = updateFlagsForResolve(
+                flags, userId, intent, callingUid, false /*includeInstantApps*/);
         List<ResolveInfo> query = queryIntentServicesInternal(
-                intent, resolvedType, flags, userId, callingUid, includeInstantApps);
+                intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/);
         if (query != null) {
             if (query.size() >= 1) {
                 // If there is more than one service with the same priority,
@@ -7130,7 +7152,7 @@
                         (si.applicationInfo.privateFlags
                                 & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
                 final boolean isTargetHiddenFromInstantApp =
-                        (si.flags & ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
+                        (si.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0;
                 final boolean blockResolution =
                         !isTargetSameInstantApp
                         && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
@@ -7202,7 +7224,7 @@
             }
             // allow services that have been explicitly exposed to ephemeral apps
             if (!isEphemeralApp
-                    && ((info.serviceInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
+                    && ((info.serviceInfo.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0)) {
                 continue;
             }
             resolveInfos.remove(i);
@@ -7251,7 +7273,7 @@
                         (pi.applicationInfo.privateFlags
                                 & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
                 final boolean isTargetHiddenFromInstantApp =
-                        (pi.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
+                        (pi.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0;
                 final boolean blockResolution =
                         !isTargetSameInstantApp
                         && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
@@ -7323,7 +7345,7 @@
             }
             // allow providers that have been explicitly exposed to instant applications
             if (!isEphemeralApp
-                    && ((info.providerInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
+                    && ((info.providerInfo.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0)) {
                 continue;
             }
             resolveInfos.remove(i);
@@ -7684,7 +7706,7 @@
                 // instant application; filter out non-exposed provider
                 if (instantAppPkgName != null
                         && !isInstantApp
-                        && (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0) {
+                        && (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0) {
                     return null;
                 }
                 // provider not enabled
@@ -12430,16 +12452,21 @@
             if (ai == null) {
                 return null;
             }
+            final boolean matchExplicitlyVisibleOnly =
+                    (mFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
             final boolean matchVisibleToInstantApp =
                     (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            final boolean componentVisible =
+                    matchVisibleToInstantApp
+                    && info.isVisibleToInstantApp()
+                    && (!matchExplicitlyVisibleOnly || info.isExplicitlyVisibleToInstantApp());
+            final boolean matchInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
             // throw out filters that aren't visible to ephemeral apps
-            if (matchVisibleToInstantApp
-                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+            if (matchVisibleToInstantApp && !(componentVisible || userState.instantApp)) {
                 return null;
             }
-            // throw out ephemeral filters if we're not explicitly requesting them
-            if (!isInstantApp && userState.instantApp) {
+            // throw out instant app filters if we're not explicitly requesting them
+            if (!matchInstantApp && userState.instantApp) {
                 return null;
             }
             // throw out instant app filters if updates are available; will trigger
@@ -14118,9 +14145,6 @@
         synchronized (mPackages) {
             boolean result = mSettings.setDefaultBrowserPackageNameLPw(packageName, userId);
             if (packageName != null) {
-                result |= updateIntentVerificationStatus(packageName,
-                        PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS,
-                        userId);
                 mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultBrowserLPr(
                         packageName, userId);
             }
@@ -18589,6 +18613,7 @@
             destroyAppDataLIF(pkg, userId,
                     StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
             destroyAppProfilesLIF(pkg, userId);
+            clearDefaultBrowserIfNeededForUser(ps.name, userId);
             removeKeystoreDataIfNeeded(nextUserId, ps.appId);
             schedulePackageCleaning(ps.name, nextUserId, false);
             synchronized (mPackages) {
@@ -19310,12 +19335,18 @@
         }
     }
 
+    /** Clears state for all users, and touches intent filter verification policy */
     void clearDefaultBrowserIfNeeded(String packageName) {
         for (int oneUserId : sUserManager.getUserIds()) {
-            String defaultBrowserPackageName = getDefaultBrowserPackageName(oneUserId);
-            if (TextUtils.isEmpty(defaultBrowserPackageName)) continue;
+            clearDefaultBrowserIfNeededForUser(packageName, oneUserId);
+        }
+    }
+
+    private void clearDefaultBrowserIfNeededForUser(String packageName, int userId) {
+        final String defaultBrowserPackageName = getDefaultBrowserPackageName(userId);
+        if (!TextUtils.isEmpty(defaultBrowserPackageName)) {
             if (packageName.equals(defaultBrowserPackageName)) {
-                setDefaultBrowserPackageName(null, oneUserId);
+                setDefaultBrowserPackageName(null, userId);
             }
         }
     }
@@ -23517,14 +23548,13 @@
         public ResolveInfo resolveIntent(Intent intent, String resolvedType,
                 int flags, int userId) {
             return resolveIntentInternal(
-                    intent, resolvedType, flags, userId, true /*includeInstantApps*/);
+                    intent, resolvedType, flags, userId, true /*resolveForStart*/);
         }
 
         @Override
         public ResolveInfo resolveService(Intent intent, String resolvedType,
                 int flags, int userId, int callingUid) {
-            return resolveServiceInternal(
-                    intent, resolvedType, flags, userId, callingUid, true /*includeInstantApps*/);
+            return resolveServiceInternal(intent, resolvedType, flags, userId, callingUid);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 554deae..cea031e 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1386,7 +1386,11 @@
         if (userId == UserHandle.USER_ALL) {
             return false;
         }
-        mDefaultBrowserApp.put(userId, packageName);
+        if (packageName != null) {
+            mDefaultBrowserApp.put(userId, packageName);
+        } else {
+            mDefaultBrowserApp.remove(userId);
+        }
         writePackageRestrictionsLPr(userId);
         return true;
     }
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index 364bf28..ebb9450 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -193,6 +193,7 @@
                 0
                         | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                         | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                 ,
                 PixelFormat.TRANSLUCENT);
         lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index a1b1cd0..60b136f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -674,7 +674,7 @@
                 if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) {
                     wallpaperDestroyed = true;
                 }
-                win.destroyOrSaveSurface();
+                win.destroyOrSaveSurfaceUnchecked();
             } while (i > 0);
             mService.mDestroySurface.clear();
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9d6e033..6cde53a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2141,7 +2141,12 @@
             if (mInputMethodWindow == win) {
                 setInputMethodWindowLocked(null);
             }
-            win.destroyOrSaveSurface();
+            boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : false;
+            // We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces
+            // will later actually destroy the surface if we do not do so here. Normally we leave
+            // this to the exit animation.
+            win.mDestroying = true;
+            win.destroySurface(false, stopped);
         }
         // TODO(multidisplay): Magnification is supported only for the default display.
         if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9bdcc36..67516c1 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2710,7 +2710,7 @@
                     + " win.mWindowRemovalAllowed=" + mWindowRemovalAllowed
                     + " win.mRemoveOnExit=" + mRemoveOnExit);
             if (!cleanupOnResume || mRemoveOnExit) {
-                destroyOrSaveSurface();
+                destroyOrSaveSurfaceUnchecked();
             }
             if (mRemoveOnExit) {
                 removeImmediately();
@@ -2725,7 +2725,10 @@
         return destroyedSomething;
     }
 
-    void destroyOrSaveSurface() {
+    // Destroy or save the application surface without checking
+    // various indicators of whether the client has released the surface.
+    // This is in general unsafe, and most callers should use {@link #destroySurface}
+    void destroyOrSaveSurfaceUnchecked() {
         mSurfaceSaved = shouldSaveSurface();
         if (mSurfaceSaved) {
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index b945cf15..2236b59 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -341,7 +341,7 @@
             mAnimation.cancel();
             mAnimation = null;
             mLocalAnimating = false;
-            mWin.destroyOrSaveSurface();
+            mWin.destroyOrSaveSurfaceUnchecked();
         }
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
index 97fa9d55..c7b8f02 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.devicepolicy;
 
+import android.Manifest.permission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.admin.DevicePolicyManager;
@@ -115,10 +116,12 @@
                 return null;
             }
             final ServiceInfo si = list.get(0).serviceInfo;
-            if (si.exported) {
-                Log.e(TAG, "DeviceAdminService must not be exported: '"
+
+            if (!permission.BIND_DEVICE_ADMIN.equals(si.permission)) {
+                Log.e(TAG, "DeviceAdminService "
                         + si.getComponentName().flattenToShortString()
-                        + "' will be ignored.");
+                        + " must be protected with " + permission.BIND_DEVICE_ADMIN
+                        + ".");
                 return null;
             }
             return si;
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 92534a1..d057eb5 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -53,9 +53,10 @@
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
-import android.support.test.annotation.UiThreadTest;
 import android.support.test.InstrumentationRegistry;
+import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -63,6 +64,7 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
@@ -70,6 +72,8 @@
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
 
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
 public class NotificationManagerServiceTest {
     private static final long WAIT_FOR_IDLE_TIMEOUT = 2;
     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
@@ -109,7 +113,6 @@
     }
 
     @Before
-    @UiThreadTest
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mNotificationManagerService = new TestableNotificationManagerService(mContext);
@@ -124,7 +127,7 @@
         final LightsManager mockLightsManager = mock(LightsManager.class);
         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
         // Use this testable looper.
-        mTestableLooper = new TestableLooper(false);
+        mTestableLooper = TestableLooper.get(this);
 
         mListener = mNotificationListeners.new ManagedServiceInfo(
                 null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
@@ -165,7 +168,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCreateNotificationChannels_SingleChannel() throws Exception {
         final NotificationChannel channel =
                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
@@ -177,7 +179,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
         try {
             mBinderService.createNotificationChannels("test_pkg",
@@ -189,7 +190,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCreateNotificationChannels_TwoChannels() throws Exception {
         final NotificationChannel channel1 =
                 new NotificationChannel("id1", "name", NotificationManager.IMPORTANCE_DEFAULT);
@@ -202,7 +202,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
             throws Exception {
         final NotificationChannel channel =
@@ -221,7 +220,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
             throws Exception {
         final NotificationChannel channel1 =
@@ -236,7 +234,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBlockedNotifications_suspended() throws Exception {
         NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
@@ -249,7 +246,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBlockedNotifications_blockedChannel() throws Exception {
         NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
@@ -263,7 +259,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testBlockedNotifications_blockedApp() throws Exception {
         NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
@@ -277,7 +272,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
                 generateNotificationRecord(null).getNotification(), 0);
@@ -288,7 +282,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
                 generateNotificationRecord(null).getNotification(), 0);
@@ -300,7 +293,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
                 generateNotificationRecord(null).getNotification(), 0);
@@ -315,7 +307,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
@@ -328,7 +319,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
@@ -341,7 +331,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
@@ -355,7 +344,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
@@ -369,7 +357,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
@@ -382,7 +369,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
@@ -396,7 +382,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
@@ -411,7 +396,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testTvExtenderChannelOverride_onTv() throws Exception {
         mNotificationManagerService.setIsTelevision(true);
         mNotificationManagerService.setRankingHelper(mRankingHelper);
@@ -427,7 +411,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testTvExtenderChannelOverride_notOnTv() throws Exception {
         mNotificationManagerService.setIsTelevision(false);
         mNotificationManagerService.setRankingHelper(mRankingHelper);
@@ -443,7 +426,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCreateChannelNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
@@ -469,7 +451,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testCreateChannelGroupNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
@@ -490,7 +471,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUpdateChannelNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
@@ -509,7 +489,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testDeleteChannelNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
@@ -526,7 +505,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testDeleteChannelGroupNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
@@ -543,7 +521,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
@@ -561,7 +538,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
@@ -583,7 +559,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
@@ -609,7 +584,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testGetNotificationChannelFromPrivilegedListener_success() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
@@ -624,7 +598,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testGetNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
@@ -643,7 +616,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
@@ -666,7 +638,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
@@ -680,7 +651,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
@@ -698,7 +668,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
@@ -719,7 +688,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHasCompanionDevice_failure() throws Exception {
         when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
                 new IllegalArgumentException());
@@ -727,7 +695,6 @@
     }
 
     @Test
-    @UiThreadTest
     public void testHasCompanionDevice_noService() throws Exception {
         mNotificationManagerService = new TestableNotificationManagerService(mContext);
 
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 3f6f8ec..bb453a9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -843,18 +843,20 @@
 
                     updateUsbNotification();
                     updateAdbNotification();
+                    if (mBootCompleted) {
+                        Slog.i(TAG, "update state " + mConnected + " " + mConfigured);
+                        updateUsbStateBroadcastIfNeeded(false);
+                    }
                     if (UsbManager.containsFunction(mCurrentFunctions,
                             UsbManager.USB_FUNCTION_ACCESSORY)) {
                         updateCurrentAccessory();
                     }
                     if (mBootCompleted) {
-                        Slog.i(TAG, "update state " + mConnected + " " + mConfigured);
                         if (!mConnected) {
                             // restore defaults when USB is disconnected
                             Slog.i(TAG, "Disconnect, setting usb functions to null");
                             setEnabledFunctions(null, false, false);
                         }
-                        updateUsbStateBroadcastIfNeeded(false);
                         updateUsbFunctions();
                     } else {
                         mPendingBootBroadcast = true;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3aeaa29..b8e24f0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -323,9 +323,6 @@
      * a String.
      *
      * <p class="note">
-     * Requires the READ_PHONE_STATE permission.
-     *
-     * <p class="note">
      * This was a {@link android.content.Context#sendStickyBroadcast sticky}
      * broadcast in version 1.0, but it is no longer sticky.
      * Instead, use {@link #getCallState} to synchronously query the current call state.
@@ -335,6 +332,7 @@
      * @see #getCallState
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public static final String ACTION_PHONE_STATE_CHANGED =
             "android.intent.action.PHONE_STATE";
 
@@ -939,10 +937,8 @@
      * Returns the software version number for the device, for example,
      * the IMEI/SV for GSM phones. Return null if the software version is
      * not available.
-     *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getDeviceSoftwareVersion() {
         return getDeviceSoftwareVersion(getSlotIndex());
     }
@@ -952,12 +948,10 @@
      * the IMEI/SV for GSM phones. Return null if the software version is
      * not available.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *
      * @param slotIndex of which deviceID is returned
      */
     /** {@hide} */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getDeviceSoftwareVersion(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
@@ -975,13 +969,11 @@
      * Returns the unique device ID, for example, the IMEI for GSM and the MEID
      * or ESN for CDMA phones. Return null if device ID is not available.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *
      * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
      * MEID for CDMA.
      */
     @Deprecated
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getDeviceId() {
         try {
             ITelephony telephony = getITelephony();
@@ -999,15 +991,13 @@
      * Returns the unique device ID of a subscription, for example, the IMEI for
      * GSM and the MEID for CDMA phones. Return null if device ID is not available.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *
      * @param slotIndex of which deviceID is returned
      *
      * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
      * MEID for CDMA.
      */
     @Deprecated
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getDeviceId(int slotIndex) {
         // FIXME this assumes phoneId == slotIndex
         try {
@@ -1025,10 +1015,8 @@
     /**
      * Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
      * available.
-     *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getImei() {
         return getImei(getSlotIndex());
     }
@@ -1037,11 +1025,9 @@
      * Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
      * available.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *
      * @param slotIndex of which IMEI is returned
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getImei(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
@@ -1057,10 +1043,8 @@
 
     /**
      * Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
-     *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getMeid() {
         return getMeid(getSlotIndex());
     }
@@ -1068,11 +1052,9 @@
     /**
      * Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *
      * @param slotIndex of which MEID is returned
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getMeid(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
@@ -1128,13 +1110,13 @@
      *<p>
      * @return Current location of the device or null if not available.
      *
-     * <p>Requires Permission:
-     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
-     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION}.
-     *
      * @deprecated use {@link #getAllCellInfo} instead, which returns a superset of this API.
      */
     @Deprecated
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.ACCESS_COARSE_LOCATION,
+            android.Manifest.permission.ACCESS_FINE_LOCATION
+    })
     public CellLocation getCellLocation() {
         try {
             ITelephony telephony = getITelephony();
@@ -1166,11 +1148,9 @@
      * Enables location update notifications.  {@link PhoneStateListener#onCellLocationChanged
      * PhoneStateListener.onCellLocationChanged} will be called on location updates.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES
-     * CONTROL_LOCATION_UPDATES}
-     *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.CONTROL_LOCATION_UPDATES)
     public void enableLocationUpdates() {
         enableLocationUpdates(getSubId());
     }
@@ -1180,12 +1160,10 @@
      * {@link PhoneStateListener#onCellLocationChanged
      * PhoneStateListener.onCellLocationChanged} will be called on location updates.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES
-     * CONTROL_LOCATION_UPDATES}
-     *
      * @param subId for which the location updates are enabled
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.CONTROL_LOCATION_UPDATES)
     public void enableLocationUpdates(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -1200,11 +1178,9 @@
      * Disables location update notifications.  {@link PhoneStateListener#onCellLocationChanged
      * PhoneStateListener.onCellLocationChanged} will be called on location updates.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES
-     * CONTROL_LOCATION_UPDATES}
-     *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.CONTROL_LOCATION_UPDATES)
     public void disableLocationUpdates() {
         disableLocationUpdates(getSubId());
     }
@@ -1223,15 +1199,13 @@
     /**
      * Returns the neighboring cell information of the device.
      *
-     * <p>Requires Permission:
-     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
-     *
      * @return List of NeighboringCellInfo or null if info unavailable.
      *
      * @deprecated Use {@link #getAllCellInfo} which returns a superset of the information
      *             from NeighboringCellInfo.
      */
     @Deprecated
+    @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
     public List<NeighboringCellInfo> getNeighboringCellInfo() {
         try {
             ITelephony telephony = getITelephony();
@@ -1587,14 +1561,12 @@
      * invalid subscription ID is pinned to the TelephonyManager, the returned config will contain
      * default values.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
-     * READ_PHONE_STATE}
-     *
      * @see CarrierConfigManager#getConfigForSubId(int)
      * @see #createForSubscriptionId(int)
      * @see #createForPhoneAccountHandle(PhoneAccountHandle)
      */
     @WorkerThread
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public PersistableBundle getCarrierConfig() {
         CarrierConfigManager carrierConfigManager = mContext
                 .getSystemService(CarrierConfigManager.class);
@@ -1754,11 +1726,9 @@
      * @see #NETWORK_TYPE_EHRPD
      * @see #NETWORK_TYPE_HSPAP
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
    public int getNetworkType(int subId) {
        try {
            ITelephony telephony = getITelephony();
@@ -1784,10 +1754,6 @@
      * If this object has been created with {@link #createForSubscriptionId}, applies to the given
      * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *
      * @return the network type
      *
      * @see #NETWORK_TYPE_UNKNOWN
@@ -1807,6 +1773,7 @@
      * @see #NETWORK_TYPE_EHRPD
      * @see #NETWORK_TYPE_HSPAP
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getDataNetworkType() {
         return getDataNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
     }
@@ -1817,12 +1784,9 @@
      * @return the network type
      *
      * @param subId for which network type is returned
-     *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getDataNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -1843,23 +1807,17 @@
 
     /**
      * Returns the NETWORK_TYPE_xxxx for voice
-     *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getVoiceNetworkType() {
         return getVoiceNetworkType(getSubId());
     }
 
     /**
      * Returns the NETWORK_TYPE_xxxx for voice for a subId
-     *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getVoiceNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -2261,10 +2219,8 @@
     /**
      * Returns the serial number of the SIM, if applicable. Return null if it is
      * unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getSimSerialNumber() {
          return getSimSerialNumber(getSubId());
     }
@@ -2274,10 +2230,9 @@
      * unavailable.
      * <p>
      * @param subId for which Sim Serial number is returned
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getSimSerialNumber(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -2300,12 +2255,9 @@
      * @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}
      * or {@link PhoneConstants#LTE_ON_CDMA_TRUE}
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getLteOnCdmaMode() {
         return getLteOnCdmaMode(getSubId());
     }
@@ -2318,12 +2270,9 @@
      * @param subId for which radio is LTE on CDMA is returned
      * @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}
      * or {@link PhoneConstants#LTE_ON_CDMA_TRUE}
-     *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getLteOnCdmaMode(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -2348,10 +2297,8 @@
     /**
      * Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
      * Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getSubscriberId() {
         return getSubscriberId(getSubId());
     }
@@ -2360,13 +2307,11 @@
      * Returns the unique subscriber ID, for example, the IMSI for a GSM phone
      * for a subscription.
      * Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      *
      * @param subId whose subscriber id is returned
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getSubscriberId(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -2384,10 +2329,8 @@
     /**
      * Returns the Group Identifier Level1 for a GSM phone.
      * Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getGroupIdLevel1() {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -2405,13 +2348,11 @@
     /**
      * Returns the Group Identifier Level1 for a GSM phone for a particular subscription.
      * Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      *
      * @param subId whose subscriber id is returned
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getGroupIdLevel1(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -2430,15 +2371,13 @@
      * Returns the phone number string for line 1, for example, the MSISDN
      * for a GSM phone. Return null if it is unavailable.
      * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *   OR
-     *   {@link android.Manifest.permission#READ_SMS}
-     *   OR
-     *   {@link android.Manifest.permission#READ_PHONE_NUMBERS}
-     * <p>
      * The default SMS app can also use this.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.READ_SMS,
+            android.Manifest.permission.READ_PHONE_NUMBERS
+    })
     public String getLine1Number() {
         return getLine1Number(getSubId());
     }
@@ -2447,18 +2386,16 @@
      * Returns the phone number string for line 1, for example, the MSISDN
      * for a GSM phone for a particular subscription. Return null if it is unavailable.
      * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *   OR
-     *   {@link android.Manifest.permission#READ_SMS}
-     *   OR
-     *   {@link android.Manifest.permission#READ_PHONE_NUMBERS}
-     * <p>
      * The default SMS app can also use this.
      *
      * @param subId whose phone number for line 1 is returned
      * @hide
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.READ_SMS,
+            android.Manifest.permission.READ_PHONE_NUMBERS
+    })
     public String getLine1Number(int subId) {
         String number = null;
         try {
@@ -2530,12 +2467,10 @@
     /**
      * Returns the alphabetic identifier associated with the line 1 number.
      * Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      * nobody seems to call this.
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getLine1AlphaTag() {
         return getLine1AlphaTag(getSubId());
     }
@@ -2544,13 +2479,11 @@
      * Returns the alphabetic identifier associated with the line 1 number
      * for a subscription.
      * Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @param subId whose alphabetic identifier associated with line 1 is returned
      * nobody seems to call this.
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getLine1AlphaTag(int subId) {
         String alphaTag = null;
         try {
@@ -2599,12 +2532,10 @@
     /**
      * Returns the MSISDN string.
      * for a GSM phone. Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getMsisdn() {
         return getMsisdn(getSubId());
     }
@@ -2612,13 +2543,11 @@
     /**
      * Returns the MSISDN string.
      * for a GSM phone. Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      *
      * @param subId for which msisdn is returned
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getMsisdn(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -2635,10 +2564,8 @@
 
     /**
      * Returns the voice mail number. Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getVoiceMailNumber() {
         return getVoiceMailNumber(getSubId());
     }
@@ -2646,12 +2573,10 @@
     /**
      * Returns the voice mail number for a subscription.
      * Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @param subId whose voice mail number is returned
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getVoiceMailNumber(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -2668,25 +2593,21 @@
 
     /**
      * Returns the complete voice mail number. Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#CALL_PRIVILEGED CALL_PRIVILEGED}
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.CALL_PRIVILEGED)
     public String getCompleteVoiceMailNumber() {
         return getCompleteVoiceMailNumber(getSubId());
     }
 
     /**
      * Returns the complete voice mail number. Return null if it is unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#CALL_PRIVILEGED CALL_PRIVILEGED}
      *
      * @param subId
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.CALL_PRIVILEGED)
     public String getCompleteVoiceMailNumber(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -2757,9 +2678,6 @@
     /**
      * Returns whether the visual voicemail client is enabled.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     *
      * @param phoneAccountHandle the phone account to check for.
      * @return {@code true} when the visual voicemail client is enabled for this client
      * @hide
@@ -2767,6 +2685,7 @@
      * be implemented instead.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
         return false;
     }
@@ -2804,14 +2723,12 @@
      * to the TelephonyManager. Returns {@code null} when there is no package responsible for
      * processing visual voicemail for the subscription.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
-     * READ_PHONE_STATE}
-     *
      * @see #createForSubscriptionId(int)
      * @see #createForPhoneAccountHandle(PhoneAccountHandle)
      * @see VisualVoicemailService
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getVisualVoicemailPackageName() {
         try {
             ITelephony telephony = getITelephony();
@@ -2971,9 +2888,6 @@
     /**
      * Send a visual voicemail SMS. The IPC caller must be the current default dialer.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#SEND_SMS SEND_SMS}
-     *
      * @param phoneAccountHandle The account to send the SMS with.
      * @param number The destination number.
      * @param port The destination port for data SMS, or 0 for text SMS.
@@ -2985,6 +2899,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.SEND_SMS)
     public void sendVisualVoicemailSmsForSubscriber(int subId, String number, int port,
             String text, PendingIntent sentIntent) {
         try {
@@ -3089,9 +3004,6 @@
     /**
      * Returns the voice activation state for the given subscriber.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE}
-     *
      * @param subId The subscription id.
      *
      * @return voiceActivationState for the given subscriber
@@ -3101,6 +3013,7 @@
      * @see #SIM_ACTIVATION_STATE_DEACTIVATED
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getVoiceActivationState(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -3115,9 +3028,6 @@
     /**
      * Returns the data activation state for the given subscriber.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE}
-     *
      * @param subId The subscription id.
      *
      * @return dataActivationState for the given subscriber
@@ -3128,6 +3038,7 @@
      * @see #SIM_ACTIVATION_STATE_RESTRICTED
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getDataActivationState(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -3142,23 +3053,19 @@
     /**
      * Returns the voice mail count. Return 0 if unavailable, -1 if there are unread voice messages
      * but the count is unknown.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getVoiceMessageCount() {
         return getVoiceMessageCount(getSubId());
     }
 
     /**
      * Returns the voice mail count for a subscription. Return 0 if unavailable.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @param subId whose voice message count is returned
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getVoiceMessageCount(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -3176,10 +3083,8 @@
     /**
      * Retrieves the alphabetic identifier associated with the voice
      * mail number.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getVoiceMailAlphaTag() {
         return getVoiceMailAlphaTag(getSubId());
     }
@@ -3187,13 +3092,11 @@
     /**
      * Retrieves the alphabetic identifier associated with the voice
      * mail number for a subscription.
-     * <p>
-     * Requires Permission:
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @param subId whose alphabetic identifier associated with the
      * voice mail number is returned
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getVoiceMailAlphaTag(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3504,23 +3407,18 @@
 
     /**
      * Returns the CDMA ERI icon index to display
-     *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getCdmaEriIconIndex() {
         return getCdmaEriIconIndex(getSubId());
     }
 
     /**
      * Returns the CDMA ERI icon index to display for a subscription
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getCdmaEriIconIndex(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -3540,11 +3438,9 @@
      * 0 - ON
      * 1 - FLASHING
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getCdmaEriIconMode() {
         return getCdmaEriIconMode(getSubId());
     }
@@ -3554,11 +3450,9 @@
      * 0 - ON
      * 1 - FLASHING
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getCdmaEriIconMode(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -3576,11 +3470,9 @@
     /**
      * Returns the CDMA ERI text,
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getCdmaEriText() {
         return getCdmaEriText(getSubId());
     }
@@ -3588,11 +3480,9 @@
     /**
      * Returns the CDMA ERI text, of a subscription
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getCdmaEriText(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -3675,13 +3565,10 @@
      * android.telephony.TelephonyManager#getCellLocation getCellLocation()}
      * instead.
      *
-     * <p>Requires permission:
-     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
-     *
      * @return List of {@link android.telephony.CellInfo}; null if cell
      * information is unavailable.
-     *
      */
+    @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
     public List<CellInfo> getAllCellInfo() {
         try {
             ITelephony telephony = getITelephony();
@@ -4535,11 +4422,9 @@
      * Returns an array of Forbidden PLMNs from the USIM App
      * Returns null if the query fails.
      *
-     *
-     * <p>Requires that the caller has READ_PHONE_STATE
-     *
      * @return an array of forbidden PLMNs or null if not available
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String[] getForbiddenPlmns() {
       return getForbiddenPlmns(getSubId(), APPTYPE_USIM);
     }
@@ -4548,14 +4433,12 @@
      * Returns an array of Forbidden PLMNs from the specified SIM App
      * Returns null if the query fails.
      *
-     *
-     * <p>Requires that the calling app has READ_PHONE_STATE
-     *
      * @param subId subscription ID used for authentication
      * @param appType the icc application type, like {@link #APPTYPE_USIM}
      * @return fplmns an array of forbidden PLMNs
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String[] getForbiddenPlmns(int subId, int appType) {
         try {
             ITelephony telephony = getITelephony();
@@ -6243,10 +6126,8 @@
 
     /**
      * Returns the current {@link ServiceState} information.
-     *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public ServiceState getServiceState() {
         return getServiceStateForSubscriber(getSubId());
     }
diff --git a/tests/testables/src/android/testing/AndroidTestingRunner.java b/tests/testables/src/android/testing/AndroidTestingRunner.java
index 816ed03..a425f70 100644
--- a/tests/testables/src/android/testing/AndroidTestingRunner.java
+++ b/tests/testables/src/android/testing/AndroidTestingRunner.java
@@ -18,7 +18,7 @@
 import android.support.test.internal.runner.junit4.statement.RunBefores;
 import android.support.test.internal.runner.junit4.statement.UiThreadStatement;
 
-import android.testing.TestableLooper.LooperStatement;
+import android.testing.TestableLooper.LooperFrameworkMethod;
 import android.testing.TestableLooper.RunWithLooper;
 
 import org.junit.After;
@@ -30,6 +30,7 @@
 import org.junit.runners.model.InitializationError;
 import org.junit.runners.model.Statement;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -49,28 +50,21 @@
 
     @Override
     protected Statement methodInvoker(FrameworkMethod method, Object test) {
-        return shouldRunOnUiThread(method) ? new UiThreadStatement(
-                methodInvokerInt(method, test), true) : methodInvokerInt(method, test);
-    }
-
-    protected Statement methodInvokerInt(FrameworkMethod method, Object test) {
-        RunWithLooper annotation = method.getAnnotation(RunWithLooper.class);
-        if (annotation == null) annotation = mKlass.getAnnotation(RunWithLooper.class);
-        if (annotation != null) {
-            return new LooperStatement(super.methodInvoker(method, test),
-                    annotation.setAsMainLooper(), test);
-        }
-        return super.methodInvoker(method, test);
+        method = looperWrap(method, test, method);
+        final Statement statement = super.methodInvoker(method, test);
+        return shouldRunOnUiThread(method) ? new UiThreadStatement(statement, true) : statement;
     }
 
     protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) {
-        List befores = this.getTestClass().getAnnotatedMethods(Before.class);
+        List befores = looperWrap(method, target,
+                this.getTestClass().getAnnotatedMethods(Before.class));
         return befores.isEmpty() ? statement : new RunBefores(method, statement,
                 befores, target);
     }
 
     protected Statement withAfters(FrameworkMethod method, Object target, Statement statement) {
-        List afters = this.getTestClass().getAnnotatedMethods(After.class);
+        List afters = looperWrap(method, target,
+                this.getTestClass().getAnnotatedMethods(After.class));
         return afters.isEmpty() ? statement : new RunAfters(method, statement, afters,
                 target);
     }
@@ -88,6 +82,30 @@
         return annotation == null ? 0L : annotation.timeout();
     }
 
+    protected List<FrameworkMethod> looperWrap(FrameworkMethod method, Object test,
+            List<FrameworkMethod> methods) {
+        RunWithLooper annotation = method.getAnnotation(RunWithLooper.class);
+        if (annotation == null) annotation = mKlass.getAnnotation(RunWithLooper.class);
+        if (annotation != null) {
+            methods = new ArrayList<>(methods);
+            for (int i = 0; i < methods.size(); i++) {
+                methods.set(i, LooperFrameworkMethod.get(methods.get(i),
+                        annotation.setAsMainLooper(), test));
+            }
+        }
+        return methods;
+    }
+
+    protected FrameworkMethod looperWrap(FrameworkMethod method, Object test,
+            FrameworkMethod base) {
+        RunWithLooper annotation = method.getAnnotation(RunWithLooper.class);
+        if (annotation == null) annotation = mKlass.getAnnotation(RunWithLooper.class);
+        if (annotation != null) {
+            return LooperFrameworkMethod.get(base, annotation.setAsMainLooper(), test);
+        }
+        return base;
+    }
+
     public boolean shouldRunOnUiThread(FrameworkMethod method) {
         if (mKlass.getAnnotation(UiThreadTest.class) != null) {
             return true;
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index 8a33cf9..9eddc51 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -15,20 +15,21 @@
 package android.testing;
 
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
+import android.os.TestLooperManager;
+import android.support.test.InstrumentationRegistry;
 import android.util.ArrayMap;
 
-import org.junit.runners.model.Statement;
+import org.junit.runners.model.FrameworkMethod;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
-import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.util.Map;
 
 /**
@@ -38,65 +39,35 @@
  */
 public class TestableLooper {
 
-    private final Method mNext;
-    private final Method mRecycleUnchecked;
-
     private Looper mLooper;
     private MessageQueue mQueue;
     private boolean mMain;
     private Object mOriginalMain;
     private MessageHandler mMessageHandler;
 
-    private int mParsedCount;
     private Handler mHandler;
-    private Message mEmptyMessage;
+    private Runnable mEmptyMessage;
+    private TestLooperManager mQueueWrapper;
 
-    public TestableLooper() throws Exception {
-        this(true);
+    public TestableLooper(Looper l) throws Exception {
+        this(InstrumentationRegistry.getInstrumentation().acquireLooperManager(l), l);
     }
 
-    public TestableLooper(boolean setMyLooper) throws Exception {
-        setupQueue(setMyLooper);
-        mNext = mQueue.getClass().getDeclaredMethod("next");
-        mNext.setAccessible(true);
-        mRecycleUnchecked = Message.class.getDeclaredMethod("recycleUnchecked");
-        mRecycleUnchecked.setAccessible(true);
+    private TestableLooper(TestLooperManager wrapper, Looper l) throws Exception {
+        mQueueWrapper = wrapper;
+        setupQueue(l);
+    }
+
+    private TestableLooper(Looper looper, boolean b) throws Exception {
+        setupQueue(looper);
     }
 
     public Looper getLooper() {
         return mLooper;
     }
 
-    private void clearLooper() throws NoSuchFieldException, IllegalAccessException {
-        Field field = Looper.class.getDeclaredField("sThreadLocal");
-        field.setAccessible(true);
-        ThreadLocal<Looper> sThreadLocal = (ThreadLocal<Looper>) field.get(null);
-        sThreadLocal.set(null);
-    }
-
-    private boolean setForCurrentThread() throws NoSuchFieldException, IllegalAccessException {
-        if (Looper.myLooper() != mLooper) {
-            Field field = Looper.class.getDeclaredField("sThreadLocal");
-            field.setAccessible(true);
-            ThreadLocal<Looper> sThreadLocal = (ThreadLocal<Looper>) field.get(null);
-            sThreadLocal.set(mLooper);
-            return true;
-        }
-        return false;
-    }
-
-    private void setupQueue(boolean setMyLooper) throws Exception {
-        if (setMyLooper) {
-            clearLooper();
-            Looper.prepare();
-            mLooper = Looper.myLooper();
-        } else {
-            Constructor<Looper> constructor = Looper.class.getDeclaredConstructor(
-                    boolean.class);
-            constructor.setAccessible(true);
-            mLooper = constructor.newInstance(true);
-        }
-
+    private void setupQueue(Looper l) throws Exception {
+        mLooper = l;
         mQueue = mLooper.getQueue();
         mHandler = new Handler(mLooper);
     }
@@ -121,9 +92,7 @@
      * tests.
      */
     public void destroy() throws NoSuchFieldException, IllegalAccessException {
-        if (Looper.myLooper() == mLooper) {
-            clearLooper();
-        }
+        mQueueWrapper.release();
         if (mMain && mOriginalMain != null) {
             Field field = mLooper.getClass().getDeclaredField("sMainLooper");
             field.setAccessible(true);
@@ -156,34 +125,35 @@
 
     private int processQueuedMessages() {
         int count = 0;
-        mEmptyMessage = mHandler.obtainMessage(1);
-        mHandler.sendMessageDelayed(mEmptyMessage, 1);
+        mEmptyMessage = () -> { };
+        mHandler.post(mEmptyMessage);
+        waitForMessage(mQueueWrapper, mHandler, mEmptyMessage);
         while (parseMessageInt()) count++;
         return count;
     }
 
     private boolean parseMessageInt() {
         try {
-            Message result = (Message) mNext.invoke(mQueue);
+            Message result = mQueueWrapper.next();
             if (result != null) {
                 // This is a break message.
-                if (result == mEmptyMessage) {
-                    mRecycleUnchecked.invoke(result);
+                if (result.getCallback() == mEmptyMessage) {
+                    mQueueWrapper.recycle(result);
                     return false;
                 }
 
                 if (mMessageHandler != null) {
                     if (mMessageHandler.onMessageHandled(result)) {
                         result.getTarget().dispatchMessage(result);
-                        mRecycleUnchecked.invoke(result);
+                        mQueueWrapper.recycle(result);
                     } else {
-                        mRecycleUnchecked.invoke(result);
+                        mQueueWrapper.recycle(result);
                         // Message handler indicated it doesn't want us to continue.
                         return false;
                     }
                 } else {
                     result.getTarget().dispatchMessage(result);
-                    mRecycleUnchecked.invoke(result);
+                    mQueueWrapper.recycle(result);
                 }
             } else {
                 // No messages, don't continue parsing
@@ -199,10 +169,14 @@
      * Runs an executable with myLooper set and processes all messages added.
      */
     public void runWithLooper(RunnableWithException runnable) throws Exception {
-        boolean set = setForCurrentThread();
-        runnable.run();
+        new Handler(getLooper()).post(() -> {
+            try {
+                runnable.run();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        });
         processAllMessages();
-        if (set) clearLooper();
     }
 
     public interface RunnableWithException {
@@ -215,39 +189,132 @@
         boolean setAsMainLooper() default false;
     }
 
+    private static void waitForMessage(TestLooperManager queueWrapper, Handler handler,
+            Runnable execute) {
+        for (int i = 0; i < 10; i++) {
+            if (!queueWrapper.hasMessages(handler, null, execute)) {
+                try {
+                    Thread.sleep(1);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+        if (!queueWrapper.hasMessages(handler, null, execute)) {
+            throw new RuntimeException("Message didn't queue...");
+        }
+    }
+
     private static final Map<Object, TestableLooper> sLoopers = new ArrayMap<>();
 
     public static TestableLooper get(Object test) {
         return sLoopers.get(test);
     }
 
-    public static class LooperStatement extends Statement {
-        private final boolean mSetAsMain;
-        private final Statement mBase;
-        private final TestableLooper mLooper;
+    public static class LooperFrameworkMethod extends FrameworkMethod {
+        private HandlerThread mHandlerThread;
 
-        public LooperStatement(Statement base, boolean setAsMain, Object test) {
-            mBase = base;
+        private final TestableLooper mTestableLooper;
+        private final Looper mLooper;
+        private final Handler mHandler;
+
+        public LooperFrameworkMethod(FrameworkMethod base, boolean setAsMain, Object test) {
+            super(base.getMethod());
             try {
-                mLooper = new TestableLooper(false);
-                sLoopers.put(test, mLooper);
-                mSetAsMain = setAsMain;
+                mLooper = setAsMain ? Looper.getMainLooper() : createLooper();
+                mTestableLooper = new TestableLooper(mLooper, false);
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
+            sLoopers.put(test, mTestableLooper);
+            mHandler = new Handler(mLooper);
+        }
+
+        public LooperFrameworkMethod(TestableLooper other, FrameworkMethod base) {
+            super(base.getMethod());
+            mLooper = other.mLooper;
+            mTestableLooper = other;
+            mHandler = new Handler(mLooper);
+        }
+
+        public static FrameworkMethod get(FrameworkMethod base, boolean setAsMain, Object test) {
+            if (sLoopers.containsKey(test)) {
+                return new LooperFrameworkMethod(sLoopers.get(test), base);
+            }
+            return new LooperFrameworkMethod(base, setAsMain, test);
         }
 
         @Override
-        public void evaluate() throws Throwable {
-            mLooper.setForCurrentThread();
-            if (mSetAsMain) {
-                mLooper.setAsMainLooper();
+        public Object invokeExplosively(Object target, Object... params) throws Throwable {
+            if (Looper.myLooper() == mLooper) {
+                // Already on the right thread from another statement, just execute then.
+                return super.invokeExplosively(target, params);
+            }
+            boolean set = mTestableLooper.mQueueWrapper == null;
+            if (set) {
+                mTestableLooper.mQueueWrapper = InstrumentationRegistry.getInstrumentation()
+                        .acquireLooperManager(mLooper);
+            }
+            try {
+                Object[] ret = new Object[1];
+                // Run the execution on the looper thread.
+                Runnable execute = () -> {
+                    try {
+                        ret[0] = super.invokeExplosively(target, params);
+                    } catch (Throwable throwable) {
+                        throw new LooperException(throwable);
+                    }
+                };
+                Message m = Message.obtain(mHandler, execute);
+
+                // Dispatch our message.
+                try {
+                    mTestableLooper.mQueueWrapper.execute(m);
+                } catch (LooperException e) {
+                    throw e.getSource();
+                } catch (RuntimeException re) {
+                    // If the TestLooperManager has to post, it will wrap what it throws in a
+                    // RuntimeException, make sure we grab the actual source.
+                    if (re.getCause() instanceof LooperException) {
+                        throw ((LooperException) re.getCause()).getSource();
+                    } else {
+                        throw re.getCause();
+                    }
+                } finally {
+                    m.recycle();
+                }
+                return ret[0];
+            } finally {
+                if (set) {
+                    mTestableLooper.mQueueWrapper.release();
+                    mTestableLooper.mQueueWrapper = null;
+                }
+            }
+        }
+
+        private Looper createLooper() {
+            // TODO: Find way to share these.
+            mHandlerThread = new HandlerThread(TestableLooper.class.getSimpleName());
+            mHandlerThread.start();
+            return mHandlerThread.getLooper();
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            super.finalize();
+            if (mHandlerThread != null) {
+                mHandlerThread.quit();
+            }
+        }
+
+        private static class LooperException extends RuntimeException {
+            private final Throwable mSource;
+
+            public LooperException(Throwable t) {
+                mSource = t;
             }
 
-            try {
-                mBase.evaluate();
-            } finally {
-                mLooper.destroy();
+            public Throwable getSource() {
+                return mSource;
             }
         }
     }
diff --git a/tests/testables/tests/src/android/testing/TestableLooperTest.java b/tests/testables/tests/src/android/testing/TestableLooperTest.java
index 18e5fff..12f1d0a 100644
--- a/tests/testables/tests/src/android/testing/TestableLooperTest.java
+++ b/tests/testables/tests/src/android/testing/TestableLooperTest.java
@@ -24,17 +24,16 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.testing.TestableLooper.MessageHandler;
 import android.testing.TestableLooper.RunWithLooper;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 public class TestableLooperTest {
@@ -46,11 +45,6 @@
         mTestableLooper = TestableLooper.get(this);
     }
 
-    @After
-    public void tearDown() throws Exception {
-        mTestableLooper.destroy();
-    }
-
     @Test
     public void testMessageExecuted() throws Exception {
         Handler h = new Handler();
@@ -133,39 +127,23 @@
     @Test
     public void testMainLooper() throws Exception {
         assertNotEquals(Looper.myLooper(), Looper.getMainLooper());
-
-        Looper originalMain = Looper.getMainLooper();
-        mTestableLooper.setAsMainLooper();
-        assertEquals(Looper.myLooper(), Looper.getMainLooper());
-        Runnable r = mock(Runnable.class);
-
-        new Handler(Looper.getMainLooper()).post(r);
-        mTestableLooper.processAllMessages();
-
-        verify(r).run();
-        mTestableLooper.destroy();
-
-        assertEquals(originalMain, Looper.getMainLooper());
-    }
-
-    @Test
-    public void testNotMyLooper() throws Exception {
-        TestableLooper looper = new TestableLooper(false);
-
-        assertEquals(Looper.myLooper(), mTestableLooper.getLooper());
-        assertNotEquals(Looper.myLooper(), looper.getLooper());
-
         Runnable r = mock(Runnable.class);
         Runnable r2 = mock(Runnable.class);
-        new Handler().post(r);
-        new Handler(looper.getLooper()).post(r2);
+        TestableLooper testableLooper = new TestableLooper(Looper.getMainLooper());
 
-        looper.processAllMessages();
-        verify(r2).run();
-        verify(r, never()).run();
+        try {
+            testableLooper.setMessageHandler(m -> {
+                if (m.getCallback() == r) return true;
+                return false;
+            });
+            new Handler(Looper.getMainLooper()).post(r);
+            testableLooper.processAllMessages();
 
-        mTestableLooper.processAllMessages();
-        verify(r).run();
+            verify(r).run();
+            verify(r2, never()).run();
+        } finally {
+            testableLooper.destroy();
+        }
     }
 
     @Test