Merge "Use String.equals when comparing conflicting providers"
diff --git a/Android.bp b/Android.bp
index 1c59e2b..415eff3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -368,6 +368,7 @@
         "core/java/com/android/internal/app/IAppOpsService.aidl",
         "core/java/com/android/internal/app/IBatteryStats.aidl",
         "core/java/com/android/internal/app/ISoundTriggerService.aidl",
+        "core/java/com/android/internal/app/IVoiceActionCheckCallback.aidl",
         "core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl",
         "core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl",
         "core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index 75787a7..6042b2f 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -14015,12 +14015,15 @@
     method public android.graphics.Paint.Style getStyle();
     method public android.graphics.Paint.Align getTextAlign();
     method public void getTextBounds(java.lang.String, int, int, android.graphics.Rect);
+    method public void getTextBounds(java.lang.CharSequence, int, int, android.graphics.Rect);
     method public void getTextBounds(char[], int, int, android.graphics.Rect);
     method public java.util.Locale getTextLocale();
     method public android.os.LocaleList getTextLocales();
     method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
     method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
     method public float getTextRunAdvances(char[], int, int, int, int, boolean, float[], int);
+    method public int getTextRunCursor(char[], int, int, boolean, int, int);
+    method public int getTextRunCursor(java.lang.CharSequence, int, int, boolean, int, int);
     method public float getTextScaleX();
     method public float getTextSize();
     method public float getTextSkewX();
@@ -14087,6 +14090,11 @@
     method public void setWordSpacing(float);
     method public android.graphics.Xfermode setXfermode(android.graphics.Xfermode);
     field public static final int ANTI_ALIAS_FLAG = 1; // 0x1
+    field public static final int CURSOR_AFTER = 0; // 0x0
+    field public static final int CURSOR_AT = 4; // 0x4
+    field public static final int CURSOR_AT_OR_AFTER = 1; // 0x1
+    field public static final int CURSOR_AT_OR_BEFORE = 3; // 0x3
+    field public static final int CURSOR_BEFORE = 2; // 0x2
     field public static final int DEV_KERN_TEXT_FLAG = 256; // 0x100
     field public static final int DITHER_FLAG = 4; // 0x4
     field public static final int EMBEDDED_BITMAP_TEXT_FLAG = 1024; // 0x400
@@ -39920,6 +39928,7 @@
     method public int getDisabledShowContext();
     method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
     method public android.os.IBinder onBind(android.content.Intent);
+    method public java.util.Set<java.lang.String> onGetSupportedVoiceActions(java.util.Set<java.lang.String>);
     method public void onLaunchVoiceAssistFromKeyguard();
     method public void onReady();
     method public void onShutdown();
diff --git a/api/system-current.txt b/api/system-current.txt
index 47b4cfc..8f7606a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5405,7 +5405,6 @@
   }
 
   public class TelephonyManager {
-    method public deprecated void answerRingingCall();
     method public deprecated void call(java.lang.String, java.lang.String);
     method public int checkCarrierPrivilegesForPackage(java.lang.String);
     method public int checkCarrierPrivilegesForPackageAnyPhone(java.lang.String);
@@ -5413,7 +5412,6 @@
     method public boolean disableDataConnectivity();
     method public boolean enableDataConnectivity();
     method public void enableVideoCalling(boolean);
-    method public deprecated boolean endCall();
     method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index b88c760..9012c33 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -143,3 +143,12 @@
 
 }
 
+package android.telephony {
+
+  public class TelephonyManager {
+    method public deprecated void answerRingingCall();
+    method public deprecated boolean endCall();
+  }
+
+}
+
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 36e51b9..12fb4a3 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -470,7 +470,8 @@
                     onExecute(provider);
                 } finally {
                     if (provider != null) {
-                        activityManager.removeContentProviderExternal(providerName, token);
+                        activityManager.removeContentProviderExternalAsUser(
+                                providerName, token, mUserId);
                     }
                 }
             } catch (Exception e) {
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index 950a258..455e4bb 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -84,7 +84,8 @@
                     cursor.close();
                 }
                 if (provider != null) {
-                    activityManager.removeContentProviderExternal(providerName, token);
+                    activityManager.removeContentProviderExternalAsUser(providerName, token,
+                            UserHandle.USER_SYSTEM);
                 }
             }
         } catch (RemoteException e) {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 16360b3..2490cae 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -263,7 +263,9 @@
     void killAllBackgroundProcesses();
     ContentProviderHolder getContentProviderExternal(in String name, int userId,
             in IBinder token, String tag);
+    /** @deprecated - Use {@link #removeContentProviderExternalAsUser} which takes a user ID. */
     void removeContentProviderExternal(in String name, in IBinder token);
+    void removeContentProviderExternalAsUser(in String name, in IBinder token, int userId);
     // Get memory information about the calling process.
     void getMyMemoryState(out ActivityManager.RunningAppProcessInfo outInfo);
     boolean killProcessesBelowForeground(in String reason);
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index 3fe17840..8760efe 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -95,9 +95,6 @@
      * Sets the current primary clip on the clipboard.  This is the clip that
      * is involved in normal cut and paste operations.
      *
-     * <em>If the application is not the default IME or does not have input focus this will have
-     * no effect.</em>
-     *
      * @param clip The clipped data item to set.
      * @see #getPrimaryClip()
      * @see #clearPrimaryClip()
@@ -115,9 +112,6 @@
     /**
      * Clears any current primary clip on the clipboard.
      *
-     * <em>If the application is not the default IME or does not have input focus this will have
-     * no effect.</em>
-     *
      * @see #setPrimaryClip(ClipData)
      */
     public void clearPrimaryClip() {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2ae3ae6..d88f6e3 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3167,11 +3167,11 @@
      *
      * <p>Note: Instant apps, for which {@link PackageManager#isInstantApp()} returns true,
      * don't have access to the following system services: {@link #DEVICE_POLICY_SERVICE},
-     * {@link #FINGERPRINT_SERVICE}, {@link #SHORTCUT_SERVICE}, {@link #USB_SERVICE},
-     * {@link #WALLPAPER_SERVICE}, {@link #WIFI_P2P_SERVICE}, {@link #WIFI_SERVICE},
-     * {@link #WIFI_AWARE_SERVICE}. For these services this method will return <code>null</code>.
-     * Generally, if you are running as an instant app you should always check whether the result
-     * of this method is null.
+     * {@link #FINGERPRINT_SERVICE}, {@link #KEYGUARD_SERVICE}, {@link #SHORTCUT_SERVICE},
+     * {@link #USB_SERVICE}, {@link #WALLPAPER_SERVICE}, {@link #WIFI_P2P_SERVICE},
+     * {@link #WIFI_SERVICE}, {@link #WIFI_AWARE_SERVICE}. For these services this method will
+     * return <code>null</code>.  Generally, if you are running as an instant app you should always
+     * check whether the result of this method is null.
      *
      * @param name The name of the desired service.
      *
@@ -3258,11 +3258,11 @@
      *
      * <p>Note: Instant apps, for which {@link PackageManager#isInstantApp()} returns true,
      * don't have access to the following system services: {@link #DEVICE_POLICY_SERVICE},
-     * {@link #FINGERPRINT_SERVICE}, {@link #SHORTCUT_SERVICE}, {@link #USB_SERVICE},
-     * {@link #WALLPAPER_SERVICE}, {@link #WIFI_P2P_SERVICE}, {@link #WIFI_SERVICE},
-     * {@link #WIFI_AWARE_SERVICE}. For these services this method will return <code>null</code>.
-     * Generally, if you are running as an instant app you should always check whether the result
-     * of this method is null.
+     * {@link #FINGERPRINT_SERVICE}, {@link #KEYGUARD_SERVICE}, {@link #SHORTCUT_SERVICE},
+     * {@link #USB_SERVICE}, {@link #WALLPAPER_SERVICE}, {@link #WIFI_P2P_SERVICE},
+     * {@link #WIFI_SERVICE}, {@link #WIFI_AWARE_SERVICE}. For these services this method will
+     * return <code>null</code>.  Generally, if you are running as an instant app you should always
+     * check whether the result of this method is null.
      *
      * @param serviceClass The class of the desired service.
      * @return The service or null if the class is not a supported system service.
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 963f881..19af609 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -102,7 +102,13 @@
 
     private static volatile boolean sForceSafeLabels = false;
 
-    /** {@hide} */
+    /**
+     * Always use {@link #loadSafeLabel safe labels} when calling {@link #loadLabel}.
+     *
+     * @param forceSafeLabels {@code true} to enforce safe labels
+     *
+     * @hide
+     */
     @SystemApi
     public static void setForceSafeLabels(boolean forceSafeLabels) {
         sForceSafeLabels = forceSafeLabels;
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 20e1454e..b5b4432 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -136,24 +136,6 @@
     public abstract void setVoiceInteractionPackagesProvider(PackagesProvider provider);
 
     /**
-     * Sets the SMS packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setSmsAppPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the dialer packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setDialerAppPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the sim call manager packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setSimCallManagerPackagesProvider(PackagesProvider provider);
-
-    /**
      * Sets the Use Open Wifi packages provider.
      * @param provider The packages provider.
      */
@@ -166,26 +148,28 @@
     public abstract void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider);
 
     /**
-     * Requests granting of the default permissions to the current default SMS app.
-     * @param packageName The default SMS package name.
-     * @param userId The user for which to grant the permissions.
+     * Called when the package for the default dialer changed
+     *
+     * @param packageName the new dialer package
+     * @param userId user for which the change was made
      */
-    public abstract void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId);
+    public void onDefaultDialerAppChanged(String packageName, int userId) {}
 
     /**
-     * Requests granting of the default permissions to the current default dialer app.
-     * @param packageName The default dialer package name.
-     * @param userId The user for which to grant the permissions.
+     * Called when the package for the default SMS handler changed
+     *
+     * @param packageName the new sms package
+     * @param userId user for which the change was made
      */
-    public abstract void grantDefaultPermissionsToDefaultDialerApp(String packageName, int userId);
+    public void onDefaultSmsAppChanged(String packageName, int userId) {}
 
     /**
-     * Requests granting of the default permissions to the current default sim call manager.
-     * @param packageName The default sim call manager package name.
-     * @param userId The user for which to grant the permissions.
+     * Called when the package for the default sim call manager changed
+     *
+     * @param packageName the new sms package
+     * @param userId user for which the change was made
      */
-    public abstract void grantDefaultPermissionsToDefaultSimCallManager(String packageName,
-            int userId);
+    public void onDefaultSimCallManagerAppChanged(String packageName, int userId) {}
 
     /**
      * Requests granting of the default permissions to the current default Use Open Wifi app.
@@ -446,8 +430,8 @@
          *
          * @param packageName The package to check for
          * @param uid the uid in which the package is running
-         * @return {@link USER_TRUSTED} if the user has trusted the package, {@link USER_BLOCKED}
-         * if user has blocked requests from the package, {@link USER_DEFAULT} if the user response
+         * @return {@link #USER_TRUSTED} if the user has trusted the package, {@link #USER_BLOCKED}
+         * if user has blocked requests from the package, {@link #USER_DEFAULT} if the user response
          * is not yet available
          */
         int getPackageTrustedToInstallApps(String packageName, int uid);
@@ -561,7 +545,7 @@
     /**
      * Returns a list without a change observer.
      *
-     * {@see #getPackageList(PackageListObserver)}
+     * @see #getPackageList(PackageListObserver)
      */
     public @NonNull PackageList getPackageList() {
         return getPackageList(null);
@@ -590,7 +574,16 @@
     /**
      * Returns a package object for the disabled system package name.
      */
-    public abstract @Nullable PackageParser.Package getDisabledPackage(@NonNull String packageName);
+    public abstract @Nullable PackageParser.Package getDisabledSystemPackage(
+            @NonNull String packageName);
+
+    /**
+     * Returns the package name for the disabled system package.
+     *
+     * This is equivalent to
+     * {@link #getDisabledSystemPackage(String)}.{@link PackageParser.Package#packageName}
+     */
+    public abstract @Nullable String getDisabledSystemPackageName(@NonNull String packageName);
 
     /**
      * Returns whether or not the component is the resolver activity.
@@ -619,7 +612,7 @@
      * Access may be limited based upon whether the calling or target applications
      * are instant applications.
      *
-     * @see #canAccessInstantApps(int)
+     * @see #canAccessInstantApps
      */
     public abstract boolean filterAppAccess(
             @Nullable PackageParser.Package pkg, int callingUid, int userId);
@@ -635,6 +628,9 @@
     public abstract void updatePermissionFlagsTEMP(@NonNull String permName,
             @NonNull String packageName, int flagMask, int flagValues, int userId);
 
+    /** Returns whether the given package was signed by the platform */
+    public abstract boolean isPlatformSigned(String pkg);
+
     /**
      * Returns true if it's still safe to restore data backed up from this app's version
      * that was signed with restoringFromSigHash.
diff --git a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
index f2da21e..18aea03 100644
--- a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
+++ b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
@@ -16,6 +16,7 @@
 
 package android.permissionpresenterservice;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Context;
@@ -73,12 +74,13 @@
     public abstract List<RuntimePermissionPresentationInfo> onGetAppPermissions(String packageName);
 
     /**
-     * Revoke the permission {@code permissionName} for app {@code packageName}
+     * Revokes the permission {@code permissionName} for app {@code packageName}
      *
      * @param packageName The package for which to revoke
      * @param permissionName The permission to revoke
      */
-    public abstract void onRevokeRuntimePermission(String packageName, String permissionName);
+    public abstract void onRevokeRuntimePermission(@NonNull String packageName,
+            @NonNull String permissionName);
 
     @Override
     public final IBinder onBind(Intent intent) {
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 663bdcb..3893f2a 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -43,13 +43,20 @@
     }
 
     /**
-     * Notifies the Android System that an
-     * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
-     * FillCallback)} was successfully fulfilled by the service.
+     * Notifies the Android System that a fill request
+     * ({@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+     * FillCallback)}) was successfully fulfilled by the service.
      *
-     * @param response autofill information for that activity, or {@code null} when the activity
-     * cannot be autofilled (for example, if it only contains read-only fields). See
-     * {@link FillResponse} for examples.
+     * <p>This method should always be called, even if the service doesn't have the heuristics to
+     * fulfill the request (in which case it should be called with {@code null}).
+     *
+     * <p>See the main {@link AutofillService} documentation for more details and examples.
+     *
+     * @param response autofill information for that activity, or {@code null} when the service
+     * cannot autofill the activity.
+     *
+     * @throws IllegalStateException if this method or {@link #onFailure(CharSequence)} was already
+     * called.
      */
     public void onSuccess(@Nullable FillResponse response) {
         assertNotCalled();
@@ -67,11 +74,25 @@
     }
 
     /**
-     * Notifies the Android System that an
+     * Notifies the Android System that a fill request (
      * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
-     * FillCallback)} could not be fulfilled by the service.
+     * FillCallback)}) could not be fulfilled by the service (for example, because the user data was
+     * not available yet), so the request could be retried later.
      *
-     * @param message error message to be displayed to the user.
+     * <p><b>Note: </b>this method should not be used when the service didn't have the heursitics to
+     * fulfill the request; in this case, the service should call {@link #onSuccess(FillResponse)
+     * onSuccess(null)} instead.
+     *
+     * <p><b>Note: </b>on Android versions up to {@link android.os.Build.VERSION_CODES#P}, this
+     * method is not working as intended, and the service should call
+     * {@link #onSuccess(FillResponse) onSuccess(null)} instead.
+     *
+     * @param message error message to be displayed to the user. <b>Note: </b> this message is
+     * displayed on {@code logcat} logs and should not contain PII (Personally Identifiable
+     * Information, such as username or email address).
+     *
+     * @throws IllegalStateException if this method or {@link #onSuccess(FillResponse)} was already
+     * called.
      */
     public void onFailure(@Nullable CharSequence message) {
         Log.w(TAG, "onFailure(): " + (message == null ? null : message.length() + "_chars"));
diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java
index e252e96..0625095 100644
--- a/core/java/android/service/autofill/SaveCallback.java
+++ b/core/java/android/service/autofill/SaveCallback.java
@@ -45,6 +45,9 @@
      * Notifies the Android System that an
      * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} was successfully handled
      * by the service.
+     *
+     * @throws IllegalStateException if this method, {@link #onSuccess(IntentSender)}, or
+     * {@link #onFailure(CharSequence)} was already called.
      */
     public void onSuccess() {
         onSuccessInternal(null);
@@ -62,6 +65,9 @@
      *
      * @param intentSender intent that will be launched from the context of activity being
      * autofilled.
+     *
+     * @throws IllegalStateException if this method, {@link #onSuccess()},
+     * or {@link #onFailure(CharSequence)} was already called.
      */
     public void onSuccess(@NonNull IntentSender intentSender) {
         onSuccessInternal(Preconditions.checkNotNull(intentSender));
@@ -90,7 +96,12 @@
      * you prefer to show your own message, call {@link #onSuccess()} or
      * {@link #onSuccess(IntentSender)} instead.
      *
-     * @param message error message to be displayed to the user.
+     * @param message error message to be displayed to the user. <b>Note: </b> this message is
+     * displayed on {@code logcat} logs and should not contain PII (Personally Identifiable
+     * Information, such as username or email address).
+     *
+     * @throws IllegalStateException if this method, {@link #onSuccess()},
+     * or {@link #onSuccess(IntentSender)} was already called.
      */
     public void onFailure(CharSequence message) {
         Log.w(TAG, "onFailure(): " + (message == null ? null : message.length() + "_chars"));
diff --git a/core/java/android/service/voice/IVoiceInteractionService.aidl b/core/java/android/service/voice/IVoiceInteractionService.aidl
index e3d68a6..24819a6 100644
--- a/core/java/android/service/voice/IVoiceInteractionService.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionService.aidl
@@ -16,6 +16,8 @@
 
 package android.service.voice;
 
+import com.android.internal.app.IVoiceActionCheckCallback;
+
 /**
  * @hide
  */
@@ -24,4 +26,6 @@
     void soundModelsChanged();
     void shutdown();
     void launchVoiceAssistFromKeyguard();
+    void getActiveServiceSupportedActions(in List<String> voiceActions,
+     in IVoiceActionCheckCallback callback);
 }
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 0bbc07e..e105fdf 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -16,6 +16,8 @@
 
 package android.service.voice;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
@@ -26,17 +28,22 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
+import android.util.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.IVoiceActionCheckCallback;
 import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 
 /**
  * Top-level service of the current global voice interactor, which is providing
@@ -71,23 +78,43 @@
     public static final String SERVICE_META_DATA = "android.voice_interaction";
 
     IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() {
-        @Override public void ready() {
-            mHandler.sendEmptyMessage(MSG_READY);
-        }
-        @Override public void shutdown() {
-            mHandler.sendEmptyMessage(MSG_SHUTDOWN);
-        }
-        @Override public void soundModelsChanged() {
-            mHandler.sendEmptyMessage(MSG_SOUND_MODELS_CHANGED);
-        }
         @Override
-        public void launchVoiceAssistFromKeyguard() throws RemoteException {
-            mHandler.sendEmptyMessage(MSG_LAUNCH_VOICE_ASSIST_FROM_KEYGUARD);
+        public void ready() {
+            Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage(
+                    VoiceInteractionService::onReady, VoiceInteractionService.this));
+        }
+
+        @Override
+        public void shutdown() {
+            Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage(
+                    VoiceInteractionService::onShutdownInternal, VoiceInteractionService.this));
+        }
+
+        @Override
+        public void soundModelsChanged() {
+            Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage(
+                    VoiceInteractionService::onSoundModelsChangedInternal,
+                    VoiceInteractionService.this));
+        }
+
+        @Override
+        public void launchVoiceAssistFromKeyguard() {
+            Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage(
+                    VoiceInteractionService::onLaunchVoiceAssistFromKeyguard,
+                    VoiceInteractionService.this));
+        }
+
+        @Override
+        public void getActiveServiceSupportedActions(List<String> voiceActions,
+                IVoiceActionCheckCallback callback) {
+            Handler.getMain().executeOrSendMessage(
+                    PooledLambda.obtainMessage(VoiceInteractionService::onHandleVoiceActionCheck,
+                            VoiceInteractionService.this,
+                            voiceActions,
+                            callback));
         }
     };
 
-    MyHandler mHandler;
-
     IVoiceInteractionManagerService mSystemService;
 
     private final Object mLock = new Object();
@@ -96,33 +123,6 @@
 
     private AlwaysOnHotwordDetector mHotwordDetector;
 
-    static final int MSG_READY = 1;
-    static final int MSG_SHUTDOWN = 2;
-    static final int MSG_SOUND_MODELS_CHANGED = 3;
-    static final int MSG_LAUNCH_VOICE_ASSIST_FROM_KEYGUARD = 4;
-
-    class MyHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_READY:
-                    onReady();
-                    break;
-                case MSG_SHUTDOWN:
-                    onShutdownInternal();
-                    break;
-                case MSG_SOUND_MODELS_CHANGED:
-                    onSoundModelsChangedInternal();
-                    break;
-                case MSG_LAUNCH_VOICE_ASSIST_FROM_KEYGUARD:
-                    onLaunchVoiceAssistFromKeyguard();
-                    break;
-                default:
-                    super.handleMessage(msg);
-            }
-        }
-    }
-
     /**
      * Called when a user has activated an affordance to launch voice assist from the Keyguard.
      *
@@ -186,7 +186,7 @@
      * be any combination of
      * {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and
      * {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT
-      * VoiceInteractionSession.SHOW_WITH_SCREENSHOT}
+     * VoiceInteractionSession.SHOW_WITH_SCREENSHOT}
      * to request that the system generate and deliver assist data on the current foreground
      * app as part of showing the session UI.
      */
@@ -200,10 +200,22 @@
         }
     }
 
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mHandler = new MyHandler();
+    /**
+     * Request to query for what extended voice actions this service supports. This method will
+     * be called when the system checks the supported actions of this
+     * {@link VoiceInteractionService}. Supported actions may be delivered to
+     * {@link VoiceInteractionSession} later to request a session to perform an action.
+     *
+     * <p>Voice actions are defined in support libraries and could vary based on platform context.
+     * For example, car related voice actions will be defined in car support libraries.
+     *
+     * @param voiceActions A set of checked voice actions.
+     * @return Returns a subset of checked voice actions. Additional voice actions in the
+     * returned set will be ignored. Returns null or empty set if no actions are supported.
+     */
+    @Nullable
+    public Set<String> onGetSupportedVoiceActions(@NonNull Set<String> voiceActions) {
+        return null;
     }
 
     @Override
@@ -254,6 +266,18 @@
         }
     }
 
+    private void onHandleVoiceActionCheck(List<String> voiceActions,
+            IVoiceActionCheckCallback callback) {
+        if (callback != null) {
+            try {
+                Set<String> voiceActionsSet = new ArraySet<>(voiceActions);
+                Set<String> resultSet = onGetSupportedVoiceActions(voiceActionsSet);
+                callback.onComplete(resultSet == null ? null : new ArrayList<>(resultSet));
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
     /**
      * Creates an {@link AlwaysOnHotwordDetector} for the given keyphrase and locale.
      * This instance must be retained and used by the client.
@@ -289,12 +313,12 @@
     }
 
     /**
-      * Checks if a given keyphrase and locale are supported to create an
-      * {@link AlwaysOnHotwordDetector}.
-      *
-      * @return true if the keyphrase and locale combination is supported, false otherwise.
-      * @hide
-      */
+     * Checks if a given keyphrase and locale are supported to create an
+     * {@link AlwaysOnHotwordDetector}.
+     *
+     * @return true if the keyphrase and locale combination is supported, false otherwise.
+     * @hide
+     */
     @UnsupportedAppUsage
     public final boolean isKeyphraseAndLocaleSupportedForHotword(String keyphrase, Locale locale) {
         if (mKeyphraseEnrollmentInfo == null) {
diff --git a/core/java/android/text/GraphicsOperations.java b/core/java/android/text/GraphicsOperations.java
index 6edf845..6c15446 100644
--- a/core/java/android/text/GraphicsOperations.java
+++ b/core/java/android/text/GraphicsOperations.java
@@ -58,6 +58,6 @@
     /**
      * Just like {@link Paint#getTextRunCursor}.
      */
-    int getTextRunCursor(int contextStart, int contextEnd, int dir, int offset,
+    int getTextRunCursor(int contextStart, int contextEnd, boolean isRtl, int offset,
             int cursorOpt, Paint p);
 }
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 33c977b..c89617f 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -619,7 +619,7 @@
                     previousLineBottom = lbottom;
                     int lbaseline = lbottom - getLineDescent(i);
 
-                    if (start >= spanEnd) {
+                    if (end >= spanEnd) {
                         // These should be infrequent, so we'll use this so that
                         // we don't have to check as often.
                         spanEnd = mLineBackgroundSpans.getNextTransition(start, textLength);
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 9d841e8..c5fabaf 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -1551,7 +1551,7 @@
      *
      * @param contextStart the start index of the context
      * @param contextEnd the (non-inclusive) end index of the context
-     * @param dir either DIRECTION_RTL or DIRECTION_LTR
+     * @param dir 1 if the run is RTL, otherwise 0
      * @param offset the cursor position to move from
      * @param cursorOpt how to move the cursor, one of CURSOR_AFTER,
      * CURSOR_AT_OR_AFTER, CURSOR_BEFORE,
@@ -1563,21 +1563,28 @@
     @Deprecated
     public int getTextRunCursor(int contextStart, int contextEnd, int dir, int offset,
             int cursorOpt, Paint p) {
+        return getTextRunCursor(contextStart, contextEnd, dir == 1, offset, cursorOpt, p);
+    }
+
+    /** @hide */
+    @Override
+    public int getTextRunCursor(int contextStart, int contextEnd, boolean isRtl, int offset,
+            int cursorOpt, Paint p) {
 
         int ret;
 
         int contextLen = contextEnd - contextStart;
         if (contextEnd <= mGapStart) {
             ret = p.getTextRunCursor(mText, contextStart, contextLen,
-                    dir, offset, cursorOpt);
+                    isRtl, offset, cursorOpt);
         } else if (contextStart >= mGapStart) {
             ret = p.getTextRunCursor(mText, contextStart + mGapLength, contextLen,
-                    dir, offset + mGapLength, cursorOpt) - mGapLength;
+                    isRtl, offset + mGapLength, cursorOpt) - mGapLength;
         } else {
             char[] buf = TextUtils.obtain(contextLen);
             getChars(contextStart, contextEnd, buf, 0);
             ret = p.getTextRunCursor(buf, 0, contextLen,
-                    dir, offset - contextStart, cursorOpt) + contextStart;
+                    isRtl, offset - contextStart, cursorOpt) + contextStart;
             TextUtils.recycle(buf);
         }
 
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index ad7a851..b49a949 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -802,14 +802,13 @@
             }
         }
 
-        int dir = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR;
         int cursorOpt = after ? Paint.CURSOR_AFTER : Paint.CURSOR_BEFORE;
         if (mCharsValid) {
             return wp.getTextRunCursor(mChars, spanStart, spanLimit - spanStart,
-                    dir, offset, cursorOpt);
+                    runIsRtl, offset, cursorOpt);
         } else {
             return wp.getTextRunCursor(mText, mStart + spanStart,
-                    mStart + spanLimit, dir, mStart + offset, cursorOpt) - mStart;
+                    mStart + spanLimit, runIsRtl, mStart + offset, cursorOpt) - mStart;
         }
     }
 
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 5f0a46d..d4bcd12 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -310,7 +310,7 @@
             return len;
         }
 
-        offset = paint.getTextRunCursor(text, offset, len, Paint.DIRECTION_LTR /* not used */,
+        offset = paint.getTextRunCursor(text, offset, len, false /* LTR, not used */,
                 offset, Paint.CURSOR_AFTER);
 
         return adjustReplacementSpan(text, offset, false /* move to the end */);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 2f677f9..be50dd1 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1348,6 +1348,10 @@
                     mServedView.getWindowToken() == appWindowToken) {
                 finishInputLocked();
             }
+            if (mCurRootView != null &&
+                    mCurRootView.getWindowToken() == appWindowToken) {
+                mCurRootView = null;
+            }
         }
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index dfbaf9a..bbfac44 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12495,11 +12495,11 @@
                     advancesIndex);
         }
 
-        public int getTextRunCursor(int contextStart, int contextEnd, int dir,
+        public int getTextRunCursor(int contextStart, int contextEnd, boolean isRtl,
                 int offset, int cursorOpt, Paint p) {
             int contextCount = contextEnd - contextStart;
             return p.getTextRunCursor(mChars, contextStart + mStart,
-                    contextCount, dir, offset + mStart, cursorOpt);
+                    contextCount, isRtl, offset + mStart, cursorOpt);
         }
     }
 
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index 9171959..0f8295a 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -16,8 +16,7 @@
 
 package com.android.internal.app;
 
-import com.android.internal.R;
-
+import android.annotation.NonNull;
 import android.app.SearchManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -32,6 +31,9 @@
 import android.provider.Settings;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.Set;
+
 /**
  * Utility method for dealing with the assistant aspects of
  * {@link com.android.internal.app.IVoiceInteractionManagerService IVoiceInteractionManagerService}.
@@ -62,6 +64,30 @@
         return false;
     }
 
+    /**
+     * Checks the availability of a set of voice actions for the current active voice service.
+     *
+     * @param voiceActions A set of supported voice actions to be checked.
+     * @param callback     The callback which will deliver a set of supported voice actions. If
+     *                     no voice actions are supported for the given voice action set, then null
+     *                     or empty set is provided.
+     */
+    public void getActiveServiceSupportedActions(@NonNull Set<String> voiceActions,
+            @NonNull IVoiceActionCheckCallback callback) {
+        try {
+            if (mVoiceInteractionManagerService != null) {
+                mVoiceInteractionManagerService
+                        .getActiveServiceSupportedActions(new ArrayList<>(voiceActions), callback);
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call activeServiceSupportedActions", e);
+            try {
+                callback.onComplete(null);
+            } catch (RemoteException re) {
+            }
+        }
+    }
+
     public void launchVoiceAssistFromKeyguard() {
         try {
             if (mVoiceInteractionManagerService != null) {
@@ -157,7 +183,7 @@
             return getActiveServiceComponentName();
         }
         final SearchManager searchManager =
-            (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
+                (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
         if (searchManager == null) {
             return null;
         }
diff --git a/core/java/com/android/internal/app/IVoiceActionCheckCallback.aidl b/core/java/com/android/internal/app/IVoiceActionCheckCallback.aidl
new file mode 100644
index 0000000..66ba93d
--- /dev/null
+++ b/core/java/com/android/internal/app/IVoiceActionCheckCallback.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 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 com.android.internal.app;
+
+oneway interface IVoiceActionCheckCallback {
+    void onComplete(in List<String> voiceActions);
+}
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index ff75a8b..5088cca 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 
+import com.android.internal.app.IVoiceActionCheckCallback;
 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.IVoiceInteractionSessionListener;
@@ -143,4 +144,11 @@
      * Register a voice interaction listener.
      */
     void registerVoiceInteractionSessionListener(IVoiceInteractionSessionListener listener);
+
+    /**
+     * Checks the availability of a set of voice actions for the current active voice service.
+     * Returns all supported voice actions.
+     */
+    void getActiveServiceSupportedActions(in List<String> voiceActions,
+     in IVoiceActionCheckCallback callback);
 }
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index 7548c22..101fd41 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -139,8 +139,7 @@
          * The client should try to restart input when its {@link android.view.Window} is focused
          * again.</p>
          *
-         * @see com.android.server.wm.WindowManagerInternal#inputMethodClientHasFocus(
-         * IInputMethodClient)
+         * @see com.android.server.wm.WindowManagerInternal#isInputMethodClientFocus(int, int)
          */
         int ERROR_NOT_IME_TARGET_WINDOW = 11;
         /**
diff --git a/data/keyboards/Vendor_054c_Product_0268.kl b/data/keyboards/Vendor_054c_Product_0268.kl
index 522db3c..b463dd8 100644
--- a/data/keyboards/Vendor_054c_Product_0268.kl
+++ b/data/keyboards/Vendor_054c_Product_0268.kl
@@ -21,8 +21,6 @@
 key 0x126    DPAD_DOWN
 key 0x127    DPAD_LEFT
 
-key 0x120    BUTTON_SELECT
-key 0x123    BUTTON_START
 key 0x12e    BUTTON_A
 key 0x12d    BUTTON_B
 key 0x12f    BUTTON_X
@@ -34,9 +32,6 @@
 key 0x121    BUTTON_THUMBL
 key 0x122    BUTTON_THUMBR
 
-# PS key
-key 0x2d0    BUTTON_MODE
-
 # Left Analog Stick
 axis 0x00    X
 axis 0x01    Y
@@ -74,3 +69,11 @@
 
 # Square
 # axis 0x37
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Select
+key 0x120    BUTTON_SELECT
+# Start
+key 0x123    BUTTON_START
+# PS key
+key 0x2d0    BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_0268_Version_8000.kl b/data/keyboards/Vendor_054c_Product_0268_Version_8000.kl
new file mode 100644
index 0000000..3d93f0f
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0268_Version_8000.kl
@@ -0,0 +1,57 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R)3 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.12
+#   and when connected over Bluetooth
+#
+
+key 0x220   DPAD_UP
+key 0x223   DPAD_RIGHT
+key 0x221   DPAD_DOWN
+key 0x222   DPAD_LEFT
+
+key 0x130   BUTTON_A
+key 0x131   BUTTON_B
+key 0x134   BUTTON_X
+key 0x133   BUTTON_Y
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+key 0x13d   BUTTON_THUMBL
+key 0x13e   BUTTON_THUMBR
+
+# left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# L2 trigger
+axis 0x02   LTRIGGER
+
+# R2 trigger
+axis 0x05   RTRIGGER
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Select
+key 0x13a   BUTTON_SELECT
+# Start
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_0268_Version_8100.kl b/data/keyboards/Vendor_054c_Product_0268_Version_8100.kl
new file mode 100644
index 0000000..3d93f0f
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0268_Version_8100.kl
@@ -0,0 +1,57 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R)3 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.12
+#   and when connected over Bluetooth
+#
+
+key 0x220   DPAD_UP
+key 0x223   DPAD_RIGHT
+key 0x221   DPAD_DOWN
+key 0x222   DPAD_LEFT
+
+key 0x130   BUTTON_A
+key 0x131   BUTTON_B
+key 0x134   BUTTON_X
+key 0x133   BUTTON_Y
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+key 0x13d   BUTTON_THUMBL
+key 0x13e   BUTTON_THUMBR
+
+# left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# L2 trigger
+axis 0x02   LTRIGGER
+
+# R2 trigger
+axis 0x05   RTRIGGER
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Select
+key 0x13a   BUTTON_SELECT
+# Start
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_0268_Version_8111.kl b/data/keyboards/Vendor_054c_Product_0268_Version_8111.kl
new file mode 100644
index 0000000..5fe35f7
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0268_Version_8111.kl
@@ -0,0 +1,57 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R)3 Controller
+# - Version 0x8111 is for Linux hid-sony driver >=4.12 and when
+#   connected over USB
+#
+
+key 0x220   DPAD_UP
+key 0x223   DPAD_RIGHT
+key 0x221   DPAD_DOWN
+key 0x222   DPAD_LEFT
+
+key 0x130   BUTTON_A
+key 0x131   BUTTON_B
+key 0x134   BUTTON_X
+key 0x133   BUTTON_Y
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+key 0x13d   BUTTON_THUMBL
+key 0x13e   BUTTON_THUMBR
+
+# left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# L2 trigger
+axis 0x02   LTRIGGER
+
+# R2 trigger
+axis 0x05   RTRIGGER
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Select
+key 0x13a   BUTTON_SELECT
+# Start
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_05c4.kl b/data/keyboards/Vendor_054c_Product_05c4.kl
index a1284a4..cd7ab1f 100644
--- a/data/keyboards/Vendor_054c_Product_05c4.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4.kl
@@ -60,7 +60,6 @@
 key 0x138    BUTTON_SELECT
 # Options
 key 0x139    BUTTON_START
-
 # PS key
 key 0x13c    BUTTON_MODE
 
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
new file mode 100644
index 0000000..19fcb86
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.10
+#   and when connected over Bluetooth
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134   BUTTON_X
+# Cross
+key 0x130   BUTTON_A
+# Circle
+key 0x131   BUTTON_B
+# Triangle
+key 0x133   BUTTON_Y
+
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+
+# L2 axis
+axis 0x02   LTRIGGER
+# R2 axis
+axis 0x05   RTRIGGER
+
+# Left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# Left stick click
+key 0x13d   BUTTON_THUMBL
+# Right stick click
+key 0x13e   BUTTON_THUMBR
+
+# Hat
+axis 0x10   HAT_X
+axis 0x11   HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a   BUTTON_SELECT
+# Options
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
new file mode 100644
index 0000000..19fcb86
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.10
+#   and when connected over Bluetooth
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134   BUTTON_X
+# Cross
+key 0x130   BUTTON_A
+# Circle
+key 0x131   BUTTON_B
+# Triangle
+key 0x133   BUTTON_Y
+
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+
+# L2 axis
+axis 0x02   LTRIGGER
+# R2 axis
+axis 0x05   RTRIGGER
+
+# Left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# Left stick click
+key 0x13d   BUTTON_THUMBL
+# Right stick click
+key 0x13e   BUTTON_THUMBR
+
+# Hat
+axis 0x10   HAT_X
+axis 0x11   HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a   BUTTON_SELECT
+# Options
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
new file mode 100644
index 0000000..d38bdec
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8111 is for Linux hid-sony driver >=4.10 and when
+#   connected over USB
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134   BUTTON_X
+# Cross
+key 0x130   BUTTON_A
+# Circle
+key 0x131   BUTTON_B
+# Triangle
+key 0x133   BUTTON_Y
+
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+
+# L2 axis
+axis 0x02   LTRIGGER
+# R2 axis
+axis 0x05   RTRIGGER
+
+# Left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# Left stick click
+key 0x13d   BUTTON_THUMBL
+# Right stick click
+key 0x13e   BUTTON_THUMBR
+
+# Hat
+axis 0x10   HAT_X
+axis 0x11   HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a   BUTTON_SELECT
+# Options
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_09cc.kl b/data/keyboards/Vendor_054c_Product_09cc.kl
index a1284a4..cd7ab1f 100644
--- a/data/keyboards/Vendor_054c_Product_09cc.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc.kl
@@ -60,7 +60,6 @@
 key 0x138    BUTTON_SELECT
 # Options
 key 0x139    BUTTON_START
-
 # PS key
 key 0x13c    BUTTON_MODE
 
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
new file mode 100644
index 0000000..19fcb86
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.10
+#   and when connected over Bluetooth
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134   BUTTON_X
+# Cross
+key 0x130   BUTTON_A
+# Circle
+key 0x131   BUTTON_B
+# Triangle
+key 0x133   BUTTON_Y
+
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+
+# L2 axis
+axis 0x02   LTRIGGER
+# R2 axis
+axis 0x05   RTRIGGER
+
+# Left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# Left stick click
+key 0x13d   BUTTON_THUMBL
+# Right stick click
+key 0x13e   BUTTON_THUMBR
+
+# Hat
+axis 0x10   HAT_X
+axis 0x11   HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a   BUTTON_SELECT
+# Options
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
new file mode 100644
index 0000000..19fcb86
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.10
+#   and when connected over Bluetooth
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134   BUTTON_X
+# Cross
+key 0x130   BUTTON_A
+# Circle
+key 0x131   BUTTON_B
+# Triangle
+key 0x133   BUTTON_Y
+
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+
+# L2 axis
+axis 0x02   LTRIGGER
+# R2 axis
+axis 0x05   RTRIGGER
+
+# Left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# Left stick click
+key 0x13d   BUTTON_THUMBL
+# Right stick click
+key 0x13e   BUTTON_THUMBR
+
+# Hat
+axis 0x10   HAT_X
+axis 0x11   HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a   BUTTON_SELECT
+# Options
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
new file mode 100644
index 0000000..d38bdec
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8111 is for Linux hid-sony driver >=4.10 and when
+#   connected over USB
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134   BUTTON_X
+# Cross
+key 0x130   BUTTON_A
+# Circle
+key 0x131   BUTTON_B
+# Triangle
+key 0x133   BUTTON_Y
+
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+
+# L2 axis
+axis 0x02   LTRIGGER
+# R2 axis
+axis 0x05   RTRIGGER
+
+# Left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# Left stick click
+key 0x13d   BUTTON_THUMBL
+# Right stick click
+key 0x13e   BUTTON_THUMBR
+
+# Hat
+axis 0x10   HAT_X
+axis 0x11   HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a   BUTTON_SELECT
+# Options
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_0ba0.kl b/data/keyboards/Vendor_054c_Product_0ba0.kl
new file mode 100644
index 0000000..bc6fc3b
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0ba0.kl
@@ -0,0 +1,70 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R) DualShock 4 USB Dongle
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x130    BUTTON_X
+# Cross
+key 0x131    BUTTON_A
+# Circle
+key 0x132    BUTTON_B
+# Triangle
+key 0x133    BUTTON_Y
+
+key 0x134    BUTTON_L1
+key 0x135    BUTTON_R1
+key 0x136    BUTTON_L2
+key 0x137    BUTTON_R2
+
+# L2 axis
+axis 0x03   LTRIGGER
+# R2 axis
+axis 0x04   RTRIGGER
+
+
+# Left Analog Stick
+axis 0x00    X
+axis 0x01    Y
+# Right Analog Stick
+axis 0x02    Z
+axis 0x05    RZ
+
+# Left stick click
+key 0x13a    BUTTON_THUMBL
+# Right stick click
+key 0x13b    BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x138    BUTTON_SELECT
+# Options
+key 0x139    BUTTON_START
+# PS key
+key 0x13c    BUTTON_MODE
+
+# Touchpad press
+# The touchpad for this joystick will become a separate input device in future releases
+# and this button will be equivalent to left mouse button
+# Therefore, map it to KEYCODE_BUTTON_1 here to allow apps to still handle this on earlier versions
+key 0x13d   BUTTON_1
diff --git a/data/keyboards/Vendor_054c_Product_0ba0_Version_8111.kl b/data/keyboards/Vendor_054c_Product_0ba0_Version_8111.kl
new file mode 100644
index 0000000..8b85a38
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0ba0_Version_8111.kl
@@ -0,0 +1,67 @@
+# Copyright (C) 2018 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.
+
+#
+# Sony Playstation(R) DualShock 4 USB Dongle
+# - Version 0x8111 is for Linux hid-sony driver >=4.10
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134   BUTTON_X
+# Cross
+key 0x130   BUTTON_A
+# Circle
+key 0x131   BUTTON_B
+# Triangle
+key 0x133   BUTTON_Y
+
+key 0x136   BUTTON_L1
+key 0x137   BUTTON_R1
+key 0x138   BUTTON_L2
+key 0x139   BUTTON_R2
+
+# L2 axis
+axis 0x02   LTRIGGER
+# R2 axis
+axis 0x05   RTRIGGER
+
+# Left Analog Stick
+axis 0x00   X
+axis 0x01   Y
+# Right Analog Stick
+axis 0x03   Z
+axis 0x04   RZ
+
+# Left stick click
+key 0x13d   BUTTON_THUMBL
+# Right stick click
+key 0x13e   BUTTON_THUMBR
+
+# Hat
+axis 0x10   HAT_X
+axis 0x11   HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a   BUTTON_SELECT
+# Options
+key 0x13b   BUTTON_START
+# PS key
+key 0x13c   BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 85b39fe..33caa00 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.annotation.ColorInt;
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -37,6 +38,8 @@
 
 import libcore.util.NativeAllocationRegistry;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -309,38 +312,47 @@
      */
     public static final int DIRECTION_RTL = 1;
 
+    /** @hide */
+    @IntDef(prefix = { "CURSOR_" }, value = {
+        CURSOR_AFTER, CURSOR_AT_OR_AFTER, CURSOR_BEFORE, CURSOR_AT_OR_BEFORE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CursorOption {}
+
     /**
-     * Option for getTextRunCursor to compute the valid cursor after
-     * offset or the limit of the context, whichever is less.
-     * @hide
+     * Option for getTextRunCursor.
+     *
+     * Compute the valid cursor after offset or the limit of the context, whichever is less.
      */
     public static final int CURSOR_AFTER = 0;
 
     /**
-     * Option for getTextRunCursor to compute the valid cursor at or after
-     * the offset or the limit of the context, whichever is less.
-     * @hide
+     * Option for getTextRunCursor.
+     *
+     * Compute the valid cursor at or after the offset or the limit of the context, whichever is
+     * less.
      */
     public static final int CURSOR_AT_OR_AFTER = 1;
 
      /**
-     * Option for getTextRunCursor to compute the valid cursor before
-     * offset or the start of the context, whichever is greater.
-     * @hide
+     * Option for getTextRunCursor.
+     *
+     * Compute the valid cursor before offset or the start of the context, whichever is greater.
      */
     public static final int CURSOR_BEFORE = 2;
 
    /**
-     * Option for getTextRunCursor to compute the valid cursor at or before
-     * offset or the start of the context, whichever is greater.
-     * @hide
+     * Option for getTextRunCursor.
+     *
+     * Compute the valid cursor at or before offset or the start of the context, whichever is
+     * greater.
      */
     public static final int CURSOR_AT_OR_BEFORE = 3;
 
     /**
-     * Option for getTextRunCursor to return offset if the cursor at offset
-     * is valid, or -1 if it isn't.
-     * @hide
+     * Option for getTextRunCursor.
+     *
+     * Return offset if the cursor at offset is valid, or -1 if it isn't.
      */
     public static final int CURSOR_AT = 4;
 
@@ -2410,34 +2422,32 @@
     }
 
     /**
-     * Returns the next cursor position in the run.  This avoids placing the
-     * cursor between surrogates, between characters that form conjuncts,
-     * between base characters and combining marks, or within a reordering
-     * cluster.
+     * Returns the next cursor position in the run.
      *
-     * <p>ContextStart and offset are relative to the start of text.
-     * The context is the shaping context for cursor movement, generally
-     * the bounds of the metric span enclosing the cursor in the direction of
-     * movement.
+     * This avoids placing the cursor between surrogates, between characters that form conjuncts,
+     * between base characters and combining marks, or within a reordering cluster.
      *
-     * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
-     * cursor position, this returns -1.  Otherwise this will never return a
-     * value before contextStart or after contextStart + contextLength.
+     * <p>
+     * ContextStart and offset are relative to the start of text.
+     * The context is the shaping context for cursor movement, generally the bounds of the metric
+     * span enclosing the cursor in the direction of movement.
+     *
+     * <p>
+     * If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid cursor position, this
+     * returns -1.  Otherwise this will never return a value before contextStart or after
+     * contextStart + contextLength.
      *
      * @param text the text
      * @param contextStart the start of the context
      * @param contextLength the length of the context
-     * @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
+     * @param isRtl true if the paragraph context is RTL, otherwise false
      * @param offset the cursor position to move from
-     * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
-     * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
-     * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
+     * @param cursorOpt how to move the cursor
      * @return the offset of the next position, or -1
-     * @hide
      */
-    @UnsupportedAppUsage
-    public int getTextRunCursor(char[] text, int contextStart, int contextLength,
-            int dir, int offset, int cursorOpt) {
+    public int getTextRunCursor(@NonNull char[] text, @IntRange(from = 0) int contextStart,
+            @IntRange(from = 0) int contextLength, boolean isRtl, @IntRange(from = 0) int offset,
+            @CursorOption int cursorOpt) {
         int contextEnd = contextStart + contextLength;
         if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
                 | (offset - contextStart) | (contextEnd - offset)
@@ -2446,85 +2456,87 @@
             throw new IndexOutOfBoundsException();
         }
 
-        return nGetTextRunCursor(mNativePaint, text, contextStart, contextLength, dir, offset,
-                cursorOpt);
+        return nGetTextRunCursor(mNativePaint, text, contextStart, contextLength,
+                isRtl ? DIRECTION_RTL : DIRECTION_LTR, offset, cursorOpt);
     }
 
     /**
-     * Returns the next cursor position in the run.  This avoids placing the
-     * cursor between surrogates, between characters that form conjuncts,
-     * between base characters and combining marks, or within a reordering
-     * cluster.
+     * Returns the next cursor position in the run.
      *
-     * <p>ContextStart, contextEnd, and offset are relative to the start of
+     * This avoids placing the cursor between surrogates, between characters that form conjuncts,
+     * between base characters and combining marks, or within a reordering cluster.
+     *
+     * <p>
+     * ContextStart, contextEnd, and offset are relative to the start of
      * text.  The context is the shaping context for cursor movement, generally
      * the bounds of the metric span enclosing the cursor in the direction of
      * movement.
      *
-     * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
-     * cursor position, this returns -1.  Otherwise this will never return a
-     * value before contextStart or after contextEnd.
+     * <p>
+     * If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid cursor position, this
+     * returns -1.  Otherwise this will never return a value before contextStart or after
+     * contextEnd.
      *
      * @param text the text
      * @param contextStart the start of the context
      * @param contextEnd the end of the context
-     * @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
+     * @param isRtl true if the paragraph context is RTL, otherwise false
      * @param offset the cursor position to move from
-     * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
-     * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
-     * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
+     * @param cursorOpt how to move the cursor
      * @return the offset of the next position, or -1
-     * @hide
      */
-    public int getTextRunCursor(CharSequence text, int contextStart,
-           int contextEnd, int dir, int offset, int cursorOpt) {
+    public int getTextRunCursor(@NonNull CharSequence text, @IntRange(from = 0) int contextStart,
+            @IntRange(from = 0) int contextEnd, boolean isRtl, @IntRange(from = 0) int offset,
+            @CursorOption int cursorOpt) {
 
         if (text instanceof String || text instanceof SpannedString ||
                 text instanceof SpannableString) {
             return getTextRunCursor(text.toString(), contextStart, contextEnd,
-                    dir, offset, cursorOpt);
+                    isRtl, offset, cursorOpt);
         }
         if (text instanceof GraphicsOperations) {
             return ((GraphicsOperations) text).getTextRunCursor(
-                    contextStart, contextEnd, dir, offset, cursorOpt, this);
+                    contextStart, contextEnd, isRtl, offset, cursorOpt, this);
         }
 
         int contextLen = contextEnd - contextStart;
         char[] buf = TemporaryBuffer.obtain(contextLen);
         TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
-        int relPos = getTextRunCursor(buf, 0, contextLen, dir, offset - contextStart, cursorOpt);
+        int relPos = getTextRunCursor(buf, 0, contextLen, isRtl, offset - contextStart, cursorOpt);
         TemporaryBuffer.recycle(buf);
         return (relPos == -1) ? -1 : relPos + contextStart;
     }
 
     /**
-     * Returns the next cursor position in the run.  This avoids placing the
-     * cursor between surrogates, between characters that form conjuncts,
-     * between base characters and combining marks, or within a reordering
-     * cluster.
+     * Returns the next cursor position in the run.
      *
-     * <p>ContextStart, contextEnd, and offset are relative to the start of
-     * text.  The context is the shaping context for cursor movement, generally
-     * the bounds of the metric span enclosing the cursor in the direction of
-     * movement.
+     * This avoids placing the cursor between surrogates, between characters that form conjuncts,
+     * between base characters and combining marks, or within a reordering cluster.
      *
-     * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
-     * cursor position, this returns -1.  Otherwise this will never return a
-     * value before contextStart or after contextEnd.
+     * <p>
+     * ContextStart, contextEnd, and offset are relative to the start of text.  The context is the
+     * shaping context for cursor movement, generally the bounds of the metric span enclosing the
+     * cursor in the direction of movement.
+     * </p>
+     *
+     * <p>
+     * If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid cursor position, this
+     * returns -1.  Otherwise this will never return a value before contextStart or after
+     * contextEnd.
+     * </p>
      *
      * @param text the text
      * @param contextStart the start of the context
      * @param contextEnd the end of the context
-     * @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
+     * @param isRtl true if the paragraph context is RTL, otherwise false.
      * @param offset the cursor position to move from
-     * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
-     * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
-     * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
+     * @param cursorOpt how to move the cursor
      * @return the offset of the next position, or -1
      * @hide
      */
-    public int getTextRunCursor(String text, int contextStart, int contextEnd,
-            int dir, int offset, int cursorOpt) {
+    public int getTextRunCursor(@NonNull String text, @IntRange(from = 0) int contextStart,
+            @IntRange(from = 0) int contextEnd, boolean isRtl, @IntRange(from = 0) int offset,
+            @CursorOption int cursorOpt) {
         if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
                 | (offset - contextStart) | (contextEnd - offset)
                 | (text.length() - contextEnd) | cursorOpt) < 0)
@@ -2532,8 +2544,8 @@
             throw new IndexOutOfBoundsException();
         }
 
-        return nGetTextRunCursor(mNativePaint, text, contextStart, contextEnd, dir, offset,
-                cursorOpt);
+        return nGetTextRunCursor(mNativePaint, text, contextStart, contextEnd,
+                isRtl ? DIRECTION_RTL : DIRECTION_LTR, offset, cursorOpt);
     }
 
     /**
@@ -2599,11 +2611,13 @@
      * Return in bounds (allocated by the caller) the smallest rectangle that
      * encloses all of the characters, with an implied origin at (0,0).
      *
+     * Note that styles are ignored even if you pass {@link android.text.Spanned} instance.
+     * Use {@link android.text.StaticLayout} for measuring bounds of {@link android.text.Spanned}.
+     *
      * @param text text to measure and return its bounds
      * @param start index of the first char in the text to measure
      * @param end 1 past the last char in the text to measure
      * @param bounds returns the unioned bounds of all the text. Must be allocated by the caller
-     * @hide
      */
     public void getTextBounds(CharSequence text, int start, int end, Rect bounds) {
         if ((start | end | (end - start) | (text.length() - end)) < 0) {
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index e6d2a6f..f2d50cd 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -146,7 +146,7 @@
                              frame[FrameInfoIndex::IntendedVsync] + mFrameInterval);
 
     // If we hit the deadline, cool!
-    if (frame[FrameInfoIndex::FrameCompleted] < mSwapDeadline) {
+    if (frame[FrameInfoIndex::FrameCompleted] < mSwapDeadline || totalDuration < mFrameInterval) {
         if (isTripleBuffered) {
             mData->reportJankType(JankType::kHighInputLatency);
             (*mGlobalData)->reportJankType(JankType::kHighInputLatency);
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 89827bc..7492aa6 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -1108,12 +1108,9 @@
 
     /**
      * Sets playback rate using {@link PlaybackParams}. The object sets its internal
-     * PlaybackParams to the input, except that the object remembers previous speed
-     * when input speed is zero. This allows the object to resume at previous speed
-     * when play() is called. Calling it before the object is prepared does not change
-     * the object state. After the object is prepared, calling it with zero speed is
-     * equivalent to calling pause(). After the object is prepared, calling it with
-     * non-zero speed is equivalent to calling play().
+     * PlaybackParams to the input. This allows the object to resume at previous speed
+     * when play() is called. Speed of zero is not allowed. Calling it does not change
+     * the object state.
      *
      * @param params the playback params.
      */
diff --git a/packages/SystemUI/res/layout/recents_onboarding.xml b/packages/SystemUI/res/layout/recents_onboarding.xml
index adf1e74..2538612 100644
--- a/packages/SystemUI/res/layout/recents_onboarding.xml
+++ b/packages/SystemUI/res/layout/recents_onboarding.xml
@@ -37,7 +37,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:layout_gravity="center_vertical"
-            android:textColor="@android:color/white"
+            android:textColor="?attr/wallpaperTextColor"
             android:textSize="16sp"/>
         <ImageView
             android:id="@+id/dismiss"
@@ -49,6 +49,7 @@
             android:layout_marginEnd="2dp"
             android:alpha="0.7"
             android:src="@drawable/ic_close_white"
+            android:tint="?attr/wallpaperTextColor"
             android:background="?android:attr/selectableItemBackgroundBorderless"
             android:contentDescription="@string/accessibility_desc_close"/>
     </LinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index f7615e6..d8f7b61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -121,7 +121,8 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+        Dependency.get(StatusBarStateController.class)
+                .addListener(mStateListener, StatusBarStateController.RANK_SHELF);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
index 7a69f2e..d6719f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
@@ -16,42 +16,70 @@
 
 package com.android.systemui.statusbar;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
 import android.util.ArraySet;
+import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+import java.lang.annotation.Retention;
+import java.util.ArrayList;
+import java.util.Comparator;
 
 /**
  * Tracks and reports on {@link StatusBarState}.
  */
 public class StatusBarStateController {
+    private static final String TAG = "SbStateController";
 
     private static final int MAX_STATE = StatusBarState.FULLSCREEN_USER_SWITCHER;
     private static final int MIN_STATE = StatusBarState.SHADE;
 
-    private final ArraySet<StateListener> mListeners = new ArraySet<>();
+    private static final Comparator <RankedListener> mComparator
+            = (o1, o2) -> Integer.compare(o1.rank, o2.rank);
+
+    private final ArrayList<RankedListener> mListeners = new ArrayList<>();
     private int mState;
     private int mLastState;
     private boolean mLeaveOpenOnKeyguardHide;
 
+    // TODO: b/115739177 (remove this explicit ordering if we can)
+    @Retention(SOURCE)
+    @IntDef({RANK_STATUS_BAR, RANK_STATUS_BAR_WINDOW_CONTROLLER, RANK_STACK_SCROLLER, RANK_SHELF})
+    public @interface SbStateListenerRank {}
+    // This is the set of known dependencies when updating StatusBarState
+    public static final int RANK_STATUS_BAR = 0;
+    public static final int RANK_STATUS_BAR_WINDOW_CONTROLLER = 1;
+    public static final int RANK_STACK_SCROLLER = 2;
+    public static final int RANK_SHELF = 3;
+
     public int getState() {
         return mState;
     }
 
-    public void setState(int state) {
+    public boolean setState(int state) {
         if (state > MAX_STATE || state < MIN_STATE) {
             throw new IllegalArgumentException("Invalid state " + state);
         }
         if (state == mState) {
-            return;
+            return false;
         }
         synchronized (mListeners) {
-            for (StateListener listener : new ArraySet<>(mListeners)) {
-                listener.onStatePreChange(mState, state);
+            for (RankedListener rl : new ArrayList<>(mListeners)) {
+                rl.listener.onStatePreChange(mState, state);
             }
             mLastState = mState;
             mState = state;
-            for (StateListener listener : new ArraySet<>(mListeners)) {
-                listener.onStateChanged(mState);
+            for (RankedListener rl : new ArrayList<>(mListeners)) {
+                rl.listener.onStateChanged(mState);
+            }
+
+            for (RankedListener rl : new ArrayList<>(mListeners)) {
+                rl.listener.onStatePostChange();
             }
         }
+
+        return true;
     }
 
     public boolean goingToFullShade() {
@@ -72,20 +100,67 @@
 
     public void addListener(StateListener listener) {
         synchronized (mListeners) {
-            mListeners.add(listener);
+            addListenerInternalLocked(listener, Integer.MAX_VALUE);
         }
     }
 
+    /**
+     * Add a listener and a rank based on the priority of this message
+     * @param listener the listener
+     * @param rank the order in which you'd like to be called. Ranked listeners will be
+     * notified before unranked, and we will sort ranked listeners from low to high
+     *
+     * @deprecated This method exists only to solve latent inter-dependencies from refactoring
+     * StatusBarState out of StatusBar.java. Any new listeners should be built not to need ranking
+     * (i.e., they are non-dependent on the order of operations of StatusBarState listeners).
+     */
+    public void addListener(StateListener listener, @SbStateListenerRank int rank) {
+        synchronized (mListeners) {
+            addListenerInternalLocked(listener, rank);
+        }
+    }
+
+    @GuardedBy("mListeners")
+    private void addListenerInternalLocked(StateListener listener, int rank) {
+        // Protect against double-subscribe
+        for (RankedListener rl : mListeners) {
+            if (rl.listener.equals(listener)) {
+                return;
+            }
+        }
+
+        RankedListener rl = new RankedListener(listener, rank);
+        mListeners.add(rl);
+        mListeners.sort(mComparator);
+    }
+
     public void removeListener(StateListener listener) {
         synchronized (mListeners) {
-            mListeners.remove(listener);
+            mListeners.removeIf((it) -> it.listener.equals(listener));
         }
     }
 
+    public static String describe(int state) {
+        return StatusBarState.toShortString(state);
+    }
+
     public interface StateListener {
         public default void onStatePreChange(int oldState, int newState) {
         }
 
+        public default void onStatePostChange() {
+        }
+
         public void onStateChanged(int newState);
     }
+
+    private class RankedListener {
+        private final StateListener listener;
+        private final int rank;
+
+        private RankedListener(StateListener l, int r) {
+            listener = l;
+            rank = r;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index a725a0b..da98565 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -620,7 +620,8 @@
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+        Dependency.get(StatusBarStateController.class)
+                .addListener(mStateListener, StatusBarStateController.RANK_STACK_SCROLLER);
         Dependency.get(ConfigurationController.class).addCallback(this);
     }
 
@@ -4248,8 +4249,9 @@
         mDimAnimator.addUpdateListener(mDimUpdateListener);
         mDimAnimator.start();
     }
+
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    public void setHideSensitive(boolean hideSensitive, boolean animate) {
+    private void setHideSensitive(boolean hideSensitive, boolean animate) {
         if (hideSensitive != mAmbientState.isHideSensitive()) {
             int childCount = getChildCount();
             for (int i = 0; i < childCount; i++) {
@@ -5008,8 +5010,12 @@
     private void setStatusBarState(int statusBarState) {
         mStatusBarState = statusBarState;
         mAmbientState.setStatusBarState(statusBarState);
+    }
+
+    private void onStatePostChange() {
         boolean onKeyguard = onKeyguard();
         boolean publicMode = mLockscreenUserManager.isAnyProfilePublicMode();
+
         if (mHeadsUpAppearanceController != null) {
             mHeadsUpAppearanceController.setPublicMode(publicMode);
         }
@@ -5026,6 +5032,8 @@
         updateFooter();
         updateChildren();
         onUpdateRowStates();
+
+        mEntryManager.updateNotifications();
     }
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5949,5 +5957,10 @@
         public void onStateChanged(int newState) {
             setStatusBarState(newState);
         }
-    };
+
+      @Override
+      public void onStatePostChange() {
+          NotificationStackScrollLayout.this.onStatePostChange();
+      }
+  };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 459b4d7..759e8ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -632,7 +632,7 @@
 
         mColorExtractor = Dependency.get(SysuiColorExtractor.class);
         mColorExtractor.addOnColorsChangedListener(this);
-        mStatusBarStateController.addListener(this);
+        mStatusBarStateController.addListener(this, StatusBarStateController.RANK_STATUS_BAR);
 
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
 
@@ -3453,7 +3453,14 @@
         mIsKeyguard = false;
         Trace.beginSection("StatusBar#hideKeyguard");
         boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
-        mStatusBarStateController.setState(StatusBarState.SHADE);
+        if (!(mStatusBarStateController.setState(StatusBarState.SHADE))) {
+            //TODO: StatusBarStateController should probably know about hiding the keyguard and
+            // notify listeners.
+
+            // If the state didn't change, we may still need to update public mode
+            updatePublicMode();
+            mEntryManager.updateNotifications();
+        }
         View viewToClick = null;
         if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
             if (!mKeyguardRequested) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 51a5df2..57c7e28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -93,7 +93,8 @@
         mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
         mDozeParameters = dozeParameters;
         mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
-        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+        Dependency.get(StatusBarStateController.class).addListener(
+                mStateListener, StatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER);
         Dependency.get(ConfigurationController.class).addCallback(this);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 0adb439..29a6b95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -403,7 +403,7 @@
                 boolean hasCACerts = !(conn.getService().getUserCaAliases().getList().isEmpty());
                 return new Pair<Integer, Boolean>(userId[0], hasCACerts);
             } catch (RemoteException | InterruptedException | AssertionError e) {
-                Log.i(TAG, e.getMessage());
+                Log.i(TAG, "failed to get CA certs", e);
                 new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed(
                         () -> new CACertLoader().execute(userId[0]),
                         CA_CERT_LOADING_RETRY_TIME_IN_MS);
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index b71d7a7..da52d40 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1834,7 +1834,7 @@
 
                 if (provider.widgets.isEmpty()) {
                     // cancel the future updates
-                    cancelBroadcasts(provider);
+                    cancelBroadcastsLocked(provider);
 
                     // send the broacast saying that the provider is not in use any more
                     sendDisabledIntentLocked(provider);
@@ -1843,18 +1843,16 @@
         }
     }
 
-    private void cancelBroadcasts(Provider provider) {
+    private void cancelBroadcastsLocked(Provider provider) {
         if (DEBUG) {
-            Slog.i(TAG, "cancelBroadcasts() for " + provider);
+            Slog.i(TAG, "cancelBroadcastsLocked() for " + provider);
         }
         if (provider.broadcast != null) {
-            mAlarmManager.cancel(provider.broadcast);
-            long token = Binder.clearCallingIdentity();
-            try {
-                provider.broadcast.cancel();
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
+            final PendingIntent broadcast = provider.broadcast;
+            mSaveStateHandler.post(() -> {
+                    mAlarmManager.cancel(broadcast);
+                    broadcast.cancel();
+            });
             provider.broadcast = null;
         }
     }
@@ -2315,7 +2313,7 @@
         mProviders.remove(provider);
 
         // no need to send the DISABLE broadcast, since the receiver is gone anyway
-        cancelBroadcasts(provider);
+        cancelBroadcastsLocked(provider);
     }
 
     private void sendEnableIntentLocked(Provider p) {
@@ -2369,17 +2367,14 @@
                 Binder.restoreCallingIdentity(token);
             }
             if (!alreadyRegistered) {
-                long period = provider.info.updatePeriodMillis;
-                if (period < MIN_UPDATE_PERIOD) {
-                    period = MIN_UPDATE_PERIOD;
-                }
-                final long oldId = Binder.clearCallingIdentity();
-                try {
+                // Set the alarm outside of our locks; we've latched the first-time
+                // invariant and established the PendingIntent safely.
+                final long period = Math.max(provider.info.updatePeriodMillis, MIN_UPDATE_PERIOD);
+                final PendingIntent broadcast = provider.broadcast;
+                mSaveStateHandler.post(() ->
                     mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                            SystemClock.elapsedRealtime() + period, period, provider.broadcast);
-                } finally {
-                    Binder.restoreCallingIdentity(oldId);
-                }
+                            SystemClock.elapsedRealtime() + period, period, broadcast)
+                );
             }
         }
     }
@@ -3382,7 +3377,7 @@
                             // Reschedule for the new updatePeriodMillis (don't worry about handling
                             // it specially if updatePeriodMillis didn't change because we just sent
                             // an update, and the next one will be updatePeriodMillis from now).
-                            cancelBroadcasts(provider);
+                            cancelBroadcastsLocked(provider);
                             registerForBroadcastsLocked(provider, appWidgetIds);
                             // If it's currently showing, call back with the new
                             // AppWidgetProviderInfo.
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 9af952d..c933833 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -105,7 +105,7 @@
                 try {
                     IBackupTransport transport =
                             transportClient.connectOrThrow(
-                                    "AppBackupUtils.appIsEligibleForBackupAtRuntime");
+                                    "AppBackupUtils.appIsRunningAndEligibleForBackupWithTransport");
                     return transport.isAppEligibleForBackup(
                             packageInfo, AppBackupUtils.appGetsFullBackup(packageInfo));
                 } catch (Exception e) {
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 380f6a7..a69d416 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1490,23 +1490,19 @@
         }
     }
 
-    private static final String TUNNEL_OP = "STOPSHIP"; // = AppOpsManager.OP_MANAGE_IPSEC_TUNNELS;
+    private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS;
 
     private void enforceTunnelPermissions(String callingPackage) {
         checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
-        if (false) { // STOPSHIP if this line is present
-            switch (getAppOpsManager().noteOp(
-                        TUNNEL_OP,
-                        Binder.getCallingUid(), callingPackage)) {
-                case AppOpsManager.MODE_DEFAULT:
-                    mContext.enforceCallingOrSelfPermission(
-                            android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
-                    break;
-                case AppOpsManager.MODE_ALLOWED:
-                    return;
-                default:
-                    throw new SecurityException("Request to ignore AppOps for non-legacy API");
-            }
+        switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
+            case AppOpsManager.MODE_DEFAULT:
+                mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
+                break;
+            case AppOpsManager.MODE_ALLOWED:
+                return;
+            default:
+                throw new SecurityException("Request to ignore AppOps for non-legacy API");
         }
     }
 
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index cb03255..f436286 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -42,31 +42,25 @@
 import android.os.ServiceManager;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.dreams.Sandman;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
-import android.text.TextUtils;
 import android.util.Slog;
 
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-
 import com.android.internal.R;
 import com.android.internal.app.DisableCarModeActivity;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.DumpUtils;
-import com.android.server.power.ShutdownThread;
 import com.android.server.twilight.TwilightListener;
 import com.android.server.twilight.TwilightManager;
 import com.android.server.twilight.TwilightState;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 final class UiModeManagerService extends SystemService {
     private static final String TAG = UiModeManager.class.getSimpleName();
     private static final boolean LOG = false;
@@ -466,7 +460,7 @@
             uiMode |= mNightMode << 4;
         }
 
-        if (mPowerSave && !mNightModeLocked) {
+        if (mPowerSave) {
             uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
             uiMode |= Configuration.UI_MODE_NIGHT_YES;
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7533db1..b898a90 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8406,10 +8406,17 @@
         }
     }
 
+    /** @deprecated - Use {@link #removeContentProviderExternalAsUser} which takes a user ID. */
+    @Deprecated
+    @Override
     public void removeContentProviderExternal(String name, IBinder token) {
+        removeContentProviderExternalAsUser(name, token, UserHandle.getCallingUserId());
+    }
+
+    @Override
+    public void removeContentProviderExternalAsUser(String name, IBinder token, int userId) {
         enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
             "Do not have permission in call removeContentProviderExternal()");
-        int userId = UserHandle.getCallingUserId();
         long ident = Binder.clearCallingIdentity();
         try {
             removeContentProviderExternalUnchecked(name, token, userId);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 628207c..2199bb7 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -17,18 +17,18 @@
 package com.android.server.am;
 
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
 import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
 import static android.app.ActivityOptions.ANIM_CUSTOM;
+import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
 import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
 import static android.app.ActivityOptions.ANIM_SCALE_UP;
 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
-import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
@@ -81,6 +81,8 @@
 import static android.os.Build.VERSION_CODES.O;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
+
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
@@ -93,6 +95,13 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
+import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
+import static com.android.server.am.ActivityRecordProto.PROC_ID;
+import static com.android.server.am.ActivityRecordProto.STATE;
+import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
+import static com.android.server.am.ActivityRecordProto.VISIBLE;
 import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
@@ -110,14 +119,6 @@
 import static com.android.server.am.TaskPersister.DEBUG;
 import static com.android.server.am.TaskPersister.IMAGE_EXTENSION;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
-import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
-import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
-import static com.android.server.am.ActivityRecordProto.PROC_ID;
-import static com.android.server.am.ActivityRecordProto.STATE;
-import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
-import static com.android.server.am.ActivityRecordProto.VISIBLE;
-import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
 import static com.android.server.wm.IdentifierProto.USER_ID;
@@ -132,6 +133,7 @@
 import android.app.PendingIntent;
 import android.app.PictureInPictureParams;
 import android.app.ResultInfo;
+import android.app.servertransaction.ActivityConfigurationChangeItem;
 import android.app.servertransaction.ActivityLifecycleItem;
 import android.app.servertransaction.ActivityRelaunchItem;
 import android.app.servertransaction.ClientTransaction;
@@ -143,7 +145,6 @@
 import android.app.servertransaction.PipModeChangeItem;
 import android.app.servertransaction.ResumeActivityItem;
 import android.app.servertransaction.WindowVisibilityItem;
-import android.app.servertransaction.ActivityConfigurationChangeItem;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -1279,20 +1280,14 @@
 
     /**
      * Check whether this activity can be launched on the specified display.
+     *
      * @param displayId Target display id.
-     * @return {@code true} if either it is the default display or this activity is resizeable and
-     *         can be put a secondary screen.
+     * @return {@code true} if either it is the default display or this activity can be put on a
+     *         secondary screen.
      */
     boolean canBeLaunchedOnDisplay(int displayId) {
-        final TaskRecord task = getTask();
-
-        // The resizeability of an Activity's parent task takes precendence over the ActivityInfo.
-        // This allows for a non resizable activity to be launched into a resizeable task.
-        final boolean resizeable =
-                task != null ? task.isResizeable() : supportsResizeableMultiWindow();
-
-        return service.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
-                resizeable, launchedFromPid, launchedFromUid, info);
+        return service.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
+                launchedFromUid, info);
     }
 
     /**
@@ -2495,6 +2490,14 @@
         }
     }
 
+    /**
+     * @return {@code true} if this activity was reparented to another display but
+     *         {@link #ensureActivityConfiguration} is not called.
+     */
+    boolean shouldUpdateConfigForDisplayChanged() {
+        return mLastReportedDisplayId != getDisplayId();
+    }
+
     boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
         return ensureActivityConfiguration(globalChanges, preserveWindow,
                 false /* ignoreStopState */);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index aa4e68d..91e677b 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -5375,12 +5375,14 @@
         display.positionChildAtTop(this, false /* includingParents */);
     }
 
+    /** NOTE: Should only be called from {@link TaskRecord#reparent}. */
     void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume,
             boolean setPause, String reason) {
         if (!moveToFront) {
             return;
         }
 
+        final ActivityState origState = r.getState();
         // If the activity owns the last resumed activity, transfer that together,
         // so that we don't resume the same activity again in the new stack.
         // Apps may depend on onResume()/onPause() being called in pairs.
@@ -5393,9 +5395,14 @@
             mPausingActivity = r;
             schedulePauseTimeout(r);
         }
-        // Move the stack in which we are placing the activity to the front. The call will also
-        // make sure the activity focus is set.
+        // Move the stack in which we are placing the activity to the front.
         moveToFront(reason);
+        // If the original state is resumed, there is no state change to update focused app.
+        // So here makes sure the activity focus is set if it is the top.
+        if (origState == RESUMED && r == mStackSupervisor.getTopResumedActivity()) {
+            // TODO(b/111361570): Support multiple focused apps in WM
+            mService.setResumedActivityUncheckLocked(r, reason);
+        }
     }
 
     public int getStackId() {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 310898e..8649e83 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -488,8 +488,8 @@
     }
 
     /** Check if placing task or activity on specified display is allowed. */
-    boolean canPlaceEntityOnDisplay(int displayId, boolean resizeable, int callingPid,
-            int callingUid, ActivityInfo activityInfo) {
+    boolean canPlaceEntityOnDisplay(int displayId, int callingPid, int callingUid,
+            ActivityInfo activityInfo) {
         if (displayId == DEFAULT_DISPLAY) {
             // No restrictions for the default display.
             return true;
@@ -498,10 +498,6 @@
             // Can't launch on secondary displays if feature is not supported.
             return false;
         }
-        if (!resizeable && !displayConfigMatchesGlobal(displayId)) {
-            // Can't apply wrong configuration to non-resizeable activities.
-            return false;
-        }
         if (!isCallerAllowedToLaunchOnDisplay(callingPid, callingUid, displayId, activityInfo)) {
             // Can't place activities to a display that has restricted launch rules.
             // In this case the request should be made by explicitly adding target display id and
@@ -4530,11 +4526,14 @@
             mService.setTaskWindowingMode(task.taskId,
                     WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
             if (preferredDisplayId != actualDisplayId) {
-                // Display a warning toast that we tried to put a non-resizeable task on a secondary
-                // display with config different from global config.
+                Slog.w(TAG, "Failed to put " + task + " on display " + preferredDisplayId);
+                // Display a warning toast that we failed to put a task on a secondary display.
                 mService.getTaskChangeNotificationController()
                         .notifyActivityLaunchOnSecondaryDisplayFailed();
                 return;
+            } else if (!forceNonResizable && handleForcedResizableTask(task,
+                    FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY)) {
+                return;
             }
         }
 
@@ -4554,16 +4553,23 @@
             return;
         }
 
+        handleForcedResizableTask(task, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN);
+    }
+
+    /**
+     * @return {@code true} if the top activity of the task is forced to be resizable and the user
+     *         was notified about activity being forced resized.
+     */
+    private boolean handleForcedResizableTask(TaskRecord task, int reason) {
         final ActivityRecord topActivity = task.getTopActivity();
         if (topActivity != null && topActivity.isNonResizableOrForcedResizable()
-            && !topActivity.noDisplay) {
+                && !topActivity.noDisplay) {
             final String packageName = topActivity.appInfo.packageName;
-            final int reason = isSecondaryDisplayPreferred
-                    ? FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY
-                    : FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
             mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
                     task.taskId, reason, packageName);
+            return true;
         }
+        return false;
     }
 
     void activityRelaunchedLocked(IBinder token) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index bcb2b9b..7df255d 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -945,7 +945,8 @@
                 auxiliaryResponse == null ? null : auxiliaryResponse.filters);
     }
 
-    void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
+    void postStartActivityProcessing(ActivityRecord r, int result,
+            ActivityStack startedActivityStack) {
         if (ActivityManager.isStartResultFatalError(result)) {
             return;
         }
@@ -957,14 +958,6 @@
         // about this, so it waits for the new activity to become visible instead.
         mSupervisor.reportWaitingActivityLaunchedIfNeeded(r, result);
 
-        ActivityStack startedActivityStack = null;
-        final ActivityStack currentStack = r.getStack();
-        if (currentStack != null) {
-            startedActivityStack = currentStack;
-        } else if (mTargetStack != null) {
-            startedActivityStack = targetStack;
-        }
-
         if (startedActivityStack == null) {
             return;
         }
@@ -1240,23 +1233,41 @@
                 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                 ActivityRecord[] outActivity) {
         int result = START_CANCELED;
+        final ActivityStack startedActivityStack;
         try {
             mService.mWindowManager.deferSurfaceLayout();
             result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                     startFlags, doResume, options, inTask, outActivity);
         } finally {
-            // If we are not able to proceed, disassociate the activity from the task. Leaving an
-            // activity in an incomplete state can lead to issues, such as performing operations
-            // without a window container.
-            final ActivityStack stack = mStartActivity.getStack();
-            if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
-                stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
-                        null /* intentResultData */, "startActivity", true /* oomAdj */);
+            final ActivityStack currentStack = r.getStack();
+            startedActivityStack = currentStack != null ? currentStack : mTargetStack;
+
+            if (ActivityManager.isStartResultSuccessful(result)) {
+                if (startedActivityStack != null) {
+                    // If there is no state change (e.g. a resumed activity is reparented to
+                    // top of another display) to trigger a visibility/configuration checking,
+                    // we have to update the configuration for changing to different display.
+                    final ActivityRecord currentTop =
+                            startedActivityStack.topRunningActivityLocked();
+                    if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
+                        mSupervisor.ensureVisibilityAndConfig(currentTop, currentTop.getDisplayId(),
+                                true /* markFrozenIfConfigChanged */, false /* deferResume */);
+                    }
+                }
+            } else {
+                // If we are not able to proceed, disassociate the activity from the task.
+                // Leaving an activity in an incomplete state can lead to issues, such as
+                // performing operations without a window container.
+                final ActivityStack stack = mStartActivity.getStack();
+                if (stack != null) {
+                    stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
+                            null /* intentResultData */, "startActivity", true /* oomAdj */);
+                }
             }
             mService.mWindowManager.continueSurfaceLayout();
         }
 
-        postStartActivityProcessing(r, result, mTargetStack);
+        postStartActivityProcessing(r, result, startedActivityStack);
 
         return result;
     }
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 212844a..6935703d 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -4688,11 +4688,7 @@
         return mSleeping;
     }
 
-    /**
-     * Update AMS states when an activity is resumed. This should only be called by
-     * {@link ActivityStack#onActivityStateChanged(
-     * ActivityRecord, ActivityStack.ActivityState, String)} when an activity is resumed.
-     */
+    /** Update AMS states when an activity is resumed. */
     void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
         final TaskRecord task = r.getTask();
         if (task.isActivityTypeStandard()) {
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index f9dccea0..aad890b 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -22,6 +22,7 @@
 
 import android.annotation.Nullable;
 import android.os.FileUtils;
+import android.os.SystemProperties;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -38,6 +39,10 @@
 final class MemoryStatUtil {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "MemoryStatUtil" : TAG_AM;
 
+    /** True if device has per-app memcg */
+    private static final Boolean DEVICE_HAS_PER_APP_MEMCG =
+            SystemProperties.getBoolean("ro.config.per_app_memcg", false);
+
     /** Path to check if device has memcg */
     private static final String MEMCG_TEST_PATH = "/dev/memcg/apps/memory.stat";
     /** Path to memory stat file for logging app start memory state */
@@ -55,15 +60,12 @@
     private static final int PGMAJFAULT_INDEX = 11;
     private static final int RSS_IN_BYTES_INDEX = 23;
 
-    /** True if device has memcg */
-    private static volatile Boolean sDeviceHasMemCg;
-
     private MemoryStatUtil() {}
 
     /**
      * Reads memory stat for a process.
      *
-     * Reads from memcg if available on device, else fallback to procfs.
+     * Reads from per-app memcg if available on device, else fallback to procfs.
      * Returns null if no stats can be read.
      */
     @Nullable
@@ -156,15 +158,10 @@
     }
 
     /**
-     * Checks if memcg is available on device.
-     *
-     * Touches the filesystem to do the check.
+     * Returns whether per-app memcg is available on device.
      */
     static boolean hasMemcg() {
-        if (sDeviceHasMemCg == null) {
-            sDeviceHasMemCg = (new File(MEMCG_TEST_PATH)).exists();
-        }
-        return sDeviceHasMemCg;
+        return DEVICE_HAS_PER_APP_MEMCG;
     }
 
     static final class MemoryStat {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 7256e23..9b42d65 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1521,14 +1521,14 @@
 
     /**
      * Check whether this task can be launched on the specified display.
+     *
      * @param displayId Target display id.
-     * @return {@code true} if either it is the default display or this activity is resizeable and
-     *         can be put a secondary screen.
+     * @return {@code true} if either it is the default display or this activity can be put on a
+     *         secondary display.
      */
     boolean canBeLaunchedOnDisplay(int displayId) {
         return mService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
-                isResizeable(false /* checkSupportsPip */), -1 /* don't check PID */,
-                -1 /* don't check UID */, null /* activityInfo */);
+                -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
     }
 
     /**
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index c028a43..873a8e3 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -639,12 +639,20 @@
             }
         }
 
-        // Otherwise only focused applications can access the clipboard.
-        boolean uidFocused = mWm.isUidFocused(callingUid);
-        if (!uidFocused) {
-            Slog.e(TAG, "Denying clipboard access to " + callingPackage
-                    + ", application is not in focus.");
+        switch (op) {
+            case AppOpsManager.OP_READ_CLIPBOARD:
+                // Clipboard can only be read by applications with focus.
+                boolean uidFocused = mWm.isUidFocused(callingUid);
+                if (!uidFocused) {
+                    Slog.e(TAG, "Denying clipboard access to " + callingPackage
+                            + ", application is not in focus.");
+                }
+                return uidFocused;
+            case AppOpsManager.OP_WRITE_CLIPBOARD:
+                // Writing is allowed without focus.
+                return true;
+            default:
+                throw new IllegalArgumentException("Unknown clipboard appop " + op);
         }
-        return uidFocused;
     }
 }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index b2287ac..a0432011 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2536,7 +2536,11 @@
                     // We need to check if this is the current client with
                     // focus in the window manager, to allow this call to
                     // be made before input is started in it.
-                    if (!mWindowManagerInternal.inputMethodClientHasFocus(client)) {
+                    final ClientState cs = mClients.get(client.asBinder());
+                    if (cs == null) {
+                        throw new IllegalArgumentException("unknown client " + client.asBinder());
+                    }
+                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) {
                         Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
                         return false;
                     }
@@ -2616,7 +2620,11 @@
                     // We need to check if this is the current client with
                     // focus in the window manager, to allow this call to
                     // be made before input is started in it.
-                    if (!mWindowManagerInternal.inputMethodClientHasFocus(client)) {
+                    final ClientState cs = mClients.get(client.asBinder());
+                    if (cs == null) {
+                        throw new IllegalArgumentException("unknown client " + client.asBinder());
+                    }
+                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) {
                         if (DEBUG) {
                             Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client);
                         }
@@ -2734,7 +2742,7 @@
                             + client.asBinder());
                 }
 
-                if (!mWindowManagerInternal.inputMethodClientHasFocus(cs.client)) {
+                if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) {
                     // Check with the window manager to make sure this client actually
                     // has a window with focus.  If not, reject.  This is thread safe
                     // because if the focus changes some time before or after, the
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index 44b9c15..3b11525 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -378,7 +378,7 @@
         for (int i = newIntents.size() - 1; i >= 0; --i) {
             final PackageParser.ActivityIntentInfo intentInfo = newIntents.get(i);
             final PackageParser.Package disabledPkg = sPackageManagerInternal
-                    .getDisabledPackage(intentInfo.activity.info.packageName);
+                    .getDisabledSystemPackage(intentInfo.activity.info.packageName);
             final List<PackageParser.Activity> systemActivities =
                     disabledPkg != null ? disabledPkg.activities : null;
             adjustPriority(systemActivities, intentInfo, setupWizardPackage);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index db0c13c..91af0ec 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -718,6 +718,8 @@
     @GuardedBy("mPackages")
     final private ArraySet<PackageListObserver> mPackageListObservers = new ArraySet<>();
 
+    private PackageManager mPackageManager;
+
     class PackageParserCallback implements PackageParser.Callback {
         @Override public final boolean hasFeature(String feature) {
             return PackageManagerService.this.hasSystemFeature(feature, 0);
@@ -22236,6 +22238,22 @@
         }
 
         @Override
+        public boolean isPlatformSigned(String packageName) {
+            PackageSetting packageSetting = mSettings.mPackages.get(packageName);
+            if (packageSetting == null) {
+                return false;
+            }
+            PackageParser.Package pkg = packageSetting.pkg;
+            if (pkg == null) {
+                // May happen if package in on a removable sd card
+                return false;
+            }
+            return pkg.mSigningDetails.hasAncestorOrSelf(mPlatformPackage.mSigningDetails)
+                    || mPlatformPackage.mSigningDetails.checkCapability(pkg.mSigningDetails,
+                    PackageParser.SigningDetails.CertCapabilities.PERMISSION);
+        }
+
+        @Override
         public boolean isDataRestoreSafe(byte[] restoringFromSigHash, String packageName) {
             SigningDetails sd = getSigningDetails(packageName);
             if (sd == null) {
@@ -22347,7 +22365,7 @@
         }
 
         @Override
-        public PackageParser.Package getDisabledPackage(String packageName) {
+        public PackageParser.Package getDisabledSystemPackage(String packageName) {
             synchronized (mPackages) {
                 final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                 return (ps != null) ? ps.pkg : null;
@@ -22355,6 +22373,12 @@
         }
 
         @Override
+        public @Nullable String getDisabledSystemPackageName(@NonNull String packageName) {
+            PackageParser.Package pkg = getDisabledSystemPackage(packageName);
+            return pkg == null ? null : pkg.packageName;
+        }
+
+        @Override
         public String getKnownPackageName(int knownPackage, int userId) {
             switch(knownPackage) {
                 case PackageManagerInternal.PACKAGE_BROWSER:
@@ -22392,21 +22416,6 @@
         }
 
         @Override
-        public void setSmsAppPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionPolicy.setSmsAppPackagesProvider(provider);
-        }
-
-        @Override
-        public void setDialerAppPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionPolicy.setDialerAppPackagesProvider(provider);
-        }
-
-        @Override
-        public void setSimCallManagerPackagesProvider(PackagesProvider provider) {
-            mDefaultPermissionPolicy.setSimCallManagerPackagesProvider(provider);
-        }
-
-        @Override
         public void setUseOpenWifiAppPackagesProvider(PackagesProvider provider) {
             mDefaultPermissionPolicy.setUseOpenWifiAppPackagesProvider(provider);
         }
@@ -22417,22 +22426,10 @@
         }
 
         @Override
-        public void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId) {
-            mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultSmsApp(packageName, userId);
-        }
-
-        @Override
-        public void grantDefaultPermissionsToDefaultDialerApp(String packageName, int userId) {
+        public void onDefaultDialerAppChanged(String packageName, int userId) {
             synchronized (mPackages) {
                 mSettings.setDefaultDialerPackageNameLPw(packageName, userId);
             }
-            mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultDialerApp(packageName, userId);
-        }
-
-        @Override
-        public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
-            mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultSimCallManager(
-                    packageName, userId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 846c7b7..3c9dd63 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -23,12 +23,13 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.DownloadManager;
+import android.app.SearchManager;
 import android.app.admin.DevicePolicyManager;
 import android.companion.CompanionDeviceManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageList;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManagerInternal.PackagesProvider;
@@ -53,6 +54,7 @@
 import android.provider.MediaStore;
 import android.provider.Telephony.Sms.Intents;
 import android.security.Credentials;
+import android.speech.RecognitionService;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -61,6 +63,7 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.server.LocalServices;
 
@@ -73,6 +76,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -94,10 +98,15 @@
     private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars
     private static final boolean DEBUG = false;
 
-    private static final int DEFAULT_FLAGS =
+    @PackageManager.ResolveInfoFlags
+    private static final int DEFAULT_INTENT_QUERY_FLAGS =
             PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                     | PackageManager.MATCH_UNINSTALLED_PACKAGES;
 
+    @PackageManager.PackageInfoFlags
+    private static final int DEFAULT_PACKAGE_INFO_QUERY_FLAGS =
+            PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS;
+
     private static final String AUDIO_MIME_TYPE = "audio/mpeg";
 
     private static final String TAG_EXCEPTIONS = "exceptions";
@@ -108,6 +117,8 @@
     private static final String ATTR_FIXED = "fixed";
 
     private static final Set<String> PHONE_PERMISSIONS = new ArraySet<>();
+
+
     static {
         PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE);
         PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE);
@@ -219,7 +230,7 @@
     private final DefaultPermissionGrantedCallback mPermissionGrantedCallback;
     public interface DefaultPermissionGrantedCallback {
         /** Callback when permissions have been granted */
-        public void onDefaultRuntimePermissionsGranted(int userId);
+        void onDefaultRuntimePermissionsGranted(int userId);
     }
 
     public DefaultPermissionGrantPolicy(Context context, Looper looper,
@@ -291,9 +302,9 @@
         grantDefaultPermissionExceptions(userId);
     }
 
-    private void grantRuntimePermissionsForPackage(int userId, PackageParser.Package pkg) {
+    private void grantRuntimePermissionsForSystemPackage(int userId, PackageInfo pkg) {
         Set<String> permissions = new ArraySet<>();
-        for (String permission :  pkg.requestedPermissions) {
+        for (String permission : pkg.requestedPermissions) {
             final BasePermission bp = mPermissionManager.getPermission(permission);
             if (bp == null) {
                 continue;
@@ -307,36 +318,71 @@
         }
     }
 
-    private void grantAllRuntimePermissions(int userId) {
-        Log.i(TAG, "Granting all runtime permissions for user " + userId);
-        final PackageList packageList = mServiceInternal.getPackageList();
-        for (String packageName : packageList.getPackageNames()) {
-            final PackageParser.Package pkg = mServiceInternal.getPackage(packageName);
-            if (pkg == null) {
-                continue;
-            }
-            grantRuntimePermissionsForPackage(userId, pkg);
-        }
-    }
-
     public void scheduleReadDefaultPermissionExceptions() {
         mHandler.sendEmptyMessage(MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS);
     }
 
     private void grantPermissionsToSysComponentsAndPrivApps(int userId) {
         Log.i(TAG, "Granting permissions to platform components for user " + userId);
-        final PackageList packageList = mServiceInternal.getPackageList();
-        for (String packageName : packageList.getPackageNames()) {
-            final PackageParser.Package pkg = mServiceInternal.getPackage(packageName);
+        List<PackageInfo> packages = mContext.getPackageManager().getInstalledPackagesAsUser(
+                DEFAULT_PACKAGE_INFO_QUERY_FLAGS, UserHandle.USER_SYSTEM);
+        for (PackageInfo pkg : packages) {
             if (pkg == null) {
                 continue;
             }
             if (!isSysComponentOrPersistentPlatformSignedPrivApp(pkg)
                     || !doesPackageSupportRuntimePermissions(pkg)
-                    || pkg.requestedPermissions.isEmpty()) {
+                    || ArrayUtils.isEmpty(pkg.requestedPermissions)) {
                 continue;
             }
-            grantRuntimePermissionsForPackage(userId, pkg);
+            grantRuntimePermissionsForSystemPackage(userId, pkg);
+        }
+    }
+
+    @SafeVarargs
+    private final void grantIgnoringSystemPackage(String packageName, int userId,
+            Set<String>... permissionGroups) {
+        grantPermissionsToSystemPackage(packageName, userId, false, true, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantSystemFixedPermissionsToSystemPackage(String packageName, int userId,
+            Set<String>... permissionGroups) {
+        grantPermissionsToSystemPackage(packageName, userId, true, false, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantPermissionsToSystemPackage(
+            String packageName, int userId, Set<String>... permissionGroups) {
+        grantPermissionsToSystemPackage(packageName, userId, false, false, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantPermissionsToSystemPackage(String packageName, int userId,
+            boolean systemFixed, boolean ignoreSystemPackage, Set<String>... permissionGroups) {
+        if (!ignoreSystemPackage && !isSystemPackage(packageName)) {
+            return;
+        }
+        grantRuntimePermissionsToPackage(getSystemPackageInfo(packageName),
+                userId, systemFixed, ignoreSystemPackage, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantRuntimePermissionsToPackage(String packageName, int userId,
+            boolean systemFixed, boolean ignoreSystemPackage, Set<String>... permissionGroups) {
+        grantRuntimePermissionsToPackage(getPackageInfo(packageName),
+                userId, systemFixed, ignoreSystemPackage, permissionGroups);
+    }
+
+    @SafeVarargs
+    private final void grantRuntimePermissionsToPackage(PackageInfo packageName, int userId,
+            boolean systemFixed, boolean ignoreSystemPackage, Set<String>... permissionGroups) {
+        if (packageName == null) return;
+        if (doesPackageSupportRuntimePermissions(packageName)) {
+            for (Set<String> permissionGroup : permissionGroups) {
+                grantRuntimePermissions(packageName, permissionGroup, systemFixed,
+                        ignoreSystemPackage, userId);
+            }
         }
     }
 
@@ -379,594 +425,373 @@
                 syncAdapterPackagesProvider.getPackages(CalendarContract.AUTHORITY, userId) : null;
 
         // Installer
-        final String installerPackageName = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_INSTALLER, userId);
-        PackageParser.Package installerPackage = getSystemPackage(installerPackageName);
-        if (installerPackage != null
-                && doesPackageSupportRuntimePermissions(installerPackage)) {
-            grantRuntimePermissions(installerPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getKnownPackage(PackageManagerInternal.PACKAGE_INSTALLER, userId),
+                userId, STORAGE_PERMISSIONS);
 
         // Verifier
-        final String verifierPackageName = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_VERIFIER, userId);
-        PackageParser.Package verifierPackage = getSystemPackage(verifierPackageName);
-        if (verifierPackage != null
-                && doesPackageSupportRuntimePermissions(verifierPackage)) {
-            grantRuntimePermissions(verifierPackage, STORAGE_PERMISSIONS, true, userId);
-            grantRuntimePermissions(verifierPackage, PHONE_PERMISSIONS, false, userId);
-            grantRuntimePermissions(verifierPackage, SMS_PERMISSIONS, false, userId);
-        }
+        final String verifier = getKnownPackage(PackageManagerInternal.PACKAGE_VERIFIER, userId);
+        grantSystemFixedPermissionsToSystemPackage(verifier, userId, STORAGE_PERMISSIONS);
+        grantPermissionsToSystemPackage(verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS);
 
         // SetupWizard
-        final String setupWizardPackageName = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId);
-        PackageParser.Package setupPackage = getSystemPackage(setupWizardPackageName);
-        if (setupPackage != null
-                && doesPackageSupportRuntimePermissions(setupPackage)) {
-            grantRuntimePermissions(setupPackage, PHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(setupPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(setupPackage, LOCATION_PERMISSIONS, userId);
-            grantRuntimePermissions(setupPackage, CAMERA_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getKnownPackage(PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId), userId,
+                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, LOCATION_PERMISSIONS, CAMERA_PERMISSIONS);
 
         // Camera
-        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
-        PackageParser.Package cameraPackage = getDefaultSystemHandlerActivityPackage(
-                cameraIntent, userId);
-        if (cameraPackage != null
-                && doesPackageSupportRuntimePermissions(cameraPackage)) {
-            grantRuntimePermissions(cameraPackage, CAMERA_PERMISSIONS, userId);
-            grantRuntimePermissions(cameraPackage, MICROPHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(cameraPackage, STORAGE_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(MediaStore.ACTION_IMAGE_CAPTURE, userId),
+                userId, CAMERA_PERMISSIONS, MICROPHONE_PERMISSIONS, STORAGE_PERMISSIONS);
 
         // Media provider
-        PackageParser.Package mediaStorePackage = getDefaultProviderAuthorityPackage(
-                MediaStore.AUTHORITY, userId);
-        if (mediaStorePackage != null) {
-            grantRuntimePermissions(mediaStorePackage, STORAGE_PERMISSIONS, true, userId);
-            grantRuntimePermissions(mediaStorePackage, MEDIA_AURAL_PERMISSIONS, true, userId);
-            grantRuntimePermissions(mediaStorePackage, MEDIA_VISUAL_PERMISSIONS, true, userId);
-            grantRuntimePermissions(mediaStorePackage, PHONE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultProviderAuthorityPackage(MediaStore.AUTHORITY, userId), userId,
+                STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS, MEDIA_VISUAL_PERMISSIONS,
+                PHONE_PERMISSIONS);
 
         // Downloads provider
-        PackageParser.Package downloadsPackage = getDefaultProviderAuthorityPackage(
-                "downloads", userId);
-        if (downloadsPackage != null) {
-            grantRuntimePermissions(downloadsPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultProviderAuthorityPackage("downloads", userId), userId,
+                STORAGE_PERMISSIONS);
 
         // Downloads UI
-        Intent downloadsUiIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
-        PackageParser.Package downloadsUiPackage = getDefaultSystemHandlerActivityPackage(
-                downloadsUiIntent, userId);
-        if (downloadsUiPackage != null
-                && doesPackageSupportRuntimePermissions(downloadsUiPackage)) {
-            grantRuntimePermissions(downloadsUiPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        DownloadManager.ACTION_VIEW_DOWNLOADS, userId),
+                userId, STORAGE_PERMISSIONS);
 
         // Storage provider
-        PackageParser.Package storagePackage = getDefaultProviderAuthorityPackage(
-                "com.android.externalstorage.documents", userId);
-        if (storagePackage != null) {
-            grantRuntimePermissions(storagePackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultProviderAuthorityPackage("com.android.externalstorage.documents", userId),
+                userId, STORAGE_PERMISSIONS);
 
         // CertInstaller
-        Intent certInstallerIntent = new Intent(Credentials.INSTALL_ACTION);
-        PackageParser.Package certInstallerPackage = getDefaultSystemHandlerActivityPackage(
-                certInstallerIntent, userId);
-        if (certInstallerPackage != null
-                && doesPackageSupportRuntimePermissions(certInstallerPackage)) {
-            grantRuntimePermissions(certInstallerPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(Credentials.INSTALL_ACTION, userId), userId,
+                STORAGE_PERMISSIONS);
 
         // Dialer
         if (dialerAppPackageNames == null) {
-            Intent dialerIntent = new Intent(Intent.ACTION_DIAL);
-            PackageParser.Package dialerPackage = getDefaultSystemHandlerActivityPackage(
-                    dialerIntent, userId);
-            if (dialerPackage != null) {
-                grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);
-            }
+            String dialerPackage =
+                    getDefaultSystemHandlerActivityPackage(Intent.ACTION_DIAL, userId);
+            grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);
         } else {
             for (String dialerAppPackageName : dialerAppPackageNames) {
-                PackageParser.Package dialerPackage = getSystemPackage(dialerAppPackageName);
-                if (dialerPackage != null) {
-                    grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);
-                }
+                grantDefaultPermissionsToDefaultSystemDialerApp(dialerAppPackageName, userId);
             }
         }
 
         // Sim call manager
         if (simCallManagerPackageNames != null) {
             for (String simCallManagerPackageName : simCallManagerPackageNames) {
-                PackageParser.Package simCallManagerPackage =
-                        getSystemPackage(simCallManagerPackageName);
-                if (simCallManagerPackage != null) {
-                    grantDefaultPermissionsToDefaultSimCallManager(simCallManagerPackage,
-                            userId);
-                }
+                grantDefaultPermissionsToDefaultSystemSimCallManager(
+                        simCallManagerPackageName, userId);
             }
         }
 
         // Use Open Wifi
         if (useOpenWifiAppPackageNames != null) {
             for (String useOpenWifiPackageName : useOpenWifiAppPackageNames) {
-                PackageParser.Package useOpenWifiPackage =
-                        getSystemPackage(useOpenWifiPackageName);
-                if (useOpenWifiPackage != null) {
-                    grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(useOpenWifiPackage,
-                            userId);
-                }
+                grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(
+                        useOpenWifiPackageName, userId);
             }
         }
 
         // SMS
         if (smsAppPackageNames == null) {
-            Intent smsIntent = new Intent(Intent.ACTION_MAIN);
-            smsIntent.addCategory(Intent.CATEGORY_APP_MESSAGING);
-            PackageParser.Package smsPackage = getDefaultSystemHandlerActivityPackage(
-                    smsIntent, userId);
-            if (smsPackage != null) {
-               grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
-            }
+            String smsPackage = getDefaultSystemHandlerActivityPackageForCategory(
+                    Intent.CATEGORY_APP_MESSAGING, userId);
+            grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
         } else {
-            for (String smsPackageName : smsAppPackageNames) {
-                PackageParser.Package smsPackage = getSystemPackage(smsPackageName);
-                if (smsPackage != null) {
-                    grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
-                }
+            for (String smsPackage : smsAppPackageNames) {
+                grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
             }
         }
 
         // Cell Broadcast Receiver
-        Intent cbrIntent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        PackageParser.Package cbrPackage =
-                getDefaultSystemHandlerActivityPackage(cbrIntent, userId);
-        if (cbrPackage != null && doesPackageSupportRuntimePermissions(cbrPackage)) {
-            grantRuntimePermissions(cbrPackage, SMS_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(Intents.SMS_CB_RECEIVED_ACTION, userId),
+                userId, SMS_PERMISSIONS);
 
         // Carrier Provisioning Service
-        Intent carrierProvIntent = new Intent(Intents.SMS_CARRIER_PROVISION_ACTION);
-        PackageParser.Package carrierProvPackage =
-                getDefaultSystemHandlerServicePackage(carrierProvIntent, userId);
-        if (carrierProvPackage != null
-                && doesPackageSupportRuntimePermissions(carrierProvPackage)) {
-            grantRuntimePermissions(carrierProvPackage, SMS_PERMISSIONS, false, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerServicePackage(Intents.SMS_CARRIER_PROVISION_ACTION, userId),
+                userId, SMS_PERMISSIONS);
 
         // Calendar
-        Intent calendarIntent = new Intent(Intent.ACTION_MAIN);
-        calendarIntent.addCategory(Intent.CATEGORY_APP_CALENDAR);
-        PackageParser.Package calendarPackage = getDefaultSystemHandlerActivityPackage(
-                calendarIntent, userId);
-        if (calendarPackage != null
-                && doesPackageSupportRuntimePermissions(calendarPackage)) {
-            grantRuntimePermissions(calendarPackage, CALENDAR_PERMISSIONS, userId);
-            grantRuntimePermissions(calendarPackage, CONTACTS_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(
+                        Intent.CATEGORY_APP_CALENDAR, userId),
+                userId, CALENDAR_PERMISSIONS, CONTACTS_PERMISSIONS);
 
         // Calendar provider
-        PackageParser.Package calendarProviderPackage = getDefaultProviderAuthorityPackage(
-                CalendarContract.AUTHORITY, userId);
-        if (calendarProviderPackage != null) {
-            grantRuntimePermissions(calendarProviderPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(calendarProviderPackage, CALENDAR_PERMISSIONS,
-                    true, userId);
-            grantRuntimePermissions(calendarProviderPackage, STORAGE_PERMISSIONS, userId);
-        }
+        String calendarProvider =
+                getDefaultProviderAuthorityPackage(CalendarContract.AUTHORITY, userId);
+        grantPermissionsToSystemPackage(calendarProvider, userId,
+                CONTACTS_PERMISSIONS, STORAGE_PERMISSIONS);
+        grantSystemFixedPermissionsToSystemPackage(calendarProvider, userId, CALENDAR_PERMISSIONS);
 
         // Calendar provider sync adapters
-        List<PackageParser.Package> calendarSyncAdapters = getHeadlessSyncAdapterPackages(
-                calendarSyncAdapterPackages, userId);
-        final int calendarSyncAdapterCount = calendarSyncAdapters.size();
-        for (int i = 0; i < calendarSyncAdapterCount; i++) {
-            PackageParser.Package calendarSyncAdapter = calendarSyncAdapters.get(i);
-            if (doesPackageSupportRuntimePermissions(calendarSyncAdapter)) {
-                grantRuntimePermissions(calendarSyncAdapter, CALENDAR_PERMISSIONS, userId);
-            }
-        }
+        grantPermissionToEachSystemPackage(
+                getHeadlessSyncAdapterPackages(calendarSyncAdapterPackages, userId),
+                userId, CALENDAR_PERMISSIONS);
 
         // Contacts
-        Intent contactsIntent = new Intent(Intent.ACTION_MAIN);
-        contactsIntent.addCategory(Intent.CATEGORY_APP_CONTACTS);
-        PackageParser.Package contactsPackage = getDefaultSystemHandlerActivityPackage(
-                contactsIntent, userId);
-        if (contactsPackage != null
-                && doesPackageSupportRuntimePermissions(contactsPackage)) {
-            grantRuntimePermissions(contactsPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(contactsPackage, PHONE_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(
+                        Intent.CATEGORY_APP_CONTACTS, userId),
+                userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
 
         // Contacts provider sync adapters
-        List<PackageParser.Package> contactsSyncAdapters = getHeadlessSyncAdapterPackages(
-                contactsSyncAdapterPackages, userId);
-        final int contactsSyncAdapterCount = contactsSyncAdapters.size();
-        for (int i = 0; i < contactsSyncAdapterCount; i++) {
-            PackageParser.Package contactsSyncAdapter = contactsSyncAdapters.get(i);
-            if (doesPackageSupportRuntimePermissions(contactsSyncAdapter)) {
-                grantRuntimePermissions(contactsSyncAdapter, CONTACTS_PERMISSIONS, userId);
-            }
-        }
+        grantPermissionToEachSystemPackage(
+                getHeadlessSyncAdapterPackages(contactsSyncAdapterPackages, userId),
+                userId, CONTACTS_PERMISSIONS);
 
         // Contacts provider
-        PackageParser.Package contactsProviderPackage = getDefaultProviderAuthorityPackage(
-                ContactsContract.AUTHORITY, userId);
-        if (contactsProviderPackage != null) {
-            grantRuntimePermissions(contactsProviderPackage, CONTACTS_PERMISSIONS,
-                    true, userId);
-            grantRuntimePermissions(contactsProviderPackage, PHONE_PERMISSIONS,
-                    true, userId);
-            grantRuntimePermissions(contactsProviderPackage, STORAGE_PERMISSIONS, userId);
-        }
+        String contactsProviderPackage =
+                getDefaultProviderAuthorityPackage(ContactsContract.AUTHORITY, userId);
+        grantSystemFixedPermissionsToSystemPackage(contactsProviderPackage, userId,
+                CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
+        grantPermissionsToSystemPackage(contactsProviderPackage, userId, STORAGE_PERMISSIONS);
 
         // Device provisioning
-        Intent deviceProvisionIntent = new Intent(
-                DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE);
-        PackageParser.Package deviceProvisionPackage =
-                getDefaultSystemHandlerActivityPackage(deviceProvisionIntent, userId);
-        if (deviceProvisionPackage != null
-                && doesPackageSupportRuntimePermissions(deviceProvisionPackage)) {
-            grantRuntimePermissions(deviceProvisionPackage, CONTACTS_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, userId),
+                userId, CONTACTS_PERMISSIONS);
 
         // Maps
-        Intent mapsIntent = new Intent(Intent.ACTION_MAIN);
-        mapsIntent.addCategory(Intent.CATEGORY_APP_MAPS);
-        PackageParser.Package mapsPackage = getDefaultSystemHandlerActivityPackage(
-                mapsIntent, userId);
-        if (mapsPackage != null
-                && doesPackageSupportRuntimePermissions(mapsPackage)) {
-            grantRuntimePermissions(mapsPackage, LOCATION_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(Intent.CATEGORY_APP_MAPS, userId),
+                userId, LOCATION_PERMISSIONS);
 
         // Gallery
-        Intent galleryIntent = new Intent(Intent.ACTION_MAIN);
-        galleryIntent.addCategory(Intent.CATEGORY_APP_GALLERY);
-        PackageParser.Package galleryPackage = getDefaultSystemHandlerActivityPackage(
-                galleryIntent, userId);
-        if (galleryPackage != null
-                && doesPackageSupportRuntimePermissions(galleryPackage)) {
-            grantRuntimePermissions(galleryPackage, STORAGE_PERMISSIONS, userId);
-            grantRuntimePermissions(galleryPackage, MEDIA_VISUAL_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(
+                        Intent.CATEGORY_APP_GALLERY, userId),
+                userId, STORAGE_PERMISSIONS, MEDIA_VISUAL_PERMISSIONS);
 
         // Email
-        Intent emailIntent = new Intent(Intent.ACTION_MAIN);
-        emailIntent.addCategory(Intent.CATEGORY_APP_EMAIL);
-        PackageParser.Package emailPackage = getDefaultSystemHandlerActivityPackage(
-                emailIntent, userId);
-        if (emailPackage != null
-                && doesPackageSupportRuntimePermissions(emailPackage)) {
-            grantRuntimePermissions(emailPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(emailPackage, CALENDAR_PERMISSIONS, userId);
-        }
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackageForCategory(
+                        Intent.CATEGORY_APP_EMAIL, userId),
+                userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS);
 
         // Browser
-        PackageParser.Package browserPackage = null;
-        String defaultBrowserPackage = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_BROWSER, userId);
-        if (defaultBrowserPackage != null) {
-            browserPackage = getPackage(defaultBrowserPackage);
-        }
+        String browserPackage = getKnownPackage(PackageManagerInternal.PACKAGE_BROWSER, userId);
         if (browserPackage == null) {
-            Intent browserIntent = new Intent(Intent.ACTION_MAIN);
-            browserIntent.addCategory(Intent.CATEGORY_APP_BROWSER);
-            browserPackage = getDefaultSystemHandlerActivityPackage(
-                    browserIntent, userId);
+            browserPackage = getDefaultSystemHandlerActivityPackageForCategory(
+                    Intent.CATEGORY_APP_BROWSER, userId);
+            if (!isSystemPackage(browserPackage)) {
+                browserPackage = null;
+            }
         }
-        if (browserPackage != null
-                && doesPackageSupportRuntimePermissions(browserPackage)) {
-            grantRuntimePermissions(browserPackage, LOCATION_PERMISSIONS, userId);
-        }
+        grantRuntimePermissionsToPackage(browserPackage, userId,
+                false /* systemFixed */, false /* ignoreSystemPackage */,
+                LOCATION_PERMISSIONS);
 
         // Voice interaction
         if (voiceInteractPackageNames != null) {
             for (String voiceInteractPackageName : voiceInteractPackageNames) {
-                PackageParser.Package voiceInteractPackage = getSystemPackage(
-                        voiceInteractPackageName);
-                if (voiceInteractPackage != null
-                        && doesPackageSupportRuntimePermissions(voiceInteractPackage)) {
-                    grantRuntimePermissions(voiceInteractPackage,
-                            CONTACTS_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            CALENDAR_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            MICROPHONE_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            PHONE_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            SMS_PERMISSIONS, userId);
-                    grantRuntimePermissions(voiceInteractPackage,
-                            LOCATION_PERMISSIONS, userId);
-                }
+                grantPermissionsToSystemPackage(voiceInteractPackageName, userId,
+                        CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
+                        PHONE_PERMISSIONS, SMS_PERMISSIONS, LOCATION_PERMISSIONS);
             }
         }
 
         if (ActivityManager.isLowRamDeviceStatic()) {
             // Allow voice search on low-ram devices
-            Intent globalSearchIntent = new Intent("android.search.action.GLOBAL_SEARCH");
-            PackageParser.Package globalSearchPickerPackage =
-                getDefaultSystemHandlerActivityPackage(globalSearchIntent, userId);
-
-            if (globalSearchPickerPackage != null
-                    && doesPackageSupportRuntimePermissions(globalSearchPickerPackage)) {
-                grantRuntimePermissions(globalSearchPickerPackage,
-                    MICROPHONE_PERMISSIONS, false, userId);
-                grantRuntimePermissions(globalSearchPickerPackage,
-                    LOCATION_PERMISSIONS, false, userId);
-            }
+            grantPermissionsToSystemPackage(
+                    getDefaultSystemHandlerActivityPackage(
+                            SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId),
+                    userId, MICROPHONE_PERMISSIONS, LOCATION_PERMISSIONS);
         }
 
         // Voice recognition
-        Intent voiceRecoIntent = new Intent("android.speech.RecognitionService");
-        voiceRecoIntent.addCategory(Intent.CATEGORY_DEFAULT);
-        PackageParser.Package voiceRecoPackage = getDefaultSystemHandlerServicePackage(
-                voiceRecoIntent, userId);
-        if (voiceRecoPackage != null
-                && doesPackageSupportRuntimePermissions(voiceRecoPackage)) {
-            grantRuntimePermissions(voiceRecoPackage, MICROPHONE_PERMISSIONS, userId);
-        }
+        Intent voiceRecoIntent = new Intent(RecognitionService.SERVICE_INTERFACE)
+                .addCategory(Intent.CATEGORY_DEFAULT);
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerServicePackage(voiceRecoIntent, userId), userId,
+                MICROPHONE_PERMISSIONS);
 
         // Location
         if (locationPackageNames != null) {
             for (String packageName : locationPackageNames) {
-                PackageParser.Package locationPackage = getSystemPackage(packageName);
-                if (locationPackage != null
-                        && doesPackageSupportRuntimePermissions(locationPackage)) {
-                    grantRuntimePermissions(locationPackage, CONTACTS_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, CALENDAR_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, MICROPHONE_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, PHONE_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, SMS_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, LOCATION_PERMISSIONS,
-                            true, userId);
-                    grantRuntimePermissions(locationPackage, CAMERA_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, SENSORS_PERMISSIONS, userId);
-                    grantRuntimePermissions(locationPackage, STORAGE_PERMISSIONS, userId);
-                }
+                grantPermissionsToSystemPackage(packageName, userId,
+                        CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
+                        PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
+                        SENSORS_PERMISSIONS, STORAGE_PERMISSIONS);
+                grantSystemFixedPermissionsToSystemPackage(packageName, userId,
+                        LOCATION_PERMISSIONS);
             }
         }
 
         // Music
-        Intent musicIntent = new Intent(Intent.ACTION_VIEW);
-        musicIntent.addCategory(Intent.CATEGORY_DEFAULT);
-        musicIntent.setDataAndType(Uri.fromFile(new File("foo.mp3")),
-                AUDIO_MIME_TYPE);
-        PackageParser.Package musicPackage = getDefaultSystemHandlerActivityPackage(
-                musicIntent, userId);
-        if (musicPackage != null
-                && doesPackageSupportRuntimePermissions(musicPackage)) {
-            grantRuntimePermissions(musicPackage, STORAGE_PERMISSIONS, userId);
-            grantRuntimePermissions(musicPackage, MEDIA_AURAL_PERMISSIONS, userId);
-        }
+        Intent musicIntent = new Intent(Intent.ACTION_VIEW)
+                .addCategory(Intent.CATEGORY_DEFAULT)
+                .setDataAndType(Uri.fromFile(new File("foo.mp3")), AUDIO_MIME_TYPE);
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(musicIntent, userId), userId,
+                STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS);
 
         // Home
-        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
-        homeIntent.addCategory(Intent.CATEGORY_HOME);
-        homeIntent.addCategory(Intent.CATEGORY_LAUNCHER_APP);
-        PackageParser.Package homePackage = getDefaultSystemHandlerActivityPackage(
-                homeIntent, userId);
-        if (homePackage != null
-                && doesPackageSupportRuntimePermissions(homePackage)) {
-            grantRuntimePermissions(homePackage, LOCATION_PERMISSIONS, false, userId);
-        }
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN)
+                .addCategory(Intent.CATEGORY_HOME)
+                .addCategory(Intent.CATEGORY_LAUNCHER_APP);
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(homeIntent, userId), userId,
+                LOCATION_PERMISSIONS);
 
         // Watches
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0)) {
             // Home application on watches
-            Intent wearHomeIntent = new Intent(Intent.ACTION_MAIN);
-            wearHomeIntent.addCategory(Intent.CATEGORY_HOME_MAIN);
 
-            PackageParser.Package wearHomePackage = getDefaultSystemHandlerActivityPackage(
-                    wearHomeIntent, userId);
-
-            if (wearHomePackage != null
-                    && doesPackageSupportRuntimePermissions(wearHomePackage)) {
-                grantRuntimePermissions(wearHomePackage, CONTACTS_PERMISSIONS, false,
-                        userId);
-                grantRuntimePermissions(wearHomePackage, PHONE_PERMISSIONS, true, userId);
-                grantRuntimePermissions(wearHomePackage, MICROPHONE_PERMISSIONS, false,
-                        userId);
-                grantRuntimePermissions(wearHomePackage, LOCATION_PERMISSIONS, false,
-                        userId);
-            }
+            String wearPackage = getDefaultSystemHandlerActivityPackageForCategory(
+                    Intent.CATEGORY_HOME_MAIN, userId);
+            grantPermissionsToSystemPackage(wearPackage, userId,
+                    CONTACTS_PERMISSIONS, MICROPHONE_PERMISSIONS, LOCATION_PERMISSIONS);
+            grantSystemFixedPermissionsToSystemPackage(wearPackage, userId, PHONE_PERMISSIONS);
 
             // Fitness tracking on watches
-            Intent trackIntent = new Intent(ACTION_TRACK);
-            PackageParser.Package trackPackage = getDefaultSystemHandlerActivityPackage(
-                    trackIntent, userId);
-            if (trackPackage != null
-                    && doesPackageSupportRuntimePermissions(trackPackage)) {
-                grantRuntimePermissions(trackPackage, SENSORS_PERMISSIONS, false, userId);
-                grantRuntimePermissions(trackPackage, LOCATION_PERMISSIONS, false, userId);
-            }
+            grantPermissionsToSystemPackage(
+                    getDefaultSystemHandlerActivityPackage(ACTION_TRACK, userId), userId,
+                    SENSORS_PERMISSIONS, LOCATION_PERMISSIONS);
         }
 
         // Print Spooler
-        PackageParser.Package printSpoolerPackage = getSystemPackage(
-                PrintManager.PRINT_SPOOLER_PACKAGE_NAME);
-        if (printSpoolerPackage != null
-                && doesPackageSupportRuntimePermissions(printSpoolerPackage)) {
-            grantRuntimePermissions(printSpoolerPackage, LOCATION_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(PrintManager.PRINT_SPOOLER_PACKAGE_NAME, userId,
+                LOCATION_PERMISSIONS);
 
         // EmergencyInfo
-        Intent emergencyInfoIntent = new Intent(TelephonyManager.ACTION_EMERGENCY_ASSISTANCE);
-        PackageParser.Package emergencyInfoPckg = getDefaultSystemHandlerActivityPackage(
-                emergencyInfoIntent, userId);
-        if (emergencyInfoPckg != null
-                && doesPackageSupportRuntimePermissions(emergencyInfoPckg)) {
-            grantRuntimePermissions(emergencyInfoPckg, CONTACTS_PERMISSIONS, true, userId);
-            grantRuntimePermissions(emergencyInfoPckg, PHONE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        TelephonyManager.ACTION_EMERGENCY_ASSISTANCE, userId),
+                userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
 
         // NFC Tag viewer
-        Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW);
-        nfcTagIntent.setType("vnd.android.cursor.item/ndef_msg");
-        PackageParser.Package nfcTagPkg = getDefaultSystemHandlerActivityPackage(
-                nfcTagIntent, userId);
-        if (nfcTagPkg != null
-                && doesPackageSupportRuntimePermissions(nfcTagPkg)) {
-            grantRuntimePermissions(nfcTagPkg, CONTACTS_PERMISSIONS, false, userId);
-            grantRuntimePermissions(nfcTagPkg, PHONE_PERMISSIONS, false, userId);
-        }
+        Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW)
+                .setType("vnd.android.cursor.item/ndef_msg");
+        grantPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(nfcTagIntent, userId), userId,
+                CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
 
         // Storage Manager
-        Intent storageManagerIntent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
-        PackageParser.Package storageManagerPckg = getDefaultSystemHandlerActivityPackage(
-                storageManagerIntent, userId);
-        if (storageManagerPckg != null
-                && doesPackageSupportRuntimePermissions(storageManagerPckg)) {
-            grantRuntimePermissions(storageManagerPckg, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        StorageManager.ACTION_MANAGE_STORAGE, userId),
+                userId, STORAGE_PERMISSIONS);
 
         // Companion devices
-        PackageParser.Package companionDeviceDiscoveryPackage = getSystemPackage(
-                CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME);
-        if (companionDeviceDiscoveryPackage != null
-                && doesPackageSupportRuntimePermissions(companionDeviceDiscoveryPackage)) {
-            grantRuntimePermissions(companionDeviceDiscoveryPackage,
-                    LOCATION_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, userId,
+                LOCATION_PERMISSIONS);
 
         // Ringtone Picker
-        Intent ringtonePickerIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
-        PackageParser.Package ringtonePickerPackage =
-                getDefaultSystemHandlerActivityPackage(ringtonePickerIntent, userId);
-        if (ringtonePickerPackage != null
-                && doesPackageSupportRuntimePermissions(ringtonePickerPackage)) {
-            grantRuntimePermissions(ringtonePickerPackage,
-                    STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(
+                getDefaultSystemHandlerActivityPackage(
+                        RingtoneManager.ACTION_RINGTONE_PICKER, userId),
+                userId, STORAGE_PERMISSIONS);
 
         // TextClassifier Service
         String textClassifierPackageName =
                 mContext.getPackageManager().getSystemTextClassifierPackageName();
         if (!TextUtils.isEmpty(textClassifierPackageName)) {
-            PackageParser.Package textClassifierPackage =
-                    getSystemPackage(textClassifierPackageName);
-            if (textClassifierPackage != null
-                    && doesPackageSupportRuntimePermissions(textClassifierPackage)) {
-                grantRuntimePermissions(textClassifierPackage, PHONE_PERMISSIONS, false, userId);
-                grantRuntimePermissions(textClassifierPackage, SMS_PERMISSIONS, false, userId);
-                grantRuntimePermissions(textClassifierPackage, CALENDAR_PERMISSIONS, false, userId);
-                grantRuntimePermissions(textClassifierPackage, LOCATION_PERMISSIONS, false, userId);
-                grantRuntimePermissions(textClassifierPackage, CONTACTS_PERMISSIONS, false, userId);
-            }
+            grantPermissionsToSystemPackage(textClassifierPackageName, userId,
+                    PHONE_PERMISSIONS, SMS_PERMISSIONS, CALENDAR_PERMISSIONS,
+                    LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
         }
 
         // There is no real "marker" interface to identify the shared storage backup, it is
         // hardcoded in BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE.
-        PackageParser.Package sharedStorageBackupPackage = getSystemPackage(
-                "com.android.sharedstoragebackup");
-        if (sharedStorageBackupPackage != null) {
-            grantRuntimePermissions(sharedStorageBackupPackage, STORAGE_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage("com.android.sharedstoragebackup", userId,
+                STORAGE_PERMISSIONS);
 
         if (mPermissionGrantedCallback != null) {
             mPermissionGrantedCallback.onDefaultRuntimePermissionsGranted(userId);
         }
     }
 
-    private void grantDefaultPermissionsToDefaultSystemDialerApp(
-            PackageParser.Package dialerPackage, int userId) {
-        if (doesPackageSupportRuntimePermissions(dialerPackage)) {
-            boolean isPhonePermFixed =
-                    mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0);
-            grantRuntimePermissions(
-                    dialerPackage, PHONE_PERMISSIONS, isPhonePermFixed, userId);
-            grantRuntimePermissions(dialerPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(dialerPackage, SMS_PERMISSIONS, userId);
-            grantRuntimePermissions(dialerPackage, MICROPHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(dialerPackage, CAMERA_PERMISSIONS, userId);
+    private String getDefaultSystemHandlerActivityPackageForCategory(String category, int userId) {
+        return getDefaultSystemHandlerActivityPackage(
+                new Intent(Intent.ACTION_MAIN).addCategory(category), userId);
+    }
+
+    @SafeVarargs
+    private final void grantPermissionToEachSystemPackage(
+            ArrayList<String> packages, int userId, Set<String>... permissions) {
+        if (packages == null) return;
+        final int count = packages.size();
+        for (int i = 0; i < count; i++) {
+            grantPermissionsToSystemPackage(packages.get(i), userId, permissions);
         }
     }
 
-    private void grantDefaultPermissionsToDefaultSystemSmsApp(
-            PackageParser.Package smsPackage, int userId) {
-        if (doesPackageSupportRuntimePermissions(smsPackage)) {
-            grantRuntimePermissions(smsPackage, PHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, CONTACTS_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, SMS_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, STORAGE_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, MICROPHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(smsPackage, CAMERA_PERMISSIONS, userId);
+    private String getKnownPackage(int knownPkgId, int userId) {
+        return mServiceInternal.getKnownPackageName(knownPkgId, userId);
+    }
+
+    private void grantDefaultPermissionsToDefaultSystemDialerApp(
+            String dialerPackage, int userId) {
+        if (dialerPackage == null) {
+            return;
         }
+        boolean isPhonePermFixed =
+                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0);
+        if (isPhonePermFixed) {
+            grantSystemFixedPermissionsToSystemPackage(dialerPackage, userId, PHONE_PERMISSIONS);
+        } else {
+            grantPermissionsToSystemPackage(dialerPackage, userId, PHONE_PERMISSIONS);
+        }
+        grantPermissionsToSystemPackage(dialerPackage, userId,
+                CONTACTS_PERMISSIONS, SMS_PERMISSIONS, MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
+    }
+
+    private void grantDefaultPermissionsToDefaultSystemSmsApp(String smsPackage, int userId) {
+        grantPermissionsToSystemPackage(smsPackage, userId,
+                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, SMS_PERMISSIONS,
+                STORAGE_PERMISSIONS, MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
     }
 
     private void grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(
-            PackageParser.Package useOpenWifiPackage, int userId) {
-        if (doesPackageSupportRuntimePermissions(useOpenWifiPackage)) {
-            grantRuntimePermissions(useOpenWifiPackage, COARSE_LOCATION_PERMISSIONS, userId);
-        }
+            String useOpenWifiPackage, int userId) {
+        grantPermissionsToSystemPackage(
+                useOpenWifiPackage, userId, COARSE_LOCATION_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to default sms app for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package smsPackage = getPackage(packageName);
-        if (smsPackage != null && doesPackageSupportRuntimePermissions(smsPackage)) {
-            grantRuntimePermissions(smsPackage, PHONE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, CONTACTS_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, SMS_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, STORAGE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, MICROPHONE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(smsPackage, CAMERA_PERMISSIONS, false, true, userId);
-        }
+        grantIgnoringSystemPackage(packageName, userId,
+                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, SMS_PERMISSIONS, STORAGE_PERMISSIONS,
+                MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultDialerApp(String packageName, int userId) {
+        mServiceInternal.onDefaultDialerAppChanged(packageName, userId);
         Log.i(TAG, "Granting permissions to default dialer app for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package dialerPackage = getPackage(packageName);
-        if (dialerPackage != null
-                && doesPackageSupportRuntimePermissions(dialerPackage)) {
-            grantRuntimePermissions(dialerPackage, PHONE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(dialerPackage, CONTACTS_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(dialerPackage, SMS_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(dialerPackage, MICROPHONE_PERMISSIONS, false, true, userId);
-            grantRuntimePermissions(dialerPackage, CAMERA_PERMISSIONS, false, true, userId);
-        }
+        grantIgnoringSystemPackage(packageName, userId,
+                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, SMS_PERMISSIONS,
+                MICROPHONE_PERMISSIONS, CAMERA_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to default Use Open WiFi app for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package useOpenWifiPackage = getPackage(packageName);
-        if (useOpenWifiPackage != null
-                && doesPackageSupportRuntimePermissions(useOpenWifiPackage)) {
-            grantRuntimePermissions(
-                    useOpenWifiPackage, COARSE_LOCATION_PERMISSIONS, false, true, userId);
-        }
-    }
-
-    private void grantDefaultPermissionsToDefaultSimCallManager(
-            PackageParser.Package simCallManagerPackage, int userId) {
-        Log.i(TAG, "Granting permissions to sim call manager for user:" + userId);
-        if (doesPackageSupportRuntimePermissions(simCallManagerPackage)) {
-            grantRuntimePermissions(simCallManagerPackage, PHONE_PERMISSIONS, userId);
-            grantRuntimePermissions(simCallManagerPackage, MICROPHONE_PERMISSIONS, userId);
-        }
+        grantIgnoringSystemPackage(packageName, userId, COARSE_LOCATION_PERMISSIONS);
     }
 
     public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
         if (packageName == null) {
             return;
         }
-        PackageParser.Package simCallManagerPackage = getPackage(packageName);
-        if (simCallManagerPackage != null) {
-            grantDefaultPermissionsToDefaultSimCallManager(simCallManagerPackage, userId);
+        Log.i(TAG, "Granting permissions to sim call manager for user:" + userId);
+        grantRuntimePermissionsToPackage(packageName, userId, false, false,
+                PHONE_PERMISSIONS, MICROPHONE_PERMISSIONS);
+    }
+
+    private void grantDefaultPermissionsToDefaultSystemSimCallManager(
+            String packageName, int userId) {
+        if (isSystemPackage(packageName)) {
+            grantDefaultPermissionsToDefaultSimCallManager(packageName, userId);
         }
     }
 
@@ -976,13 +801,8 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package carrierPackage = getSystemPackage(packageName);
-            if (carrierPackage != null
-                    && doesPackageSupportRuntimePermissions(carrierPackage)) {
-                grantRuntimePermissions(carrierPackage, PHONE_PERMISSIONS, userId);
-                grantRuntimePermissions(carrierPackage, LOCATION_PERMISSIONS, userId);
-                grantRuntimePermissions(carrierPackage, SMS_PERMISSIONS, userId);
-            }
+            grantPermissionsToSystemPackage(packageName, userId,
+                    PHONE_PERMISSIONS, LOCATION_PERMISSIONS, SMS_PERMISSIONS);
         }
     }
 
@@ -992,15 +812,9 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package imsServicePackage = getSystemPackage(packageName);
-            if (imsServicePackage != null
-                    && doesPackageSupportRuntimePermissions(imsServicePackage)) {
-                grantRuntimePermissions(imsServicePackage, PHONE_PERMISSIONS, userId);
-                grantRuntimePermissions(imsServicePackage, MICROPHONE_PERMISSIONS, userId);
-                grantRuntimePermissions(imsServicePackage, LOCATION_PERMISSIONS, userId);
-                grantRuntimePermissions(imsServicePackage, CAMERA_PERMISSIONS, userId);
-                grantRuntimePermissions(imsServicePackage, CONTACTS_PERMISSIONS, userId);
-            }
+            grantPermissionsToSystemPackage(packageName, userId,
+                    PHONE_PERMISSIONS, MICROPHONE_PERMISSIONS, LOCATION_PERMISSIONS,
+                    CAMERA_PERMISSIONS, CONTACTS_PERMISSIONS);
         }
     }
 
@@ -1011,15 +825,12 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package dataServicePackage = getSystemPackage(packageName);
-            if (dataServicePackage != null
-                    && doesPackageSupportRuntimePermissions(dataServicePackage)) {
-                // Grant these permissions as system-fixed, so that nobody can accidentally
-                // break cellular data.
-                grantRuntimePermissions(dataServicePackage, PHONE_PERMISSIONS, true, userId);
-                grantRuntimePermissions(dataServicePackage, LOCATION_PERMISSIONS, true, userId);
-            }
+            // Grant these permissions as system-fixed, so that nobody can accidentally
+            // break cellular data.
+            grantSystemFixedPermissionsToSystemPackage(packageName, userId,
+                    PHONE_PERMISSIONS, LOCATION_PERMISSIONS);
         }
+
     }
 
     public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
@@ -1029,25 +840,17 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package dataServicePackage = getSystemPackage(packageName);
-            if (dataServicePackage != null
-                    && doesPackageSupportRuntimePermissions(dataServicePackage)) {
-                revokeRuntimePermissions(dataServicePackage, PHONE_PERMISSIONS, true, userId);
-                revokeRuntimePermissions(dataServicePackage, LOCATION_PERMISSIONS, true, userId);
+            PackageInfo pkg = getSystemPackageInfo(packageName);
+            if (isSystemPackage(pkg) && doesPackageSupportRuntimePermissions(pkg)) {
+                revokeRuntimePermissions(packageName, PHONE_PERMISSIONS, true, userId);
+                revokeRuntimePermissions(packageName, LOCATION_PERMISSIONS, true, userId);
             }
         }
     }
 
     public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to active LUI app for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package luiAppPackage = getSystemPackage(packageName);
-        if (luiAppPackage != null
-                && doesPackageSupportRuntimePermissions(luiAppPackage)) {
-            grantRuntimePermissions(luiAppPackage, CAMERA_PERMISSIONS, true, userId);
-        }
+        grantSystemFixedPermissionsToSystemPackage(packageName, userId, CAMERA_PERMISSIONS);
     }
 
     public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) {
@@ -1056,123 +859,116 @@
             return;
         }
         for (String packageName : packageNames) {
-            PackageParser.Package luiAppPackage = getSystemPackage(packageName);
-            if (luiAppPackage != null
-                    && doesPackageSupportRuntimePermissions(luiAppPackage)) {
-                revokeRuntimePermissions(luiAppPackage, CAMERA_PERMISSIONS, true, userId);
+            PackageInfo pkg = getSystemPackageInfo(packageName);
+            if (isSystemPackage(pkg) && doesPackageSupportRuntimePermissions(pkg)) {
+                revokeRuntimePermissions(packageName, CAMERA_PERMISSIONS, true, userId);
             }
         }
     }
 
     public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) {
         Log.i(TAG, "Granting permissions to default browser for user:" + userId);
-        if (packageName == null) {
-            return;
-        }
-        PackageParser.Package browserPackage = getSystemPackage(packageName);
-        if (browserPackage != null
-                && doesPackageSupportRuntimePermissions(browserPackage)) {
-            grantRuntimePermissions(browserPackage, LOCATION_PERMISSIONS, false, false, userId);
-        }
+        grantPermissionsToSystemPackage(packageName, userId, LOCATION_PERMISSIONS);
     }
 
-    private PackageParser.Package getDefaultSystemHandlerActivityPackage(
-            Intent intent, int userId) {
+    private String getDefaultSystemHandlerActivityPackage(String intentAction, int userId) {
+        return getDefaultSystemHandlerActivityPackage(new Intent(intentAction), userId);
+    }
+
+    private String getDefaultSystemHandlerActivityPackage(Intent intent, int userId) {
         ResolveInfo handler = mServiceInternal.resolveIntent(intent,
-                intent.resolveType(mContext.getContentResolver()), DEFAULT_FLAGS, userId, false,
-                Binder.getCallingUid());
+                intent.resolveType(mContext.getContentResolver()), DEFAULT_INTENT_QUERY_FLAGS,
+                userId, false, Binder.getCallingUid());
         if (handler == null || handler.activityInfo == null) {
             return null;
         }
         if (mServiceInternal.isResolveActivityComponent(handler.activityInfo)) {
             return null;
         }
-        return getSystemPackage(handler.activityInfo.packageName);
+        String packageName = handler.activityInfo.packageName;
+        return isSystemPackage(packageName) ? packageName : null;
     }
 
-    private PackageParser.Package getDefaultSystemHandlerServicePackage(
+    private String getDefaultSystemHandlerServicePackage(String intentAction, int userId) {
+        return getDefaultSystemHandlerServicePackage(new Intent(intentAction), userId);
+    }
+
+    private String getDefaultSystemHandlerServicePackage(
             Intent intent, int userId) {
         List<ResolveInfo> handlers = mServiceInternal.queryIntentServices(
-                intent, DEFAULT_FLAGS, Binder.getCallingUid(), userId);
+                intent, DEFAULT_INTENT_QUERY_FLAGS, Binder.getCallingUid(), userId);
         if (handlers == null) {
             return null;
         }
         final int handlerCount = handlers.size();
         for (int i = 0; i < handlerCount; i++) {
             ResolveInfo handler = handlers.get(i);
-            PackageParser.Package handlerPackage = getSystemPackage(
-                    handler.serviceInfo.packageName);
-            if (handlerPackage != null) {
+            String handlerPackage = handler.serviceInfo.packageName;
+            if (isSystemPackage(handlerPackage)) {
                 return handlerPackage;
             }
         }
         return null;
     }
 
-    private List<PackageParser.Package> getHeadlessSyncAdapterPackages(
+    private ArrayList<String> getHeadlessSyncAdapterPackages(
             String[] syncAdapterPackageNames, int userId) {
-        List<PackageParser.Package> syncAdapterPackages = new ArrayList<>();
+        ArrayList<String> syncAdapterPackages = new ArrayList<>();
 
-        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
-        homeIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
 
         for (String syncAdapterPackageName : syncAdapterPackageNames) {
             homeIntent.setPackage(syncAdapterPackageName);
 
             ResolveInfo homeActivity = mServiceInternal.resolveIntent(homeIntent,
-                    homeIntent.resolveType(mContext.getContentResolver()), DEFAULT_FLAGS,
+                    homeIntent.resolveType(mContext.getContentResolver()),
+                    DEFAULT_INTENT_QUERY_FLAGS,
                     userId, false, Binder.getCallingUid());
             if (homeActivity != null) {
                 continue;
             }
 
-            PackageParser.Package syncAdapterPackage = getSystemPackage(syncAdapterPackageName);
-            if (syncAdapterPackage != null) {
-                syncAdapterPackages.add(syncAdapterPackage);
+            if (isSystemPackage(syncAdapterPackageName)) {
+                syncAdapterPackages.add(syncAdapterPackageName);
             }
         }
 
         return syncAdapterPackages;
     }
 
-    private PackageParser.Package getDefaultProviderAuthorityPackage(
-            String authority, int userId) {
-        ProviderInfo provider =
-                mServiceInternal.resolveContentProvider(authority, DEFAULT_FLAGS, userId);
+    private String getDefaultProviderAuthorityPackage(String authority, int userId) {
+        ProviderInfo provider = mServiceInternal.resolveContentProvider(
+                authority, DEFAULT_INTENT_QUERY_FLAGS, userId);
         if (provider != null) {
-            return getSystemPackage(provider.packageName);
+            return provider.packageName;
         }
         return null;
     }
 
-    private PackageParser.Package getPackage(String packageName) {
-        return mServiceInternal.getPackage(packageName);
+    private boolean isSystemPackage(String packageName) {
+        return isSystemPackage(getPackageInfo(packageName));
     }
 
-    private PackageParser.Package getSystemPackage(String packageName) {
-        PackageParser.Package pkg = getPackage(packageName);
-        if (pkg != null && pkg.isSystem()) {
-            return !isSysComponentOrPersistentPlatformSignedPrivApp(pkg) ? pkg : null;
+    private boolean isSystemPackage(PackageInfo pkg) {
+        if (pkg == null) {
+            return false;
         }
-        return null;
+        return pkg.applicationInfo.isSystemApp()
+                && !isSysComponentOrPersistentPlatformSignedPrivApp(pkg);
     }
 
-    private void grantRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
-            int userId) {
-        grantRuntimePermissions(pkg, permissions, false, false, userId);
-    }
-
-    private void grantRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
+    private void grantRuntimePermissions(PackageInfo pkg, Set<String> permissions,
             boolean systemFixed, int userId) {
         grantRuntimePermissions(pkg, permissions, systemFixed, false, userId);
     }
 
-    private void revokeRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
+    private void revokeRuntimePermissions(String packageName, Set<String> permissions,
             boolean systemFixed, int userId) {
-        if (pkg.requestedPermissions.isEmpty()) {
+        PackageInfo pkg = getSystemPackageInfo(packageName);
+        if (ArrayUtils.isEmpty(pkg.requestedPermissions)) {
             return;
         }
-        Set<String> revokablePermissions = new ArraySet<>(pkg.requestedPermissions);
+        Set<String> revokablePermissions = new ArraySet<>(Arrays.asList(pkg.requestedPermissions));
 
         for (String permission : permissions) {
             // We can't revoke what wasn't requested.
@@ -1181,7 +977,7 @@
             }
 
             final int flags = mServiceInternal.getPermissionFlagsTEMP(
-                    permission, pkg.packageName, userId);
+                    permission, packageName, userId);
 
             // We didn't get this through the default grant policy. Move along.
             if ((flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) == 0) {
@@ -1197,29 +993,35 @@
             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0 && !systemFixed) {
                 continue;
             }
-            mServiceInternal.revokeRuntimePermission(pkg.packageName, permission, userId, false);
+            mServiceInternal.revokeRuntimePermission(packageName, permission, userId, false);
 
             if (DEBUG) {
                 Log.i(TAG, "revoked " + (systemFixed ? "fixed " : "not fixed ")
-                        + permission + " to " + pkg.packageName);
+                        + permission + " to " + packageName);
             }
 
             // Remove the GRANTED_BY_DEFAULT flag without touching the others.
             // Note that we do not revoke FLAG_PERMISSION_SYSTEM_FIXED. That bit remains
             // sticky once set.
-            mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
+            mServiceInternal.updatePermissionFlagsTEMP(permission, packageName,
                     PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, 0, userId);
         }
     }
 
-    private void grantRuntimePermissions(PackageParser.Package pkg,
+    private void grantRuntimePermissions(PackageInfo pkg,
             Set<String> permissionsWithoutSplits, boolean systemFixed, boolean ignoreSystemPackage,
             int userId) {
-        if (pkg.requestedPermissions.isEmpty()) {
+        if (pkg == null) {
+            return;
+        }
+
+        String[] requestedPermissions = pkg.requestedPermissions;
+        if (ArrayUtils.isEmpty(requestedPermissions)) {
             return;
         }
 
         final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
+        ApplicationInfo applicationInfo = pkg.applicationInfo;
 
         // Automatically attempt to grant split permissions to older APKs
         final int numSplitPerms = PackageParser.SPLIT_PERMISSIONS.length;
@@ -1227,13 +1029,13 @@
             final PackageParser.SplitPermissionInfo splitPerm =
                     PackageParser.SPLIT_PERMISSIONS[splitPermNum];
 
-            if (pkg.applicationInfo.targetSdkVersion < splitPerm.targetSdk
+            if (applicationInfo != null
+                    && applicationInfo.targetSdkVersion < splitPerm.targetSdk
                     && permissionsWithoutSplits.contains(splitPerm.rootPerm)) {
                 Collections.addAll(permissions, splitPerm.newPerms);
             }
         }
 
-        List<String> requestedPermissions = pkg.requestedPermissions;
         Set<String> grantablePermissions = null;
 
         // In some cases, like for the Phone or SMS app, we grant permissions regardless
@@ -1242,23 +1044,25 @@
         // choice to grant this app the permissions needed to function. For all other
         // apps, (default grants on first boot and user creation) we don't grant default
         // permissions if the version on the system image does not declare them.
-        if (!ignoreSystemPackage && pkg.isUpdatedSystemApp()) {
-            final PackageParser.Package disabledPkg =
-                    mServiceInternal.getDisabledPackage(pkg.packageName);
+        if (!ignoreSystemPackage
+                && applicationInfo != null
+                && applicationInfo.isUpdatedSystemApp()) {
+            final PackageInfo disabledPkg = getSystemPackageInfo(
+                    mServiceInternal.getDisabledSystemPackageName(pkg.packageName));
             if (disabledPkg != null) {
-                if (disabledPkg.requestedPermissions.isEmpty()) {
+                if (ArrayUtils.isEmpty(disabledPkg.requestedPermissions)) {
                     return;
                 }
                 if (!requestedPermissions.equals(disabledPkg.requestedPermissions)) {
-                    grantablePermissions = new ArraySet<>(requestedPermissions);
+                    grantablePermissions = new ArraySet<>(Arrays.asList(requestedPermissions));
                     requestedPermissions = disabledPkg.requestedPermissions;
                 }
             }
         }
 
-        final int grantablePermissionCount = requestedPermissions.size();
+        final int grantablePermissionCount = requestedPermissions.length;
         for (int i = 0; i < grantablePermissionCount; i++) {
-            String permission = requestedPermissions.get(i);
+            String permission = requestedPermissions[i];
 
             // If there is a disabled system app it may request a permission the updated
             // version ot the data partition doesn't, In this case skip the permission.
@@ -1288,7 +1092,7 @@
                             pkg.packageName, permission, userId, false);
                     if (DEBUG) {
                         Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ")
-                                + permission + " to default handler " + pkg.packageName);
+                                + permission + " to default handler " + pkg);
                     }
 
                     int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
@@ -1307,7 +1111,7 @@
                         && !systemFixed) {
                     if (DEBUG) {
                         Log.i(TAG, "Granted not fixed " + permission + " to default handler "
-                                + pkg.packageName);
+                                + pkg);
                     }
                     mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
                             PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, 0, userId);
@@ -1316,28 +1120,42 @@
         }
     }
 
-    private boolean isSysComponentOrPersistentPlatformSignedPrivApp(PackageParser.Package pkg) {
+    private PackageInfo getSystemPackageInfo(String pkg) {
+        //TODO not MATCH_SYSTEM_ONLY?
+        return getPackageInfo(pkg, PackageManager.MATCH_FACTORY_ONLY);
+    }
+
+    private PackageInfo getPackageInfo(String pkg) {
+        return getPackageInfo(pkg, 0 /* extraFlags */);
+    }
+
+    private PackageInfo getPackageInfo(String pkg,
+            @PackageManager.PackageInfoFlags int extraFlags) {
+        return mServiceInternal.getPackageInfo(pkg,
+                DEFAULT_PACKAGE_INFO_QUERY_FLAGS | extraFlags,
+                //TODO is this the right filterCallingUid?
+                UserHandle.USER_SYSTEM, UserHandle.USER_SYSTEM);
+    }
+
+    private boolean isSysComponentOrPersistentPlatformSignedPrivApp(PackageInfo pkg) {
         if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
             return true;
         }
-        if (!pkg.isPrivileged()) {
+        if (!pkg.applicationInfo.isPrivilegedApp()) {
             return false;
         }
-        final PackageParser.Package disabledPkg =
-                mServiceInternal.getDisabledPackage(pkg.packageName);
+        final PackageInfo disabledPkg = getSystemPackageInfo(
+                mServiceInternal.getDisabledSystemPackageName(pkg.applicationInfo.packageName));
         if (disabledPkg != null) {
-            if ((disabledPkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
+            ApplicationInfo disabledPackageAppInfo = disabledPkg.applicationInfo;
+            if (disabledPackageAppInfo != null
+                    && (disabledPackageAppInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
                 return false;
             }
         } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
             return false;
         }
-        final String systemPackageName = mServiceInternal.getKnownPackageName(
-                PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM);
-        final PackageParser.Package systemPackage = getPackage(systemPackageName);
-        return pkg.mSigningDetails.hasAncestorOrSelf(systemPackage.mSigningDetails)
-                || systemPackage.mSigningDetails.checkCapability(pkg.mSigningDetails,
-                        PackageParser.SigningDetails.CertCapabilities.PERMISSION);
+        return mServiceInternal.isPlatformSigned(pkg.packageName);
     }
 
     private void grantDefaultPermissionExceptions(int userId) {
@@ -1357,7 +1175,7 @@
         final int exceptionCount = mGrantExceptions.size();
         for (int i = 0; i < exceptionCount; i++) {
             String packageName = mGrantExceptions.keyAt(i);
-            PackageParser.Package pkg = getSystemPackage(packageName);
+            PackageInfo pkg = getSystemPackageInfo(packageName);
             List<DefaultPermissionGrant> permissionGrants = mGrantExceptions.valueAt(i);
             final int permissionGrantCount = permissionGrants.size();
             for (int j = 0; j < permissionGrantCount; j++) {
@@ -1368,8 +1186,7 @@
                     permissions.clear();
                 }
                 permissions.add(permissionGrant.name);
-                grantRuntimePermissions(pkg, permissions,
-                        permissionGrant.fixed, userId);
+                grantRuntimePermissions(pkg, permissions, permissionGrant.fixed, userId);
             }
         }
     }
@@ -1474,15 +1291,14 @@
                         outGrantExceptions.get(packageName);
                 if (packageExceptions == null) {
                     // The package must be on the system image
-                    PackageParser.Package pkg = getSystemPackage(packageName);
-                    if (pkg == null) {
+                    if (!isSystemPackage(packageName)) {
                         Log.w(TAG, "Unknown package:" + packageName);
                         XmlUtils.skipCurrentTag(parser);
                         continue;
                     }
 
                     // The package must support runtime permissions
-                    if (!doesPackageSupportRuntimePermissions(pkg)) {
+                    if (!doesPackageSupportRuntimePermissions(getSystemPackageInfo(packageName))) {
                         Log.w(TAG, "Skipping non supporting runtime permissions package:"
                                 + packageName);
                         XmlUtils.skipCurrentTag(parser);
@@ -1527,8 +1343,9 @@
         }
     }
 
-    private static boolean doesPackageSupportRuntimePermissions(PackageParser.Package pkg) {
-        return pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
+    private static boolean doesPackageSupportRuntimePermissions(PackageInfo pkg) {
+        return pkg.applicationInfo != null
+                && pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
     }
 
     private static final class DefaultPermissionGrant {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index c4f90a12..4b6760c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1189,7 +1189,7 @@
                 // is granted only if it had been defined by the original application.
                 if (pkg.isUpdatedSystemApp()) {
                     final PackageParser.Package disabledPkg =
-                            mPackageManagerInt.getDisabledPackage(pkg.packageName);
+                            mPackageManagerInt.getDisabledSystemPackage(pkg.packageName);
                     final PackageSetting disabledPs =
                             (disabledPkg != null) ? (PackageSetting) disabledPkg.mExtras : null;
                     if (disabledPs != null
@@ -1221,7 +1221,7 @@
                         // packages can also get the permission.
                         if (pkg.parentPackage != null) {
                             final PackageParser.Package disabledParentPkg = mPackageManagerInt
-                                    .getDisabledPackage(pkg.parentPackage.packageName);
+                                    .getDisabledSystemPackage(pkg.parentPackage.packageName);
                             final PackageSetting disabledParentPs = (disabledParentPkg != null)
                                     ? (PackageSetting) disabledParentPkg.mExtras : null;
                             if (disabledParentPkg != null
@@ -1372,7 +1372,7 @@
             return;
         }
         final PackageParser.Package disabledPkg =
-                mPackageManagerInt.getDisabledPackage(pkg.parentPackage.packageName);
+                mPackageManagerInt.getDisabledSystemPackage(pkg.parentPackage.packageName);
         if (disabledPkg == null || disabledPkg.mExtras == null) {
             return;
         }
diff --git a/services/core/java/com/android/server/policy/TEST_MAPPING b/services/core/java/com/android/server/policy/TEST_MAPPING
new file mode 100644
index 0000000..e212b04
--- /dev/null
+++ b/services/core/java/com/android/server/policy/TEST_MAPPING
@@ -0,0 +1,50 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.policy."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "android.support.test.filters.FlakyTest"
+        }
+      ]
+    },
+    {
+      "name": "WmTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.policy."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.policy."
+        }
+      ]
+    },
+    {
+      "name": "WmTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.policy."
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 5981ab0..68e636a 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -49,6 +49,7 @@
 import android.util.Slog;
 import android.util.StatsLog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -75,7 +76,8 @@
  * tell the system when we go to sleep so that it can lock the keyguard if needed.
  * </p>
  */
-final class Notifier {
+@VisibleForTesting
+public class Notifier {
     private static final String TAG = "PowerManagerNotifier";
 
     private static final boolean DEBUG = false;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index bdf12ca..9f6b3dd 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -64,7 +64,6 @@
 import android.os.WorkSource;
 import android.os.WorkSource.WorkChain;
 import android.provider.Settings;
-import android.provider.Settings.Global;
 import android.provider.Settings.SettingNotFoundException;
 import android.service.dreams.DreamManagerInternal;
 import android.service.vr.IVrManager;
@@ -84,7 +83,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.BackgroundThread;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.server.EventLogTags;
 import com.android.server.LockGuard;
@@ -230,6 +228,10 @@
     private final BatterySaverController mBatterySaverController;
     private final BatterySaverStateMachine mBatterySaverStateMachine;
     private final BatterySavingStats mBatterySavingStats;
+    private final BinderService mBinderService;
+    private final LocalService mLocalService;
+    private final NativeWrapper mNativeWrapper;
+    private final Injector mInjector;
 
     private LightsManager mLightsManager;
     private BatteryManagerInternal mBatteryManagerInternal;
@@ -636,10 +638,76 @@
         }
     }
 
+    /**
+     * Wrapper around the static-native methods of PowerManagerService.
+     *
+     * This class exists to allow us to mock static native methods in our tests. If mocking static
+     * methods becomes easier than this in the future, we can delete this class.
+     */
+    @VisibleForTesting
+    public static class NativeWrapper {
+        /** Wrapper for PowerManager.nativeInit */
+        public void nativeInit(PowerManagerService service) {
+            service.nativeInit();
+        }
+
+        /** Wrapper for PowerManager.nativeAcquireSuspectBlocker */
+        public void nativeAcquireSuspendBlocker(String name) {
+            PowerManagerService.nativeAcquireSuspendBlocker(name);
+        }
+
+        /** Wrapper for PowerManager.nativeReleaseSuspendBlocker */
+        public void nativeReleaseSuspendBlocker(String name) {
+            PowerManagerService.nativeReleaseSuspendBlocker(name);
+        }
+
+        /** Wrapper for PowerManager.nativeSetInteractive */
+        public void nativeSetInteractive(boolean enable) {
+            PowerManagerService.nativeSetInteractive(enable);
+        }
+
+        /** Wrapper for PowerManager.nativeSetAutoSuspend */
+        public void nativeSetAutoSuspend(boolean enable) {
+            PowerManagerService.nativeSetAutoSuspend(enable);
+        }
+
+        /** Wrapper for PowerManager.nativeSendPowerHint */
+        public void nativeSendPowerHint(int hintId, int data) {
+            PowerManagerService.nativeSendPowerHint(hintId, data);
+        }
+
+        /** Wrapper for PowerManager.nativeSetFeature */
+        public void nativeSetFeature(int featureId, int data) {
+            PowerManagerService.nativeSetFeature(featureId, data);
+        }
+    }
+
+    @VisibleForTesting
+    static class Injector {
+        Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
+                SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
+            return new Notifier(looper, context, batteryStats, suspendBlocker, policy);
+        }
+
+        SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
+            SuspendBlocker suspendBlocker = service.new SuspendBlockerImpl(name);
+            service.mSuspendBlockers.add(suspendBlocker);
+            return suspendBlocker;
+        }
+
+        BatterySaverPolicy createBatterySaverPolicy(
+                Object lock, Context context, BatterySavingStats batterySavingStats) {
+            return new BatterySaverPolicy(lock, context, batterySavingStats);
+        }
+
+        NativeWrapper createNativeWrapper() {
+            return new NativeWrapper();
+        }
+    }
+
     final Constants mConstants;
 
     private native void nativeInit();
-
     private static native void nativeAcquireSuspendBlocker(String name);
     private static native void nativeReleaseSuspendBlocker(String name);
     private static native void nativeSetInteractive(boolean enable);
@@ -648,8 +716,19 @@
     private static native void nativeSetFeature(int featureId, int data);
 
     public PowerManagerService(Context context) {
+        this(context, new Injector());
+    }
+
+    @VisibleForTesting
+    PowerManagerService(Context context, Injector injector) {
         super(context);
+
         mContext = context;
+        mBinderService = new BinderService();
+        mLocalService = new LocalService();
+        mNativeWrapper = injector.createNativeWrapper();
+        mInjector = injector;
+
         mHandlerThread = new ServiceThread(TAG,
                 Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
         mHandlerThread.start();
@@ -658,57 +737,40 @@
         mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
 
         mBatterySavingStats = new BatterySavingStats(mLock);
-        mBatterySaverPolicy = new BatterySaverPolicy(mLock, mContext, mBatterySavingStats);
+        mBatterySaverPolicy =
+                mInjector.createBatterySaverPolicy(mLock, mContext, mBatterySavingStats);
         mBatterySaverController = new BatterySaverController(mLock, mContext,
-                BackgroundThread.get().getLooper(), mBatterySaverPolicy, mBatterySavingStats);
+                BackgroundThread.get().getLooper(), mBatterySaverPolicy,
+                mBatterySavingStats);
         mBatterySaverStateMachine = new BatterySaverStateMachine(
                 mLock, mContext, mBatterySaverController);
 
         synchronized (mLock) {
-            mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
-            mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
-            mDisplaySuspendBlocker.acquire();
-            mHoldingDisplaySuspendBlocker = true;
+            mWakeLockSuspendBlocker =
+                    mInjector.createSuspendBlocker(this, "PowerManagerService.WakeLocks");
+            mDisplaySuspendBlocker =
+                    mInjector.createSuspendBlocker(this, "PowerManagerService.Display");
+            if (mDisplaySuspendBlocker != null) {
+                mDisplaySuspendBlocker.acquire();
+                mHoldingDisplaySuspendBlocker = true;
+            }
             mHalAutoSuspendModeEnabled = false;
             mHalInteractiveModeEnabled = true;
 
             mWakefulness = WAKEFULNESS_AWAKE;
-
             sQuiescent = SystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
 
-            nativeInit();
-            nativeSetAutoSuspend(false);
-            nativeSetInteractive(true);
-            nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
+            mNativeWrapper.nativeInit(this);
+            mNativeWrapper.nativeSetAutoSuspend(false);
+            mNativeWrapper.nativeSetInteractive(true);
+            mNativeWrapper.nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
         }
     }
 
-    @VisibleForTesting
-    PowerManagerService(Context context, BatterySaverPolicy batterySaverPolicy) {
-        super(context);
-
-        mContext = context;
-        mHandlerThread = new ServiceThread(TAG,
-                Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
-        mHandlerThread.start();
-        mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
-        mConstants = new Constants(mHandler);
-        mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
-        mDisplaySuspendBlocker = null;
-        mWakeLockSuspendBlocker = null;
-
-        mBatterySavingStats = new BatterySavingStats(mLock);
-        mBatterySaverPolicy = batterySaverPolicy;
-        mBatterySaverController = new BatterySaverController(mLock, context,
-                BackgroundThread.getHandler().getLooper(), batterySaverPolicy, mBatterySavingStats);
-        mBatterySaverStateMachine = new BatterySaverStateMachine(
-                mLock, mContext, mBatterySaverController);
-    }
-
     @Override
     public void onStart() {
-        publishBinderService(Context.POWER_SERVICE, new BinderService());
-        publishLocalService(PowerManagerInternal.class, new LocalService());
+        publishBinderService(Context.POWER_SERVICE, mBinderService);
+        publishLocalService(PowerManagerInternal.class, mLocalService);
 
         Watchdog.getInstance().addMonitor(this);
         Watchdog.getInstance().addThread(mHandler);
@@ -752,11 +814,13 @@
             // The notifier runs on the system server's main looper so as not to interfere
             // with the animations and other critical functions of the power manager.
             mBatteryStats = BatteryStatsService.getService();
-            mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
-                    createSuspendBlockerLocked("PowerManagerService.Broadcasts"), mPolicy);
+            mNotifier = mInjector.createNotifier(Looper.getMainLooper(), mContext, mBatteryStats,
+                    mInjector.createSuspendBlocker(this, "PowerManagerService.Broadcasts"),
+                    mPolicy);
 
             mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
-                    createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
+                    mInjector.createSuspendBlocker(
+                            this, "PowerManagerService.WirelessChargerDetector"),
                     mHandler);
             mSettingsObserver = new SettingsObserver(mHandler);
 
@@ -824,7 +888,7 @@
         resolver.registerContentObserver(Settings.Global.getUriFor(
                 Settings.Global.DEVICE_DEMO_MODE),
                 false, mSettingsObserver, UserHandle.USER_SYSTEM);
-        IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
+        IVrManager vrManager = IVrManager.Stub.asInterface(getBinderService(Context.VR_SERVICE));
         if (vrManager != null) {
             try {
                 vrManager.registerListener(mVrStateCallbacks);
@@ -927,7 +991,8 @@
                             UserHandle.USER_CURRENT) != 0;
             if (doubleTapWakeEnabled != mDoubleTapWakeEnabled) {
                 mDoubleTapWakeEnabled = doubleTapWakeEnabled;
-                nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, mDoubleTapWakeEnabled ? 1 : 0);
+                mNativeWrapper.nativeSetFeature(
+                        POWER_FEATURE_DOUBLE_TAP_TO_WAKE, mDoubleTapWakeEnabled ? 1 : 0);
             }
         }
 
@@ -1509,6 +1574,11 @@
         }
     }
 
+    @VisibleForTesting
+    int getWakefulness() {
+        return mWakefulness;
+    }
+
     /**
      * Logs the time the device would have spent awake before user activity timeout,
      * had the system not been told the user was inactive.
@@ -2640,7 +2710,7 @@
             mHalAutoSuspendModeEnabled = enable;
             Trace.traceBegin(Trace.TRACE_TAG_POWER, "setHalAutoSuspend(" + enable + ")");
             try {
-                nativeSetAutoSuspend(enable);
+                mNativeWrapper.nativeSetAutoSuspend(enable);
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_POWER);
             }
@@ -2655,7 +2725,7 @@
             mHalInteractiveModeEnabled = enable;
             Trace.traceBegin(Trace.TRACE_TAG_POWER, "setHalInteractive(" + enable + ")");
             try {
-                nativeSetInteractive(enable);
+                mNativeWrapper.nativeSetInteractive(enable);
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_POWER);
             }
@@ -3127,7 +3197,7 @@
                 break;
         }
 
-        nativeSendPowerHint(hintId, data);
+        mNativeWrapper.nativeSendPowerHint(hintId, data);
     }
 
     /**
@@ -3718,12 +3788,6 @@
         proto.flush();
     }
 
-    private SuspendBlocker createSuspendBlockerLocked(String name) {
-        SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
-        mSuspendBlockers.add(suspendBlocker);
-        return suspendBlocker;
-    }
-
     private void incrementBootCount() {
         synchronized (mLock) {
             int count;
@@ -4022,7 +4086,7 @@
                     Slog.wtf(TAG, "Suspend blocker \"" + mName
                             + "\" was finalized without being released!");
                     mReferenceCount = 0;
-                    nativeReleaseSuspendBlocker(mName);
+                    mNativeWrapper.nativeReleaseSuspendBlocker(mName);
                     Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
                 }
             } finally {
@@ -4039,7 +4103,7 @@
                         Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");
                     }
                     Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
-                    nativeAcquireSuspendBlocker(mName);
+                    mNativeWrapper.nativeAcquireSuspendBlocker(mName);
                 }
             }
         }
@@ -4052,7 +4116,7 @@
                     if (DEBUG_SPEW) {
                         Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
                     }
-                    nativeReleaseSuspendBlocker(mName);
+                    mNativeWrapper.nativeReleaseSuspendBlocker(mName);
                     Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
                 } else if (mReferenceCount < 0) {
                     Slog.wtf(TAG, "Suspend blocker \"" + mName
@@ -4090,7 +4154,8 @@
         }
     }
 
-    private final class BinderService extends IPowerManager.Stub {
+    @VisibleForTesting
+    final class BinderService extends IPowerManager.Stub {
         @Override
         public void onShellCommand(FileDescriptor in, FileDescriptor out,
                 FileDescriptor err, String[] args, ShellCallback callback,
@@ -4592,6 +4657,16 @@
     }
 
     @VisibleForTesting
+    BinderService getBinderServiceInstance() {
+        return mBinderService;
+    }
+
+    @VisibleForTesting
+    LocalService getLocalServiceInstance() {
+        return mLocalService;
+    }
+
+    @VisibleForTesting
     // lastRebootReasonProperty argument to permit testing
     int getLastShutdownReasonInternal(String lastRebootReasonProperty) {
         String line = SystemProperties.get(lastRebootReasonProperty);
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index 6c5452a..7a3f030 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -22,7 +22,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
-import android.content.pm.PackageManagerInternal;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
@@ -39,12 +38,13 @@
 import android.util.IntArray;
 import android.util.Slog;
 
-import android.util.SparseBooleanArray;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.telephony.SmsApplication;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.pm.UserManagerService;
+import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
+import com.android.server.pm.permission.PermissionManagerInternal;
 
 /**
  * Starts the telecom component by binding to its ITelecomService implementation. Telecom is setup
@@ -72,8 +72,8 @@
                 synchronized (mLock) {
                     if (mDefaultSmsAppRequests != null || mDefaultDialerAppRequests != null
                             || mDefaultSimCallManagerRequests != null) {
-                        final PackageManagerInternal packageManagerInternal = LocalServices
-                                .getService(PackageManagerInternal.class);
+                        final DefaultPermissionGrantPolicy permissionPolicy =
+                                getDefaultPermissionGrantPolicy();
 
                         if (mDefaultSmsAppRequests != null) {
                             ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
@@ -83,7 +83,7 @@
                                 for (int i = requestCount - 1; i >= 0; i--) {
                                     final int userid = mDefaultSmsAppRequests.get(i);
                                     mDefaultSmsAppRequests.remove(i);
-                                    packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(
+                                    permissionPolicy.grantDefaultPermissionsToDefaultSmsApp(
                                             smsComponent.getPackageName(), userid);
                                 }
                             }
@@ -97,7 +97,7 @@
                                 for (int i = requestCount - 1; i >= 0; i--) {
                                     final int userId = mDefaultDialerAppRequests.get(i);
                                     mDefaultDialerAppRequests.remove(i);
-                                    packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(
+                                    permissionPolicy.grantDefaultPermissionsToDefaultDialerApp(
                                             packageName, userId);
                                 }
                             }
@@ -113,7 +113,7 @@
                                 for (int i = requestCount - 1; i >= 0; i--) {
                                     final int userId = mDefaultSimCallManagerRequests.get(i);
                                     mDefaultSimCallManagerRequests.remove(i);
-                                    packageManagerInternal
+                                    permissionPolicy
                                             .grantDefaultPermissionsToDefaultSimCallManager(
                                                     packageName, userId);
                                 }
@@ -132,6 +132,11 @@
         }
     }
 
+    private DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy() {
+        return LocalServices.getService(PermissionManagerInternal.class)
+                .getDefaultPermissionGrantPolicy();
+    }
+
     private static final ComponentName SERVICE_COMPONENT = new ComponentName(
             "com.android.server.telecom",
             "com.android.server.telecom.components.TelecomService");
@@ -196,82 +201,68 @@
 
 
     private void registerDefaultAppProviders() {
-        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
+        final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy();
 
-        // Set a callback for the package manager to query the default sms app.
-        packageManagerInternal.setSmsAppPackagesProvider(
-                new PackageManagerInternal.PackagesProvider() {
-            @Override
-            public String[] getPackages(int userId) {
-                synchronized (mLock) {
-                    if (mServiceConnection == null) {
-                        if (mDefaultSmsAppRequests == null) {
-                            mDefaultSmsAppRequests = new IntArray();
-                        }
-                        mDefaultSmsAppRequests.add(userId);
-                        return null;
+        // Set a callback for the permission grant policy to query the default sms app.
+        permissionPolicy.setSmsAppPackagesProvider(userId -> {
+            synchronized (mLock) {
+                if (mServiceConnection == null) {
+                    if (mDefaultSmsAppRequests == null) {
+                        mDefaultSmsAppRequests = new IntArray();
                     }
+                    mDefaultSmsAppRequests.add(userId);
+                    return null;
                 }
-                ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
-                        mContext, true);
-                if (smsComponent != null) {
-                    return new String[]{smsComponent.getPackageName()};
-                }
-                return null;
             }
+            ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
+                    mContext, true);
+            if (smsComponent != null) {
+                return new String[]{smsComponent.getPackageName()};
+            }
+            return null;
         });
 
-        // Set a callback for the package manager to query the default dialer app.
-        packageManagerInternal.setDialerAppPackagesProvider(
-                new PackageManagerInternal.PackagesProvider() {
-            @Override
-            public String[] getPackages(int userId) {
-                synchronized (mLock) {
-                    if (mServiceConnection == null) {
-                        if (mDefaultDialerAppRequests == null) {
-                            mDefaultDialerAppRequests = new IntArray();
-                        }
-                        mDefaultDialerAppRequests.add(userId);
-                        return null;
+        // Set a callback for the permission grant policy to query the default dialer app.
+        permissionPolicy.setDialerAppPackagesProvider(userId -> {
+            synchronized (mLock) {
+                if (mServiceConnection == null) {
+                    if (mDefaultDialerAppRequests == null) {
+                        mDefaultDialerAppRequests = new IntArray();
                     }
+                    mDefaultDialerAppRequests.add(userId);
+                    return null;
                 }
-                String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
-                if (packageName != null) {
-                    return new String[]{packageName};
-                }
-                return null;
             }
+            String packageName = DefaultDialerManager.getDefaultDialerApplication(mContext);
+            if (packageName != null) {
+                return new String[]{packageName};
+            }
+            return null;
         });
 
-        // Set a callback for the package manager to query the default sim call manager.
-        packageManagerInternal.setSimCallManagerPackagesProvider(
-                new PackageManagerInternal.PackagesProvider() {
-            @Override
-            public String[] getPackages(int userId) {
-                synchronized (mLock) {
-                    if (mServiceConnection == null) {
-                        if (mDefaultSimCallManagerRequests == null) {
-                            mDefaultSimCallManagerRequests = new IntArray();
-                        }
-                        mDefaultSimCallManagerRequests.add(userId);
-                        return null;
+        // Set a callback for the permission grant policy to query the default sim call manager.
+        permissionPolicy.setSimCallManagerPackagesProvider(userId -> {
+            synchronized (mLock) {
+                if (mServiceConnection == null) {
+                    if (mDefaultSimCallManagerRequests == null) {
+                        mDefaultSimCallManagerRequests = new IntArray();
                     }
+                    mDefaultSimCallManagerRequests.add(userId);
+                    return null;
                 }
-                TelecomManager telecomManager =
+            }
+            TelecomManager telecomManager =
                     (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
-                PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
-                if (phoneAccount != null) {
-                    return new String[]{phoneAccount.getComponentName().getPackageName()};
-                }
-                return null;
+            PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
+            if (phoneAccount != null) {
+                return new String[]{phoneAccount.getComponentName().getPackageName()};
             }
+            return null;
         });
     }
 
     private void registerDefaultAppNotifier() {
-        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
+        final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy();
 
         // Notify the package manager on default app changes
         final Uri defaultSmsAppUri = Settings.Secure.getUriFor(
@@ -287,17 +278,17 @@
                     ComponentName smsComponent = SmsApplication.getDefaultSmsApplication(
                             mContext, true);
                     if (smsComponent != null) {
-                        packageManagerInternal.grantDefaultPermissionsToDefaultSmsApp(
+                        permissionPolicy.grantDefaultPermissionsToDefaultSmsApp(
                                 smsComponent.getPackageName(), userId);
                     }
                 } else if (defaultDialerAppUri.equals(uri)) {
                     String packageName = DefaultDialerManager.getDefaultDialerApplication(
                             mContext);
                     if (packageName != null) {
-                        packageManagerInternal.grantDefaultPermissionsToDefaultDialerApp(
+                        permissionPolicy.grantDefaultPermissionsToDefaultDialerApp(
                                 packageName, userId);
                     }
-                    updateSimCallManagerPermissions(packageManagerInternal, userId);
+                    updateSimCallManagerPermissions(permissionPolicy, userId);
                 }
             }
         };
@@ -310,14 +301,12 @@
 
 
     private void registerCarrierConfigChangedReceiver() {
-        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
         BroadcastReceiver receiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
                     for (int userId : UserManagerService.getInstance().getUserIds()) {
-                        updateSimCallManagerPermissions(packageManagerInternal, userId);
+                        updateSimCallManagerPermissions(getDefaultPermissionGrantPolicy(), userId);
                     }
                 }
             }
@@ -327,15 +316,15 @@
             new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED), null, null);
     }
 
-    private void updateSimCallManagerPermissions(PackageManagerInternal packageManagerInternal,
-            int userId) {
+    private void updateSimCallManagerPermissions(
+            DefaultPermissionGrantPolicy permissionGrantPolicy, int userId) {
         TelecomManager telecomManager =
             (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
         PhoneAccountHandle phoneAccount = telecomManager.getSimCallManager(userId);
         if (phoneAccount != null) {
             Slog.i(TAG, "updating sim call manager permissions for userId:" + userId);
             String packageName = phoneAccount.getComponentName().getPackageName();
-            packageManagerInternal.grantDefaultPermissionsToDefaultSimCallManager(
+            permissionGrantPolicy.grantDefaultPermissionsToDefaultSimCallManager(
                 packageName, userId);
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6c7304d..d518549 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -150,7 +150,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
-import com.android.internal.view.IInputMethodClient;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.utils.RotationCache;
 import com.android.server.wm.utils.WmDisplayCutout;
@@ -2949,7 +2948,7 @@
         }
     }
 
-    boolean inputMethodClientHasFocus(IInputMethodClient client) {
+    boolean isInputMethodClientFocus(int uid, int pid) {
         final WindowState imFocus = computeImeTarget(false /* updateImeTarget */);
         if (imFocus == null) {
             return false;
@@ -2961,17 +2960,13 @@
             Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
         }
 
-        final IInputMethodClient imeClient = imFocus.mSession.mClient;
-
         if (DEBUG_INPUT_METHOD) {
-            Slog.i(TAG_WM, "IM target client: " + imeClient);
-            if (imeClient != null) {
-                Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder());
-                Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
-            }
+            Slog.i(TAG_WM, "IM target uid/pid: " + imFocus.mSession.mUid
+                    + "/" + imFocus.mSession.mPid);
+            Slog.i(TAG_WM, "Requesting client uid/pid: " + uid + "/" + pid);
         }
 
-        return imeClient != null && imeClient.asBinder() == client.asBinder();
+        return imFocus.mSession.mUid == uid && imFocus.mSession.mPid == pid;
     }
 
     boolean hasSecureWindowOnScreen() {
diff --git a/services/core/java/com/android/server/wm/TEST_MAPPING b/services/core/java/com/android/server/wm/TEST_MAPPING
index c99329a..0c9a14b 100644
--- a/services/core/java/com/android/server/wm/TEST_MAPPING
+++ b/services/core/java/com/android/server/wm/TEST_MAPPING
@@ -21,7 +21,7 @@
           "include-annotation": "android.platform.test.annotations.Presubmit"
         },
         {
-          "exclude-annotation": "android.support.test.filters.FlakyTest"
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
     },
@@ -35,7 +35,7 @@
           "include-annotation": "android.platform.test.annotations.Presubmit"
         },
         {
-          "exclude-annotation": "android.support.test.filters.FlakyTest"
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 793ce60..57cae39 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -30,7 +30,6 @@
 import android.view.MagnificationSpec;
 import android.view.WindowInfo;
 
-import com.android.internal.view.IInputMethodClient;
 import com.android.server.input.InputManagerService;
 import com.android.server.policy.WindowManagerPolicy;
 
@@ -444,9 +443,14 @@
     public abstract boolean isUidFocused(int uid);
 
     /**
-     * Returns {@code true} if a process that is identified by {@code client} has IME focus.
+     * Checks whether the specified process has IME focus or not.
+     *
+     * @param uid UID of the process to be queried
+     * @param pid PID of the process to be queried
+     * @return {@code true} if a process that is identified by {@code uid} and {@code pid} has IME
+     *         focus
      */
-    public abstract boolean inputMethodClientHasFocus(IInputMethodClient client);
+    public abstract boolean isInputMethodClientFocus(int uid, int pid);
 
     /**
      * Return the display Id for given window.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ee128c7..711f66a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7412,12 +7412,12 @@
         }
 
         @Override
-        public boolean inputMethodClientHasFocus(IInputMethodClient client) {
+        public boolean isInputMethodClientFocus(int uid, int pid) {
             synchronized (mWindowMap) {
                 // Check all displays if any input method window has focus.
                 for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) {
                     final DisplayContent displayContent = mRoot.mChildren.get(i);
-                    if (displayContent.inputMethodClientHasFocus(client)) {
+                    if (displayContent.isInputMethodClientFocus(uid, pid)) {
                         return true;
                     }
                 }
@@ -7430,8 +7430,8 @@
                 // press home.  Sometimes the IME won't go down.)
                 // Would be nice to fix this more correctly, but it's
                 // way at the end of a release, and this should be good enough.
-                if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
-                        && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
+                if (mCurrentFocus != null && mCurrentFocus.mSession.mUid == uid
+                        && mCurrentFocus.mSession.mPid == pid) {
                     return true;
                 }
             }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index f6e5601..ffc7fa2 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -188,17 +188,13 @@
 
     @Test
     public void testCanBeLaunchedOnDisplay() throws Exception {
-        testSupportsLaunchingResizeable(false /*taskPresent*/, true /*taskResizeable*/,
-                true /*activityResizeable*/, true /*expected*/);
+        mService.mSupportsMultiWindow = true;
+        final ActivityRecord activity = new ActivityBuilder(mService).build();
 
-        testSupportsLaunchingResizeable(false /*taskPresent*/, true /*taskResizeable*/,
-                false /*activityResizeable*/, false /*expected*/);
-
-        testSupportsLaunchingResizeable(true /*taskPresent*/, false /*taskResizeable*/,
-                true /*activityResizeable*/, false /*expected*/);
-
-        testSupportsLaunchingResizeable(true /*taskPresent*/, true /*taskResizeable*/,
-                false /*activityResizeable*/, true /*expected*/);
+        // An activity can be launched on default display.
+        assertTrue(activity.canBeLaunchedOnDisplay(DEFAULT_DISPLAY));
+        // An activity cannot be launched on a non-existent display.
+        assertFalse(activity.canBeLaunchedOnDisplay(DEFAULT_DISPLAY + 1));
     }
 
     @Test
@@ -229,26 +225,4 @@
         assertNull(mActivity.pendingOptions);
         assertNotNull(activity2.pendingOptions);
     }
-
-    private void testSupportsLaunchingResizeable(boolean taskPresent, boolean taskResizeable,
-            boolean activityResizeable, boolean expected) {
-        mService.mSupportsMultiWindow = true;
-
-        final TaskRecord task = taskPresent
-                ? new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build() : null;
-
-        if (task != null) {
-            task.setResizeMode(taskResizeable ? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_UNRESIZEABLE);
-        }
-
-        final ActivityRecord record = new ActivityBuilder(mService).setTask(task).build();
-        record.info.resizeMode = activityResizeable
-                ? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_UNRESIZEABLE;
-
-        record.canBeLaunchedOnDisplay(DEFAULT_DISPLAY);
-
-
-        verify(mService.mStackSupervisor, times(1)).canPlaceEntityOnDisplay(anyInt(), eq(expected),
-                anyInt(), anyInt(), eq(record.info));
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 5039e42..8ac2930 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -21,18 +21,32 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.app.ActivityManagerInternal;
+import android.content.Context;
+import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.os.BatteryManagerInternal;
+import android.os.Looper;
 import android.os.PowerManager;
 import android.os.PowerSaveState;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.android.server.power.batterysaver.BatterySaverController;
+import com.android.internal.app.IBatteryStats;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.lights.LightsManager;
+import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.power.PowerManagerService.Injector;
+import com.android.server.power.PowerManagerService.NativeWrapper;
+import com.android.server.power.batterysaver.BatterySavingStats;
 
 import org.junit.Rule;
 import org.mockito.Mock;
@@ -47,11 +61,19 @@
     private static final boolean BATTERY_SAVER_ENABLED = true;
     private static final String TEST_LAST_REBOOT_PROPERTY = "test.sys.boot.reason";
 
-    private @Mock BatterySaverPolicy mBatterySaverPolicy;
+    private @Mock BatterySaverPolicy mBatterySaverPolicyMock;
+    private @Mock LightsManager mLightsManagerMock;
+    private @Mock DisplayManagerInternal mDisplayManagerInternalMock;
+    private @Mock BatteryManagerInternal mBatteryManagerInternalMock;
+    private @Mock ActivityManagerInternal mActivityManagerInternalMock;
+    private @Mock PowerManagerService.NativeWrapper mNativeWrapperMock;
+    private @Mock Notifier mNotifierMock;
     private PowerManagerService mService;
     private PowerSaveState mPowerSaveState;
     private DisplayPowerRequest mDisplayPowerRequest;
 
+
+
     @Rule
     public void setUp() throws Exception {
         super.setUp();
@@ -61,11 +83,51 @@
                 .setBatterySaverEnabled(BATTERY_SAVER_ENABLED)
                 .setBrightnessFactor(BRIGHTNESS_FACTOR)
                 .build();
-        when(mBatterySaverPolicy.getBatterySaverPolicy(
+        when(mBatterySaverPolicyMock.getBatterySaverPolicy(
                 eq(PowerManager.ServiceType.SCREEN_BRIGHTNESS), anyBoolean()))
                 .thenReturn(mPowerSaveState);
+
         mDisplayPowerRequest = new DisplayPowerRequest();
-        mService = new PowerManagerService(getContext(), mBatterySaverPolicy);
+        addLocalServiceMock(LightsManager.class, mLightsManagerMock);
+        addLocalServiceMock(DisplayManagerInternal.class, mDisplayManagerInternalMock);
+        addLocalServiceMock(BatteryManagerInternal.class, mBatteryManagerInternalMock);
+        addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
+
+        mService = new PowerManagerService(getContext(), new Injector() {
+            Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
+                    SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
+                return mNotifierMock;
+            }
+
+            SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
+                return mock(SuspendBlocker.class);
+            }
+
+            BatterySaverPolicy createBatterySaverPolicy(
+                    Object lock, Context context, BatterySavingStats batterySavingStats) {
+                return mBatterySaverPolicyMock;
+            }
+
+            NativeWrapper createNativeWrapper() {
+                return mNativeWrapperMock;
+            }
+        });
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        LocalServices.removeServiceForTest(LightsManager.class);
+        LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+        LocalServices.removeServiceForTest(BatteryManagerInternal.class);
+        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+    }
+
+    /**
+     * Creates a mock and registers it to {@link LocalServices}.
+     */
+    private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
+        LocalServices.removeServiceForTest(clazz);
+        LocalServices.addService(clazz, mock);
     }
 
     @SmallTest
@@ -110,6 +172,25 @@
         mService.setVrModeEnabled(false);
         assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
                 DisplayPowerRequest.POLICY_BRIGHT);
+    }
 
+    @SmallTest
+    public void testWakefulnessAwake_InitialValue() throws Exception {
+        assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
+    }
+
+    @SmallTest
+    public void testWakefulnessSleep_NoDozeSleepFlag() throws Exception {
+        // Start with AWAKE state
+        assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
+
+        mService.systemReady(null);
+        mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+
+        // Take a nap with a flag.
+        mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
+            PowerManager.GO_TO_SLEEP_REASON_APPLICATION, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+
+        assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/policy/DummyPolicyTests.java b/services/tests/wmtests/src/com/android/server/policy/DummyPolicyTests.java
new file mode 100644
index 0000000..03fb123
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/DummyPolicyTests.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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 com.android.server.policy;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+
+import androidx.test.filters.FlakyTest;
+
+/**
+ * Dummy test for com.android.server.policy.
+ * TODO(b/113800711): Remove this class once the actual tests are moved from servicestests.
+ */
+public class DummyPolicyTests {
+
+    @Presubmit
+    @Test
+    public void preSubmitTest() {}
+
+    @FlakyTest
+    @Presubmit
+    @Test
+    public void flakyPreSubmitTest() {}
+
+    @Test
+    public void postSubmitTest() {}
+
+    @FlakyTest
+    @Test
+    public void flakyPostSubmitTest() {}
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index c5d6dc7..99ad1f4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -19,6 +19,8 @@
 import android.Manifest;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+
+import com.android.internal.app.IVoiceActionCheckCallback;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
 import android.content.ComponentName;
@@ -1128,6 +1130,27 @@
             }
         }
 
+        @Override
+        public void getActiveServiceSupportedActions(List<String> voiceActions,
+                IVoiceActionCheckCallback callback) {
+            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
+            synchronized (this) {
+                if (mImpl == null) {
+                    try {
+                        callback.onComplete(null);
+                    } catch (RemoteException e) {
+                    }
+                    return;
+                }
+                final long caller = Binder.clearCallingIdentity();
+                try {
+                    mImpl.getActiveServiceSupportedActions(voiceActions, callback);
+                } finally {
+                    Binder.restoreCallingIdentity(caller);
+                }
+            }
+        }
+
         public void onSessionShown() {
             synchronized (this) {
                 final int size = mVoiceInteractionSessionListeners.beginBroadcast();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 57e9f66..61d7d6c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -25,6 +25,8 @@
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
+
+import com.android.internal.app.IVoiceActionCheckCallback;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
@@ -57,6 +59,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConnection.Callback {
     final static String TAG = "VoiceInteractionServiceManager";
@@ -177,6 +180,23 @@
                 activityTokens);
     }
 
+    public void getActiveServiceSupportedActions(List<String> commands,
+            IVoiceActionCheckCallback callback) {
+        if (mService == null) {
+            Slog.w(TAG, "Not bound to voice interaction service " + mComponent);
+            try {
+                callback.onComplete(null);
+            } catch (RemoteException e) {
+            }
+            return;
+        }
+        try {
+            mService.getActiveServiceSupportedActions(commands, callback);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "RemoteException while calling getActiveServiceSupportedActions", e);
+        }
+    }
+
     public boolean hideSessionLocked() {
         if (mActiveSession != null) {
             return mActiveSession.hideLocked();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fa24796..b5d1f06 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6217,36 +6217,25 @@
     /**
      * @deprecated Use {@link android.telecom.TelecomManager#endCall()} instead.
      * @hide
+     * @removed
      */
     @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.CALL_PHONE)
     public boolean endCall() {
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null)
-                return telephony.endCall();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#endCall", e);
-        }
         return false;
     }
 
     /**
      * @deprecated Use {@link android.telecom.TelecomManager#acceptRingingCall} instead
      * @hide
+     * @removed
      */
     @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void answerRingingCall() {
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null)
-                telephony.answerRingingCall();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#answerRingingCall", e);
-        }
+
     }
 
     /**