Merge "Overall improvement on Autofill javadocs for autofillable APIs." into oc-dev
diff --git a/Android.mk b/Android.mk
index b5f8cb0..3f2ae83 100644
--- a/Android.mk
+++ b/Android.mk
@@ -923,6 +923,7 @@
     -android \
     -knowntags ./frameworks/base/docs/knowntags.txt \
     -knowntags ./libcore/known_oj_tags.txt \
+    -manifest ./frameworks/base/core/res/AndroidManifest.xml \
     -hidePackage com.android.org.conscrypt \
     -since $(SRC_API_DIR)/1.xml 1 \
     -since $(SRC_API_DIR)/2.xml 2 \
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 8fd8043..a446296 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -24,6 +24,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.Size;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.BroadcastBehavior;
 import android.app.Activity;
@@ -161,6 +162,7 @@
  * the application's main event thread.  These operations throw
  * {@link IllegalStateException} if they are used on the main thread.
  */
+@SystemService(Context.ACCOUNT_SERVICE)
 public class AccountManager {
 
     private static final String TAG = "AccountManager";
@@ -2509,6 +2511,18 @@
         return new AuthenticatorException(message);
     }
 
+    private void getAccountByTypeAndFeatures(String accountType, String[] features,
+        AccountManagerCallback<Bundle> callback, Handler handler) {
+        (new AmsTask(null, handler, callback) {
+            @Override
+            public void doWork() throws RemoteException {
+                mService.getAccountByTypeAndFeatures(mResponse, accountType, features,
+                    mContext.getOpPackageName());
+            }
+
+        }).start();
+    }
+
     private class GetAuthTokenByTypeAndFeaturesTask
             extends AmsTask implements AccountManagerCallback<Bundle> {
         GetAuthTokenByTypeAndFeaturesTask(final String accountType, final String authTokenType,
@@ -2535,13 +2549,16 @@
 
         @Override
         public void doWork() throws RemoteException {
-            getAccountsByTypeAndFeatures(mAccountType, mFeatures,
-                    new AccountManagerCallback<Account[]>() {
+            getAccountByTypeAndFeatures(mAccountType, mFeatures,
+                    new AccountManagerCallback<Bundle>() {
                         @Override
-                        public void run(AccountManagerFuture<Account[]> future) {
-                            Account[] accounts;
+                        public void run(AccountManagerFuture<Bundle> future) {
+                            String accountName = null;
+                            String accountType = null;
                             try {
-                                accounts = future.getResult();
+                                Bundle result = future.getResult();
+                                accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+                                accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
                             } catch (OperationCanceledException e) {
                                 setException(e);
                                 return;
@@ -2553,9 +2570,7 @@
                                 return;
                             }
 
-                            mNumAccounts = accounts.length;
-
-                            if (accounts.length == 0) {
+                            if (accountName == null) {
                                 if (mActivity != null) {
                                     // no accounts, add one now. pretend that the user directly
                                     // made this request
@@ -2575,63 +2590,17 @@
                                     }
                                     // we are done
                                 }
-                            } else if (accounts.length == 1) {
+                            } else {
+                                mNumAccounts = 1;
+                                Account account = new Account(accountName, accountType);
                                 // have a single account, return an authtoken for it
                                 if (mActivity == null) {
-                                    mFuture = getAuthToken(accounts[0], mAuthTokenType,
+                                    mFuture = getAuthToken(account, mAuthTokenType,
                                             false /* notifyAuthFailure */, mMyCallback, mHandler);
                                 } else {
-                                    mFuture = getAuthToken(accounts[0],
-                                            mAuthTokenType, mLoginOptions,
+                                    mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions,
                                             mActivity, mMyCallback, mHandler);
                                 }
-                            } else {
-                                if (mActivity != null) {
-                                    IAccountManagerResponse chooseResponse =
-                                            new IAccountManagerResponse.Stub() {
-                                        @Override
-                                        public void onResult(Bundle value) throws RemoteException {
-                                            Account account = new Account(
-                                                    value.getString(KEY_ACCOUNT_NAME),
-                                                    value.getString(KEY_ACCOUNT_TYPE),
-                                                    value.getString(KEY_ACCOUNT_ACCESS_ID));
-                                            mFuture = getAuthToken(account, mAuthTokenType,
-                                                    mLoginOptions,  mActivity, mMyCallback,
-                                                    mHandler);
-                                        }
-
-                                        @Override
-                                        public void onError(int errorCode, String errorMessage)
-                                                throws RemoteException {
-                                            mResponse.onError(errorCode, errorMessage);
-                                        }
-                                    };
-                                    // have many accounts, launch the chooser
-                                    Intent intent = new Intent();
-                                    // TODO - this activity will not include
-                                    // USER_MANAGED_NOT_VISIBLE
-                                    // accounts. We need to move method to service
-                                    ComponentName componentName = ComponentName.unflattenFromString(
-                                            Resources.getSystem().getString(
-                                                    R.string.config_chooseAccountActivity));
-                                    intent.setClassName(componentName.getPackageName(),
-                                            componentName.getClassName());
-                                    intent.putExtra(KEY_ACCOUNTS, accounts);
-                                    intent.putExtra(KEY_ACCOUNT_MANAGER_RESPONSE,
-                                            new AccountManagerResponse(chooseResponse));
-                                    mActivity.startActivity(intent);
-                                    // the result will arrive via the IAccountManagerResponse
-                                } else {
-                                    // send result since we can't prompt to select an account
-                                    Bundle result = new Bundle();
-                                    result.putString(KEY_ACCOUNTS, null);
-                                    try {
-                                        mResponse.onResult(result);
-                                    } catch (RemoteException e) {
-                                        // this will never happen
-                                    }
-                                    // we are done
-                                }
                             }
                         }}, mHandler);
         }
@@ -2721,8 +2690,8 @@
     public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
             final String accountType, final String authTokenType, final String[] features,
             final Activity activity, final Bundle addAccountOptions,
-            final Bundle getAuthTokenOptions,
-            final AccountManagerCallback<Bundle> callback, final Handler handler) {
+            final Bundle getAuthTokenOptions, final AccountManagerCallback<Bundle> callback,
+            final Handler handler) {
         if (accountType == null) throw new IllegalArgumentException("account type is null");
         if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
         final GetAuthTokenByTypeAndFeaturesTask task =
@@ -3237,6 +3206,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public AccountManagerFuture<Bundle> finishSessionAsUser(
             final Bundle sessionBundle,
             final Activity activity,
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 7494cfc..4cf0a20 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -40,6 +40,8 @@
     Account[] getAccountsAsUser(String accountType, int userId, String opPackageName);
     void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features,
         String opPackageName);
+    void getAccountByTypeAndFeatures(in IAccountManagerResponse response, String accountType,
+        in String[] features, String opPackageName);
     void getAccountsByFeatures(in IAccountManagerResponse response, String accountType,
         in String[] features, String opPackageName);
     boolean addAccountExplicitly(in Account account, String password, in Bundle extras);
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 38ce427..854e531 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -473,9 +473,13 @@
             if (mReversing) {
                 // Between start() and first frame, mLastEventId would be unset (i.e. -1)
                 mLastEventId = mLastEventId == -1 ? mEvents.size() : mLastEventId;
-                for (int j = mLastEventId - 1; j >= 0; j--) {
-                    AnimationEvent event = mEvents.get(j);
+                while (mLastEventId > 0) {
+                    mLastEventId = mLastEventId - 1;
+                    AnimationEvent event = mEvents.get(mLastEventId);
                     Animator anim = event.mNode.mAnimation;
+                    if (mNodeMap.get(anim).mEnded) {
+                        continue;
+                    }
                     if (event.mEvent == AnimationEvent.ANIMATION_END) {
                         anim.reverse();
                     } else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
@@ -487,9 +491,15 @@
                     }
                 }
             } else {
-                for (int j = mLastEventId + 1; j < mEvents.size(); j++) {
-                    AnimationEvent event = mEvents.get(j);
+                while (mLastEventId < mEvents.size() - 1) {
+                    // Avoid potential reentrant loop caused by child animators manipulating
+                    // AnimatorSet's lifecycle (i.e. not a recommended approach).
+                    mLastEventId = mLastEventId + 1;
+                    AnimationEvent event = mEvents.get(mLastEventId);
                     Animator anim = event.mNode.mAnimation;
+                    if (mNodeMap.get(anim).mEnded) {
+                        continue;
+                    }
                     if (event.mEvent == AnimationEvent.ANIMATION_START) {
                         anim.start();
                     } else if (event.mEvent == AnimationEvent.ANIMATION_END && anim.isStarted()) {
@@ -663,6 +673,10 @@
      * <p>Starting this <code>AnimatorSet</code> will, in turn, start the animations for which
      * it is responsible. The details of when exactly those animations are started depends on
      * the dependency relationships that have been set up between the animations.
+     *
+     * <b>Note:</b> Manipulating AnimatorSet's lifecycle in the child animators' listener callbacks
+     * will lead to undefined behaviors. Also, AnimatorSet will ignore any seeking in the child
+     * animators once {@link #start()} is called.
      */
     @SuppressWarnings("unchecked")
     @Override
diff --git a/core/java/android/annotation/SystemService.java b/core/java/android/annotation/SystemService.java
new file mode 100644
index 0000000..ba5002a
--- /dev/null
+++ b/core/java/android/annotation/SystemService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.content.Context;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Description of a system service available through
+ * {@link Context#getSystemService(Class)}.
+ *
+ * @hide
+ */
+@Retention(SOURCE)
+@Target(TYPE)
+public @interface SystemService {
+    String value();
+}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 369968f..f398c8d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
@@ -117,6 +118,7 @@
  * be used for testing and debugging purposes only.
  * </p>
  */
+@SystemService(Context.ACTIVITY_SERVICE)
 public class ActivityManager {
     private static String TAG = "ActivityManager";
 
@@ -3610,6 +3612,7 @@
      * @hide
      */
     @SystemApi @TestApi
+    @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
     public void addOnUidImportanceListener(OnUidImportanceListener listener,
             @RunningAppProcessInfo.Importance int importanceCutpoint) {
         synchronized (this) {
@@ -3638,6 +3641,7 @@
      * @hide
      */
     @SystemApi @TestApi
+    @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
     public void removeOnUidImportanceListener(OnUidImportanceListener listener) {
         synchronized (this) {
             UidObserver observer = mImportanceListeners.remove(listener);
@@ -4005,6 +4009,10 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            "android.permission.INTERACT_ACROSS_USERS",
+            "android.permission.INTERACT_ACROSS_USERS_FULL"
+    })
     public static int getCurrentUser() {
         UserInfo ui;
         try {
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 620e5cf..2813e8b 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -17,8 +17,10 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
@@ -72,12 +74,8 @@
  * {@link #setExact(int, long, PendingIntent)}.  Applications whose {@code targetSdkVersion}
  * is earlier than API 19 will continue to see the previous behavior in which all
  * alarms are delivered exactly when requested.
- *
- * <p>You do not
- * instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.ALARM_SERVICE)}.
  */
+@SystemService(Context.ALARM_SERVICE)
 public class AlarmManager {
     private static final String TAG = "AlarmManager";
 
@@ -599,6 +597,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void set(@AlarmType int type, long triggerAtMillis, long windowMillis,
             long intervalMillis, PendingIntent operation, WorkSource workSource) {
         setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, operation, null, null,
@@ -633,6 +632,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void set(@AlarmType int type, long triggerAtMillis, long windowMillis,
             long intervalMillis, OnAlarmListener listener, Handler targetHandler,
             WorkSource workSource) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8292152..e672ada 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -17,7 +17,9 @@
 package android.app;
 
 import android.Manifest;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.media.AudioAttributes.AttributeUsage;
@@ -42,10 +44,9 @@
  * API for interacting with "application operation" tracking.
  *
  * <p>This API is not generally intended for third party application developers; most
- * features are only available to system applications.  Obtain an instance of it through
- * {@link Context#getSystemService(String) Context.getSystemService} with
- * {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.</p>
+ * features are only available to system applications.
  */
+@SystemService(Context.APP_OPS_SERVICE)
 public class AppOpsManager {
     /**
      * <p>App ops allows callers to:</p>
@@ -1409,6 +1410,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS)
     public void setUidMode(String appOp, int uid, int mode) {
         try {
             mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 175b979..b6cff38 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.os.Build;
 import android.os.Bundle;
@@ -72,6 +73,7 @@
      * power whitelist when this broadcast is being delivered to it.
      * @param duration The duration in milliseconds; 0 means to not place on whitelist.
      */
+    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
     public void setTemporaryAppWhitelistDuration(long duration) {
         mTemporaryAppWhitelistDuration = duration;
     }
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index b89c165..5baaeb3 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -51,18 +52,15 @@
  * request that a URI be downloaded to a particular destination file. The download manager will
  * conduct the download in the background, taking care of HTTP interactions and retrying downloads
  * after failures or across connectivity changes and system reboots.
- *
- * Instances of this class should be obtained through
- * {@link android.content.Context#getSystemService(String)} by passing
- * {@link android.content.Context#DOWNLOAD_SERVICE}.
- *
+ * <p>
  * Apps that request downloads through this API should register a broadcast receiver for
  * {@link #ACTION_NOTIFICATION_CLICKED} to appropriately handle when the user clicks on a running
  * download in a notification or from the downloads UI.
- *
+ * <p>
  * Note that the application must have the {@link android.Manifest.permission#INTERNET}
  * permission to use this class.
  */
+@SystemService(Context.DOWNLOAD_SERVICE)
 public class DownloadManager {
 
     /**
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index fcf0aab..2a29616 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.app.trust.ITrustManager;
 import android.content.Context;
 import android.content.Intent;
@@ -44,12 +45,11 @@
 import java.util.List;
 
 /**
- * Class that can be used to lock and unlock the keyboard. Get an instance of this
- * class by calling {@link android.content.Context#getSystemService(java.lang.String)}
- * with argument {@link android.content.Context#KEYGUARD_SERVICE}. The
+ * Class that can be used to lock and unlock the keyboard. The
  * actual class to control the keyboard locking is
  * {@link android.app.KeyguardManager.KeyguardLock}.
  */
+@SystemService(Context.KEYGUARD_SERVICE)
 public class KeyguardManager {
 
     private static final String TAG = "KeyguardManager";
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 31f52db..4dd71b4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -22,6 +22,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
@@ -1009,6 +1010,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.NOTIFICATION_DURING_SETUP)
     public static final String EXTRA_ALLOW_DURING_SETUP = "android.allowDuringSetup";
 
     /**
@@ -1110,6 +1112,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME)
     public static final String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
 
     /**
@@ -1168,7 +1171,7 @@
      */
     public static final int GROUP_ALERT_CHILDREN = 2;
 
-    private int mGroupAlertBehavior = GROUP_ALERT_CHILDREN;
+    private int mGroupAlertBehavior = GROUP_ALERT_ALL;
 
     /**
      * If this notification is being shown as a badge, always show as a number.
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 6c55548..235b8d4 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.app.Notification.Builder;
 import android.content.ComponentName;
@@ -81,10 +82,6 @@
  * to the {@link #cancel(int)} or {@link #cancel(String, int)} method to clear
  * this notification.
  *
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
- *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For a guide to creating notifications, read the
@@ -93,10 +90,9 @@
  * </div>
  *
  * @see android.app.Notification
- * @see android.content.Context#getSystemService
  */
-public class NotificationManager
-{
+@SystemService(Context.NOTIFICATION_SERVICE)
+public class NotificationManager {
     private static String TAG = "NotificationManager";
     private static boolean localLOGV = false;
 
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index c529e4b..ea990ad 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.SystemService;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -46,10 +47,6 @@
  * services are provided through methods in {@link android.app.Activity Activity}
  * and the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
  * {@link android.content.Intent Intent}.
- * If you do require direct access to the SearchManager, do not instantiate
- * this class directly. Instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * context.getSystemService(Context.SEARCH_SERVICE)}.
  *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
@@ -58,9 +55,9 @@
  * <a href="{@docRoot}guide/topics/search/index.html">Search</a> developer guide.</p>
  * </div>
  */
+@SystemService(Context.SEARCH_SERVICE)
 public class SearchManager
-        implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener
-{
+        implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener {
 
     private static final boolean DBG = false;
     private static final String TAG = "SearchManager";
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index e57a9b5..fb8bd39 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -18,6 +18,7 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -36,6 +37,7 @@
  *
  * @hide
  */
+@SystemService(Context.STATUS_BAR_SERVICE)
 public class StatusBarManager {
 
     public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND;
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 07e2570..bc61668 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -49,11 +50,8 @@
  * displayed allowing the user to exit dock mode.  Thus the dock mode
  * represented here may be different than the current state of the underlying
  * dock event broadcast.
- *
- * <p>You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.UI_MODE_SERVICE)}.
  */
+@SystemService(Context.UI_MODE_SERVICE)
 public class UiModeManager {
     private static final String TAG = "UiModeManager";
 
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 8014eca..b40c96c 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -1,19 +1,20 @@
 package android.app;
 
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ComponentName;
+import android.content.Context;
 import android.os.RemoteException;
 import android.service.vr.IVrManager;
 
 /**
  * Used to control aspects of a devices Virtual Reality (VR) capabilities.
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
  * @hide
  */
 @SystemApi
+@SystemService(Context.VR_SERVICE)
 public class VrManager {
     private final IVrManager mService;
 
@@ -29,11 +30,10 @@
      * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used
      * by VR viewers to indicate that a device is placed in a VR viewer.
      *
-     * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
-     *
      * @see Activity#setVrModeEnabled(boolean, ComponentName)
      * @param enabled true if the device should be placed in persistent VR mode.
      */
+    @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
     public void setPersistentVrModeEnabled(boolean enabled) {
         try {
             mService.setPersistentVrModeEnabled(enabled);
@@ -46,13 +46,12 @@
      * Sets the resolution and DPI of the vr2d virtual display used to display 2D
      * applications in VR mode.
      *
-     * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
-     *
      * @param vr2dDisplayProp properties to be set to the virtual display for
      * 2D applications in VR mode.
      *
      * {@hide}
      */
+    @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
     public void setVr2dDisplayProperties(
             Vr2dDisplayProperties vr2dDisplayProp) {
         try {
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index db2f937..a850423 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -18,8 +18,10 @@
 
 import android.annotation.IntDef;
 import android.annotation.RawRes;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -76,13 +78,13 @@
 /**
  * Provides access to the system wallpaper. With WallpaperManager, you can
  * get the current wallpaper, get the desired dimensions for the wallpaper, set
- * the wallpaper, and more. Get an instance of WallpaperManager with
- * {@link #getInstance(android.content.Context) getInstance()}.
+ * the wallpaper, and more.
  *
  * <p> An app can check whether wallpapers are supported for the current user, by calling
  * {@link #isWallpaperSupported()}, and whether setting of wallpapers is allowed, by calling
  * {@link #isSetWallpaperAllowed()}.
  */
+@SystemService(Context.WALLPAPER_SERVICE)
 public class WallpaperManager {
     private static String TAG = "WallpaperManager";
     private static boolean DEBUG = false;
@@ -1355,6 +1357,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_HINTS)
     public void setDisplayPadding(Rect padding) {
         try {
             if (sGlobals.mService == null) {
@@ -1395,6 +1398,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
     public void clearWallpaper() {
         clearWallpaper(FLAG_LOCK, mContext.getUserId());
         clearWallpaper(FLAG_SYSTEM, mContext.getUserId());
@@ -1407,6 +1411,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
     public void clearWallpaper(@SetWallpaperFlags int which, int userId) {
         if (sGlobals.mService == null) {
             Log.w(TAG, "WallpaperService not running");
@@ -1422,12 +1427,10 @@
     /**
      * Set the live wallpaper.
      *
-     * This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT
-     * permission.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
     public boolean setWallpaperComponent(ComponentName name) {
         return setWallpaperComponent(name, UserHandle.myUserId());
     }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9ae5d1c..01c4656 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -20,9 +20,12 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
@@ -98,6 +101,7 @@
  * "{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a> developer
  * guide. </div>
  */
+@SystemService(Context.DEVICE_POLICY_SERVICE)
 public class DevicePolicyManager {
     private static String TAG = "DevicePolicyManager";
 
@@ -1601,6 +1605,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public boolean packageHasActiveAdmins(String packageName) {
         return packageHasActiveAdmins(packageName, myUserId());
     }
@@ -4512,11 +4517,10 @@
     /**
      * @return device owner component name, even if it's running on a different user.
      *
-     * <p>Requires the MANAGE_USERS permission.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public ComponentName getDeviceOwnerComponentOnAnyUser() {
         return getDeviceOwnerComponentInner(/* callingUserOnly =*/ false);
     }
@@ -4600,6 +4604,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public @Nullable String getDeviceOwner() {
         throwIfParentInstance("getDeviceOwner");
         final ComponentName name = getDeviceOwnerComponentOnCallingUser();
@@ -4617,6 +4622,7 @@
      */
     @SystemApi
     @TestApi
+    @SuppressLint("Doclava125")
     public boolean isDeviceManaged() {
         try {
             return mService.hasDeviceOwner();
@@ -4629,11 +4635,10 @@
      * Returns the device owner name.  Note this method *will* return the device owner
      * name when it's running on a different user.
      *
-     * <p>Requires the MANAGE_USERS permission.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public String getDeviceOwnerNameOnAnyUser() {
         throwIfParentInstance("getDeviceOwnerNameOnAnyUser");
         if (mService != null) {
@@ -4653,6 +4658,7 @@
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public @Nullable String getDeviceInitializerApp() {
         return null;
     }
@@ -4664,6 +4670,7 @@
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public @Nullable ComponentName getDeviceInitializerComponent() {
         return null;
     }
@@ -4686,6 +4693,7 @@
      */
     @Deprecated
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS)
     public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName)
             throws IllegalArgumentException {
         throwIfParentInstance("setActiveProfileOwner");
@@ -5003,6 +5011,7 @@
      * @throws IllegalArgumentException if the userId is invalid.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public @Nullable String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException {
         throwIfParentInstance("getProfileOwnerNameAsUser");
         if (mService != null) {
@@ -6773,8 +6782,7 @@
      * Called by the system update service to notify device and profile owners of pending system
      * updates.
      *
-     * The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE}
-     * permission. This method should only be used when it is unknown whether the pending system
+     * This method should only be used when it is unknown whether the pending system
      * update is a security patch. Otherwise, use
      * {@link #notifyPendingSystemUpdate(long, boolean)}.
      *
@@ -6785,6 +6793,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.NOTIFY_PENDING_SYSTEM_UPDATE)
     public void notifyPendingSystemUpdate(long updateReceivedTime) {
         throwIfParentInstance("notifyPendingSystemUpdate");
         if (mService != null) {
@@ -6800,8 +6809,7 @@
      * Called by the system update service to notify device and profile owners of pending system
      * updates.
      *
-     * The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE}
-     * permission. This method should be used instead of {@link #notifyPendingSystemUpdate(long)}
+     * This method should be used instead of {@link #notifyPendingSystemUpdate(long)}
      * when it is known whether the pending system update is a security patch.
      *
      * @param updateReceivedTime The time as given by {@link System#currentTimeMillis()}
@@ -6813,6 +6821,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.NOTIFY_PENDING_SYSTEM_UPDATE)
     public void notifyPendingSystemUpdate(long updateReceivedTime, boolean isSecurityPatch) {
         throwIfParentInstance("notifyPendingSystemUpdate");
         if (mService != null) {
@@ -7521,6 +7530,7 @@
      */
     @SystemApi
     @TestApi
+    @SuppressLint("Doclava125")
     public @Nullable CharSequence getDeviceOwnerOrganizationName() {
         try {
             return mService.getDeviceOwnerOrganizationName();
@@ -7711,6 +7721,7 @@
       * @hide
       */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public void setDeviceProvisioningConfigApplied() {
         try {
             mService.setDeviceProvisioningConfigApplied();
@@ -7731,6 +7742,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isDeviceProvisioningConfigApplied() {
         try {
             return mService.isDeviceProvisioningConfigApplied();
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 9d02f53..9f9b217 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -16,6 +16,7 @@
 
 package android.app.backup;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.content.Context;
@@ -324,6 +325,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public RestoreSession beginRestoreSession() {
         RestoreSession session = null;
         checkServiceBinder();
@@ -348,11 +350,10 @@
      * mechanism was disabled will still be backed up properly if it is enabled
      * at some point in the future.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void setBackupEnabled(boolean isEnabled) {
         checkServiceBinder();
         if (sService != null) {
@@ -367,11 +368,10 @@
     /**
      * Report whether the backup mechanism is currently enabled.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public boolean isBackupEnabled() {
         checkServiceBinder();
         if (sService != null) {
@@ -390,11 +390,10 @@
      * the archival restore dataset (if any).  When disabled, no such attempt will
      * be made.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void setAutoRestore(boolean isEnabled) {
         checkServiceBinder();
         if (sService != null) {
@@ -407,14 +406,14 @@
     }
 
     /**
-     * Identify the currently selected transport.  Callers must hold the
-     * android.permission.BACKUP permission to use this method.
+     * Identify the currently selected transport.
      * @return The name of the currently active backup transport.  In case of
      *   failure or if no transport is currently active, this method returns {@code null}.
      *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public String getCurrentTransport() {
         checkServiceBinder();
         if (sService != null) {
@@ -428,12 +427,12 @@
     }
 
     /**
-     * Request a list of all available backup transports' names.  Callers must
-     * hold the android.permission.BACKUP permission to use this method.
+     * Request a list of all available backup transports' names.
      *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public String[] listAllTransports() {
         checkServiceBinder();
         if (sService != null) {
@@ -449,8 +448,6 @@
     /**
      * Specify the current backup transport.
      *
-     * <p> Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @param transport The name of the transport to select.  This should be one
      *   of the names returned by {@link #listAllTransports()}. This is the String returned by
      *   {@link BackupTransport#name()} for the particular transport.
@@ -462,6 +459,7 @@
      */
     @Deprecated
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public String selectBackupTransport(String transport) {
         checkServiceBinder();
         if (sService != null) {
@@ -479,8 +477,6 @@
      * This method is async because BackupManager might need to bind to the specified transport
      * which is in a separate process.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @param transport ComponentName of the service hosting the transport. This is different from
      *                  the transport's name that is returned by {@link BackupTransport#name()}.
      * @param listener A listener object to get a callback on the transport being selected.
@@ -488,6 +484,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void selectBackupTransport(ComponentName transport,
             SelectBackupTransportCallback listener) {
         checkServiceBinder();
@@ -510,11 +507,10 @@
      * transport will still be asked to confirm via the usual requestBackupTime()
      * method.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void backupNow() {
         checkServiceBinder();
         if (sService != null) {
@@ -530,8 +526,6 @@
      * Ask the framework which dataset, if any, the given package's data would be
      * restored from if we were to install it right now.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @param packageName The name of the package whose most-suitable dataset we
      *     wish to look up
      * @return The dataset token from which a restore should be attempted, or zero if
@@ -540,6 +534,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public long getAvailableRestoreToken(String packageName) {
         checkServiceBinder();
         if (sService != null) {
@@ -555,14 +550,13 @@
     /**
      * Ask the framework whether this app is eligible for backup.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @param packageName The name of the package.
      * @return Whether this app is eligible for backup.
      *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public boolean isAppEligibleForBackup(String packageName) {
         checkServiceBinder();
         if (sService != null) {
@@ -592,6 +586,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public int requestBackup(String[] packages, BackupObserver observer) {
         return requestBackup(packages, observer, null, 0);
     }
@@ -615,6 +610,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public int requestBackup(String[] packages, BackupObserver observer,
             BackupManagerMonitor monitor, int flags) {
         checkServiceBinder();
@@ -638,11 +634,10 @@
      * Cancel all running backups. After this call returns, no currently running backups will
      * interact with the selected transport.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void cancelBackups() {
         checkServiceBinder();
         if (sService != null) {
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index 1768828..3868439 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -19,8 +19,11 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ClipData;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.PersistableBundle;
@@ -53,6 +56,7 @@
  * {@link android.content.Context#getSystemService
  * Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)}.
  */
+@SystemService(Context.JOB_SCHEDULER_SERVICE)
 public abstract class JobScheduler {
     /** @hide */
     @IntDef(prefix = { "RESULT_" }, value = {
@@ -132,6 +136,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public abstract @Result int scheduleAsPackage(@NonNull JobInfo job, @NonNull String packageName,
             int userId, String tag);
 
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 06b0aac..54a7e5c 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -18,6 +18,8 @@
 
 import android.Manifest;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -31,6 +33,7 @@
  * See {@link com.android.server.trust.TrustManagerService}
  * @hide
  */
+@SystemService(Context.TRUST_SERVICE)
 public class TrustManager {
 
     private static final int MSG_TRUST_CHANGED = 1;
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 6cd4e92..ef262e0 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -19,6 +19,7 @@
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.app.usage.NetworkStats.Bucket;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -82,6 +83,7 @@
  * the above permission, even to access an app's own data usage, and carrier-privileged apps were
  * not included.
  */
+@SystemService(Context.NETWORK_STATS_SERVICE)
 public class NetworkStatsManager {
     private static final String TAG = "NetworkStatsManager";
     private static final boolean DBG = false;
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index 0b2b190..7c68079 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -20,6 +20,7 @@
 
 import android.annotation.BytesLong;
 import android.annotation.NonNull;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.WorkerThread;
 import android.content.Context;
@@ -50,6 +51,7 @@
  * application.
  * </p>
  */
+@SystemService(Context.STORAGE_STATS_SERVICE)
 public class StorageStatsManager {
     private final Context mContext;
     private final IStorageStatsManager mService;
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 75a4a53..1f939f9 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -16,7 +16,9 @@
 
 package android.app.usage;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.os.RemoteException;
@@ -51,6 +53,7 @@
  * the permission implies intention to use the API and the user of the device can grant permission
  * through the Settings application.
  */
+@SystemService(Context.USAGE_STATS_SERVICE)
 public final class UsageStatsManager {
 
     /**
@@ -252,7 +255,6 @@
      * Temporarily whitelist the specified app for a short duration. This is to allow an app
      * receiving a high priority message to be able to access the network and acquire wakelocks
      * even if the device is in power-save mode or the app is currently considered inactive.
-     * The caller must hold the CHANGE_DEVICE_IDLE_TEMP_WHITELIST permission.
      * @param packageName The package name of the app to whitelist.
      * @param duration Duration to whitelist the app for, in milliseconds. It is recommended that
      * this be limited to 10s of seconds. Requested duration will be clamped to a few minutes.
@@ -261,6 +263,7 @@
      * @see #isAppInactive(String)
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
     public void whitelistAppTemporarily(String packageName, long duration, UserHandle user) {
         try {
             mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier());
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 6327f34..969b19e 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -51,6 +52,7 @@
  * <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> developer guide.</p>
  * </div>
  */
+@SystemService(Context.APPWIDGET_SERVICE)
 public class AppWidgetManager {
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index c7191ba..e2fa38a 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -18,6 +18,7 @@
 
 import android.Manifest;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.RemoteException;
 import android.util.Log;
@@ -48,6 +49,7 @@
  * @see Context#getSystemService
  * @see BluetoothAdapter#getDefaultAdapter()
  */
+@SystemService(Context.BLUETOOTH_SERVICE)
 public final class BluetoothManager {
     private static final String TAG = "BluetoothManager";
     private static final boolean DBG = true;
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 4e70e3f..dabe608 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.app.Activity;
 import android.app.Application;
 import android.app.PendingIntent;
@@ -47,6 +48,7 @@
  *
  * @see AssociationRequest
  */
+@SystemService(Context.COMPANION_DEVICE_SERVICE)
 public final class CompanionDeviceManager {
 
     private static final boolean DEBUG = false;
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index f1c2f34..718e465 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.SystemService;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
@@ -29,10 +30,6 @@
  * the global clipboard.
  *
  * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
- *
- * <p>
  * The ClipboardManager API itself is very simple: it consists of methods
  * to atomically get and set the current primary clipboard data.  That data
  * is expressed as a {@link ClipData} object, which defines the protocol
@@ -44,9 +41,8 @@
  * <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a>
  * developer guide.</p>
  * </div>
- *
- * @see android.content.Context#getSystemService
  */
+@SystemService(Context.CLIPBOARD_SERVICE)
 public class ClipboardManager extends android.text.ClipboardManager {
     private final Context mContext;
     private final IClipboard mService;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 10594af..db80c72 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1630,13 +1630,13 @@
     /**
      * Version of {@link #startActivity(Intent)} that allows you to specify the
      * user the activity will be started for.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS_FULL permission.
+     * that are not pre-installed on the system image.
      * @param intent The description of the activity to start.
      * @param user The UserHandle of the user to start this activity for.
      * @throws ActivityNotFoundException &nbsp;
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public void startActivityAsUser(@RequiresPermission Intent intent, UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
@@ -1672,8 +1672,7 @@
     /**
      * Version of {@link #startActivity(Intent, Bundle)} that allows you to specify the
      * user the activity will be started for.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS_FULL permission.
+     * that are not pre-installed on the system image.
      * @param intent The description of the activity to start.
      * @param options Additional options for how the Activity should be started.
      * May be null if there are no options.  See {@link android.app.ActivityOptions}
@@ -1683,6 +1682,7 @@
      * @throws ActivityNotFoundException &nbsp;
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public void startActivityAsUser(@RequiresPermission Intent intent, @Nullable Bundle options,
             UserHandle userId) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -1781,6 +1781,7 @@
      * @see #startActivities(Intent[])
      * @see PackageManager#resolveActivity
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
@@ -2081,20 +2082,19 @@
     /**
      * Version of {@link #sendBroadcast(Intent)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      * @param intent The intent to broadcast
      * @param user UserHandle to send the intent to.
      * @see #sendBroadcast(Intent)
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user);
 
     /**
      * Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * @param intent The Intent to broadcast; all receivers matching this
      *               Intent will receive the broadcast.
@@ -2105,14 +2105,14 @@
      *
      * @see #sendBroadcast(Intent, String)
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, @Nullable String receiverPermission);
 
     /**
      * Version of {@link #sendBroadcast(Intent, String, Bundle)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * @param intent The Intent to broadcast; all receivers matching this
      *               Intent will receive the broadcast.
@@ -2127,14 +2127,14 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, @Nullable String receiverPermission, @Nullable Bundle options);
 
     /**
      * Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * @param intent The Intent to broadcast; all receivers matching this
      *               Intent will receive the broadcast.
@@ -2148,6 +2148,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, @Nullable String receiverPermission, int appOp);
 
@@ -2156,8 +2157,7 @@
      * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)}
      * that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
@@ -2181,6 +2181,7 @@
      *
      * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendOrderedBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, @Nullable String receiverPermission, BroadcastReceiver resultReceiver,
             @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2192,6 +2193,7 @@
      *       BroadcastReceiver, Handler, int, String, Bundle)
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
             @Nullable String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
             @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2203,6 +2205,7 @@
      *       BroadcastReceiver, Handler, int, String, Bundle)
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
             @Nullable String receiverPermission, int appOp, @Nullable Bundle options,
             BroadcastReceiver resultReceiver, @Nullable Handler scheduler, int initialCode,
@@ -2307,8 +2310,7 @@
     /**
      * <p>Version of {@link #sendStickyBroadcast(Intent)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * @deprecated Sticky broadcasts should not be used.  They provide no security (anyone
      * can access them), no protection (anyone can modify them), and many other problems.
@@ -2324,6 +2326,10 @@
      * @see #sendBroadcast(Intent)
      */
     @Deprecated
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.BROADCAST_STICKY
+    })
     public abstract void sendStickyBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user);
 
@@ -2332,6 +2338,10 @@
      * This is just here for sending CONNECTIVITY_ACTION.
      */
     @Deprecated
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.BROADCAST_STICKY
+    })
     public abstract void sendStickyBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, Bundle options);
 
@@ -2340,8 +2350,7 @@
      * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)}
      * that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
@@ -2369,6 +2378,10 @@
      * @see #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)
      */
     @Deprecated
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.BROADCAST_STICKY
+    })
     public abstract void sendStickyOrderedBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, BroadcastReceiver resultReceiver,
             @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2377,8 +2390,7 @@
     /**
      * <p>Version of {@link #removeStickyBroadcast(Intent)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY}
      * permission in order to use this API.  If you do not hold that
@@ -2396,6 +2408,10 @@
      * @see #sendStickyBroadcastAsUser
      */
     @Deprecated
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.BROADCAST_STICKY
+    })
     public abstract void removeStickyBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user);
 
@@ -2562,9 +2578,7 @@
      * @hide
      * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
      * but for a specific user.  This receiver will receiver broadcasts that
-     * are sent to the requested user.  It
-     * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
-     * permission.
+     * are sent to the requested user.
      *
      * @param receiver The BroadcastReceiver to handle the broadcast.
      * @param user UserHandle to send the intent to.
@@ -2583,6 +2597,7 @@
      * @see #unregisterReceiver
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public abstract Intent registerReceiverAsUser(BroadcastReceiver receiver,
             UserHandle user, IntentFilter filter, @Nullable String broadcastPermission,
             @Nullable Handler scheduler);
@@ -2691,6 +2706,7 @@
      * @hide like {@link #startForegroundService(Intent)} but for a specific user.
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract ComponentName startForegroundServiceAsUser(Intent service, UserHandle user);
 
     /**
@@ -2728,11 +2744,13 @@
      * @hide like {@link #startService(Intent)} but for a specific user.
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
 
     /**
      * @hide like {@link #stopService(Intent)} but for a specific user.
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
 
     /**
@@ -2792,6 +2810,7 @@
      */
     @SystemApi
     @SuppressWarnings("unused")
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public boolean bindServiceAsUser(@RequiresPermission Intent service, ServiceConnection conn,
             int flags, UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -2803,6 +2822,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
             Handler handler, UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index 88aae66..b463ec6 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.SystemService;
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.pm.ApplicationInfo;
@@ -120,6 +121,7 @@
  * @see DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)
  * @see DevicePolicyManager#setApplicationRestrictions(ComponentName, String, Bundle)
  */
+@SystemService(Context.RESTRICTIONS_SERVICE)
 public class RestrictionsManager {
 
     private static final String TAG = "RestrictionsManager";
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 8ead0ec..ed41e79 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.TestApi;
 import android.app.PendingIntent;
@@ -79,6 +80,7 @@
  * Note as of Android O, apps on a managed profile are no longer allowed to access apps on the
  * main profile.  Apps can only access profiles returned by {@link #getProfiles()}.
  */
+@SystemService(Context.LAUNCHER_APPS_SERVICE)
 public class LauncherApps {
 
     static final String TAG = "LauncherApps";
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 4e11233..7f3f35f 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -473,6 +473,7 @@
 
     /** {@hide} */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
     public void setPermissionsResult(int sessionId, boolean accepted) {
         try {
             mInstaller.setPermissionsResult(sessionId, accepted);
@@ -1156,6 +1157,7 @@
 
         /** {@hide} */
         @SystemApi
+        @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
         public void setAllocateAggressive(boolean allocateAggressive) {
             if (allocateAggressive) {
                 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a68c097..be2cd10 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3208,8 +3208,7 @@
 
     /**
      * Return a List of all packages that are installed on the device, for a
-     * specific user. Requesting a list of installed packages for another user
-     * will require the permission INTERACT_ACROSS_USERS_FULL.
+     * specific user.
      *
      * @param flags Additional option flags to modify the data returned.
      * @param userId The user for whom the installed packages are to be listed
@@ -3224,6 +3223,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public abstract List<PackageInfo> getInstalledPackagesAsUser(@PackageInfoFlags int flags,
             @UserIdInt int userId);
 
@@ -3365,6 +3365,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
     public abstract void grantRuntimePermission(@NonNull String packageName,
             @NonNull String permissionName, @NonNull UserHandle user);
 
@@ -3390,6 +3391,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
     public abstract void revokeRuntimePermission(@NonNull String packageName,
             @NonNull String permissionName, @NonNull UserHandle user);
 
@@ -3404,6 +3406,10 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+            android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+    })
     public abstract @PermissionFlags int getPermissionFlags(String permissionName,
             String packageName, @NonNull UserHandle user);
 
@@ -3420,6 +3426,10 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+            android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+    })
     public abstract void updatePermissionFlags(String permissionName,
             String packageName, @PermissionFlags int flagMask, @PermissionFlags int flagValues,
             @NonNull UserHandle user);
@@ -4719,6 +4729,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT)
     public abstract void verifyIntentFilter(int verificationId, int verificationCode,
             List<String> failedDomains);
 
@@ -4766,6 +4777,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
     public abstract boolean updateIntentVerificationStatusAsUser(String packageName, int status,
             @UserIdInt int userId);
 
@@ -4826,6 +4838,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
     public abstract boolean setDefaultBrowserPackageNameAsUser(String packageName,
             @UserIdInt int userId);
 
@@ -5289,6 +5302,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
     public abstract void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener);
 
     /**
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 4cee2df..99700df 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -18,7 +18,11 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.pm.PackageManager.ApplicationInfoFlags;
+import android.content.pm.PackageManager.ComponentInfoFlags;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager.PackageInfoFlags;
+import android.content.pm.PackageManager.ResolveInfoFlags;
 import android.os.Bundle;
 import android.util.SparseArray;
 
@@ -133,16 +137,40 @@
     public abstract boolean isPermissionsReviewRequired(String packageName, int userId);
 
     /**
-     * Gets all of the information we know about a particular package.
-     *
-     * @param packageName The package name to find.
-     * @param userId The user under which to check.
-     *
-     * @return An {@link ApplicationInfo} containing information about the
-     *         package, or {@code null} if no application exists with that
-     *         package name.
+     * Retrieve all of the information we know about a particular package/application.
+     * @param filterCallingUid The results will be filtered in the context of this UID instead
+     * of the calling UID.
+     * @see PackageManager#getPackageInfo(String, int)
      */
-    public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
+    public abstract PackageInfo getPackageInfo(String packageName,
+            @PackageInfoFlags int flags, int filterCallingUid, int userId);
+
+    /**
+     * Retrieve all of the information we know about a particular package/application.
+     * @param filterCallingUid The results will be filtered in the context of this UID instead
+     * of the calling UID.
+     * @see PackageManager#getApplicationInfo(String, int)
+     */
+    public abstract ApplicationInfo getApplicationInfo(String packageName,
+            @ApplicationInfoFlags int flags, int filterCallingUid, int userId);
+
+    /**
+     * Retrieve all of the information we know about a particular activity class.
+     * @param filterCallingUid The results will be filtered in the context of this UID instead
+     * of the calling UID.
+     * @see PackageManager#getActivityInfo(ComponentName, int)
+     */
+    public abstract ActivityInfo getActivityInfo(ComponentName component,
+            @ComponentInfoFlags int flags, int filterCallingUid, int userId);
+
+    /**
+     * Retrieve all activities that can be performed for the given intent.
+     * @param filterCallingUid The results will be filtered in the context of this UID instead
+     * of the calling UID.
+     * @see PackageManager#queryIntentActivities(Intent, int)
+     */
+    public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
+            @ResolveInfoFlags int flags, int filterCallingUid, int userId);
 
     /**
      * Interface to {@link com.android.server.pm.PackageManagerService#getHomeActivitiesAsUser}.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 9b0bab4..5e5a6fc 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -7000,6 +7000,7 @@
             return null;
         }
         if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
+            updateApplicationInfo(a.info.applicationInfo, flags, state);
             return a.info;
         }
         // Make shallow copies so we can store the metadata safely
@@ -7088,6 +7089,7 @@
             return null;
         }
         if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
+            updateApplicationInfo(s.info.applicationInfo, flags, state);
             return s.info;
         }
         // Make shallow copies so we can store the metadata safely
@@ -7183,6 +7185,7 @@
         if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
                 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
                         || p.info.uriPermissionPatterns == null)) {
+            updateApplicationInfo(p.info.applicationInfo, flags, state);
             return p.info;
         }
         // Make shallow copies so we can store the metadata safely
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index f779aeb..c0b82b4 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
 import android.app.Activity;
@@ -24,6 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.graphics.drawable.AdaptiveIconDrawable;
 import android.os.Build.VERSION_CODES;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -335,6 +337,14 @@
  * {@link #isRequestPinShortcutSupported()}. Based on this return value, you might decide to hide
  * the option in your app that allows users to pin a shortcut.
  *
+ * <p class="note"><strong>Note:</strong> See also the support library APIs
+ * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
+ * Context)} and
+ * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut(
+ * Context, ShortcutInfoCompat, IntentSender)}, which works on Android versions lower than
+ * {@link VERSION_CODES#O} by falling back to the deprecated private intent
+ * {@code com.android.launcher.action.INSTALL_SHORTCUT}.
+ *
  * <h4>Custom Activity for Pinning Shortcuts</h4>
  *
  * <p>You can also create a specialized activity that helps users create shortcuts, complete with
@@ -569,6 +579,7 @@
  * All shortcut information is stored in credential encrypted storage, so no shortcuts can be
  * accessed when the user is locked.
  */
+@SystemService(Context.SHORTCUT_SERVICE)
 public class ShortcutManager {
     private static final String TAG = "ShortcutManager";
 
@@ -889,7 +900,7 @@
      *
      * <p> Note that this method returns max width of icon's visible part. Hence, it does not take
      * into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image
-     * to function as {@link AcaptiveIconDrawable}, multiply
+     * to function as {@link AdaptiveIconDrawable}, multiply
      * 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size.
      */
     public int getIconMaxWidth() {
@@ -938,8 +949,15 @@
      * Return {@code TRUE} if the app is running on a device whose default launcher supports
      * {@link #requestPinShortcut(ShortcutInfo, IntentSender)}.
      *
-     * <p><b>Note:</b> The return value may change in subsequent calls, if the user changes
-     * the default launcher app.
+     * <p>The return value may change in subsequent calls if the user changes the default launcher
+     * app.
+     *
+     * <p><b>Note:</b> See also the support library counterpart
+     * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
+     * Context)}, which supports Android versions lower than {@link VERSION_CODES#O} using the
+     * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
+     *
+     * @see #requestPinShortcut(ShortcutInfo, IntentSender)
      */
     public boolean isRequestPinShortcutSupported() {
         try {
@@ -963,6 +981,12 @@
      * package calls this API multiple times in a row. One possible strategy is to ignore any
      * previous requests.
      *
+     * <p><b>Note:</b> See also the support library counterpart
+     * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut(
+     * Context, ShortcutInfoCompat, IntentSender)},
+     * which supports Android versions lower than {@link VERSION_CODES#O} using the
+     * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
+     *
      * @param shortcut Shortcut to pin.  If an app wants to pin an existing (either static
      *     or dynamic) shortcut, then it only needs to have an ID. Although other fields don't have
      *     to be set, the target shortcut must be enabled.
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
index b221e16..c7a33ff 100644
--- a/core/java/android/hardware/ConsumerIrManager.java
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -16,6 +16,7 @@
 
 package android.hardware;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -24,14 +25,8 @@
 
 /**
  * Class that operates consumer infrared on the device.
- *
- * <p>
- * To obtain an instance of the system infrared transmitter, call
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with
- * {@link android.content.Context#CONSUMER_IR_SERVICE} as the argument.
- * </p>
  */
+@SystemService(Context.CONSUMER_IR_SERVICE)
 public final class ConsumerIrManager {
     private static final String TAG = "ConsumerIr";
 
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index ed56391..4bc62b1 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -17,6 +17,8 @@
 package android.hardware;
 
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.Build;
 import android.os.Handler;
 import android.os.MemoryFile;
@@ -30,10 +32,7 @@
 /**
  * <p>
  * SensorManager lets you access the device's {@link android.hardware.Sensor
- * sensors}. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#SENSOR_SERVICE}.
+ * sensors}.
  * </p>
  * <p>
  * Always make sure to disable sensors you don't need, especially when your
@@ -79,6 +78,7 @@
  * @see Sensor
  *
  */
+@SystemService(Context.SENSOR_SERVICE)
 public abstract class SensorManager {
     /** @hide */
     protected static final String TAG = "SensorManager";
diff --git a/core/java/android/hardware/SerialManager.java b/core/java/android/hardware/SerialManager.java
index 83f7649..610f6a5 100644
--- a/core/java/android/hardware/SerialManager.java
+++ b/core/java/android/hardware/SerialManager.java
@@ -16,6 +16,7 @@
 
 package android.hardware;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -25,6 +26,7 @@
 /**
  * @hide
  */
+@SystemService(Context.SERIAL_SERVICE)
 public class SerialManager {
     private static final String TAG = "SerialManager";
 
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index f61032e..1b150bf 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -17,6 +17,7 @@
 package android.hardware.camera2;
 
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -44,15 +45,11 @@
  * <p>A system service manager for detecting, characterizing, and connecting to
  * {@link CameraDevice CameraDevices}.</p>
  *
- * <p>You can get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService()}.</p>
- *
- * <pre>CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);</pre>
- *
  * <p>For more details about communicating with camera devices, read the Camera
  * developer guide or the {@link android.hardware.camera2 camera2}
  * package documentation.</p>
  */
+@SystemService(Context.CAMERA_SERVICE)
 public final class CameraManager {
 
     private static final String TAG = "CameraManager";
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 266be9a..6a02b6b 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.media.projection.MediaProjection;
 import android.os.Handler;
@@ -29,13 +30,8 @@
 
 /**
  * Manages the properties of attached displays.
- * <p>
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#DISPLAY_SERVICE}.
- * </p>
  */
+@SystemService(Context.DISPLAY_SERVICE)
 public final class DisplayManager {
     private static final String TAG = "DisplayManager";
     private static final boolean DEBUG = false;
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 324a08c..b51a791 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.Binder;
@@ -47,12 +48,8 @@
 
 /**
  * A class that coordinates access to the fingerprint hardware.
- * <p>
- * Use {@link android.content.Context#getSystemService(java.lang.String)}
- * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get
- * an instance of this class.
  */
-
+@SystemService(Context.FINGERPRINT_SERVICE)
 public class FingerprintManager {
     private static final String TAG = "FingerprintManager";
     private static final boolean DEBUG = true;
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 27e2a50..a772cbe 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -17,9 +17,13 @@
 package android.hardware.hdmi;
 
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
+import android.content.Context;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -37,6 +41,7 @@
  * @hide
  */
 @SystemApi
+@SystemService(Context.HDMI_CONTROL_SERVICE)
 public final class HdmiControlManager {
     private static final String TAG = "HdmiControlManager";
 
@@ -295,6 +300,7 @@
      * See {@link HdmiDeviceInfo#DEVICE_TV}
      */
     @Nullable
+    @SuppressLint("Doclava125")
     public HdmiClient getClient(int type) {
         if (mService == null) {
             return null;
@@ -319,6 +325,7 @@
      * @return {@link HdmiPlaybackClient} instance. {@code null} on failure.
      */
     @Nullable
+    @SuppressLint("Doclava125")
     public HdmiPlaybackClient getPlaybackClient() {
         return (HdmiPlaybackClient) getClient(HdmiDeviceInfo.DEVICE_PLAYBACK);
     }
@@ -333,6 +340,7 @@
      * @return {@link HdmiTvClient} instance. {@code null} on failure.
      */
     @Nullable
+    @SuppressLint("Doclava125")
     public HdmiTvClient getTvClient() {
         return (HdmiTvClient) getClient(HdmiDeviceInfo.DEVICE_TV);
     }
@@ -343,6 +351,7 @@
      *
      * @param isStandbyModeOn target status of the system's standby mode
      */
+    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
     public void setStandbyMode(boolean isStandbyModeOn) {
         try {
             mService.setStandbyMode(isStandbyModeOn);
@@ -403,6 +412,7 @@
      * @param listener {@link HotplugEventListener} instance
      * @see HdmiControlManager#removeHotplugEventListener(HotplugEventListener)
      */
+    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
     public void addHotplugEventListener(HotplugEventListener listener) {
         if (mService == null) {
             Log.e(TAG, "HdmiControlService is not available");
@@ -426,6 +436,7 @@
      *
      * @param listener {@link HotplugEventListener} instance to be removed
      */
+    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
     public void removeHotplugEventListener(HotplugEventListener listener) {
         if (mService == null) {
             Log.e(TAG, "HdmiControlService is not available");
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 631b77d..5149e93 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -53,13 +54,8 @@
 
 /**
  * Provides information about input devices and available key layouts.
- * <p>
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#INPUT_SERVICE}.
- * </p>
  */
+@SystemService(Context.INPUT_SERVICE)
 public final class InputManager {
     private static final String TAG = "InputManager";
     private static final boolean DEBUG = false;
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 7c4df47..6050046 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -15,7 +15,10 @@
  */
 package android.hardware.location;
 
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
@@ -33,6 +36,7 @@
  * @hide
  */
 @SystemApi
+@SystemService(Context.CONTEXTHUB_SERVICE)
 public final class ContextHubManager {
 
     private static final String TAG = "ContextHubManager";
@@ -91,6 +95,7 @@
      * Get a handle to all the context hubs in the system
      * @return array of context hub handles
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int[] getContextHubHandles() {
         try {
             return mService.getContextHubHandles();
@@ -107,6 +112,7 @@
      *
      * @see ContextHubInfo
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public ContextHubInfo getContextHubInfo(int hubHandle) {
         try {
             return mService.getContextHubInfo(hubHandle);
@@ -134,6 +140,7 @@
      *
      * @see NanoApp
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int loadNanoApp(int hubHandle, NanoApp app) {
         try {
             return mService.loadNanoApp(hubHandle, app);
@@ -157,6 +164,7 @@
      * @return 0 if the command for unloading was sent to the context hub;
      *         -1 otherwise
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int unloadNanoApp(int nanoAppHandle) {
         try {
             return mService.unloadNanoApp(nanoAppHandle);
@@ -191,6 +199,7 @@
      *
      * @see NanoAppInstanceInfo
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
         try {
             return mService.getNanoAppInstanceInfo(nanoAppHandle);
@@ -209,6 +218,7 @@
      *
      * @return int[] Array of handles to any found nano apps
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
         try {
             return mService.findNanoAppOnHub(hubHandle, filter);
@@ -236,6 +246,7 @@
      *
      * @return int 0 on success, -1 otherwise
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
         try {
             return mService.sendMessage(hubHandle, nanoAppHandle, message);
@@ -253,6 +264,7 @@
      *
      * @return int 0 on success, -1 otherwise
      */
+    @SuppressLint("Doclava125")
     public int registerCallback(Callback callback) {
         return registerCallback(callback, null);
     }
@@ -281,6 +293,7 @@
      *
      * @return int 0 on success, -1 otherwise
      */
+    @SuppressLint("Doclava125")
     public int registerCallback(Callback callback, Handler handler) {
         synchronized(this) {
             if (mCallback != null) {
@@ -302,6 +315,7 @@
      *
      * @return int 0 on success, -1 otherwise
      */
+    @SuppressLint("Doclava125")
     public int unregisterCallback(Callback callback) {
       synchronized(this) {
           if (callback != mCallback) {
diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java
index 14bb923..403b13c 100644
--- a/core/java/android/hardware/radio/RadioManager.java
+++ b/core/java/android/hardware/radio/RadioManager.java
@@ -17,6 +17,7 @@
 package android.hardware.radio;
 
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Parcel;
@@ -32,6 +33,7 @@
  * @hide
  */
 @SystemApi
+@SystemService(Context.RADIO_SERVICE)
 public class RadioManager {
 
     /** Method return status: successful operation */
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index b2a2aaf..33a92fd 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -19,6 +19,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -38,18 +39,13 @@
  * This class allows you to access the state of USB and communicate with USB devices.
  * Currently only host mode is supported in the public API.
  *
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- *
- * {@samplecode
- * UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);}
- *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For more information about communicating with USB hardware, read the
  * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB developer guide</a>.</p>
  * </div>
  */
+@SystemService(Context.USB_SERVICE)
 public class UsbManager {
     private static final String TAG = "UsbManager";
 
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index b0cc38c..e64cbcd 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -23,6 +23,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -64,9 +65,7 @@
 
 /**
  * Class that answers queries about the state of network connectivity. It also
- * notifies applications when network connectivity changes. Get an instance
- * of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.CONNECTIVITY_SERVICE)}.
+ * notifies applications when network connectivity changes.
  * <p>
  * The primary responsibilities of this class are to:
  * <ol>
@@ -80,6 +79,7 @@
  * traffic</li>
  * </ol>
  */
+@SystemService(Context.CONNECTIVITY_SERVICE)
 public class ConnectivityManager {
     private static final String TAG = "ConnectivityManager";
 
@@ -2105,6 +2105,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void startTethering(int type, boolean showProvisioningUi,
             final OnStartTetheringCallback callback, Handler handler) {
         checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
@@ -2139,6 +2140,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void stopTethering(int type) {
         try {
             mService.stopTethering(type);
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 664b7b4..31a3096 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.net.IEthernetManager;
 import android.net.IEthernetServiceListener;
@@ -31,6 +32,7 @@
  *
  * @hide
  */
+@SystemService(Context.ETHERNET_SERVICE)
 public class EthernetManager {
     private static final String TAG = "EthernetManager";
     private static final int MSG_AVAILABILITY_CHANGED = 1000;
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 114e46e..e3cda5e 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -18,6 +18,8 @@
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.NonNull;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
@@ -34,12 +36,9 @@
  * This class contains methods for managing IPsec sessions, which will perform kernel-space
  * encryption and decryption of socket or Network traffic.
  *
- * <p>An IpSecManager may be obtained by calling {@link
- * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link
- * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE}
- *
  * @hide
  */
+@SystemService(Context.IPSEC_SERVICE)
 public final class IpSecManager {
     private static final String TAG = "IpSecManager";
 
diff --git a/core/java/android/net/NetworkBadging.java b/core/java/android/net/NetworkBadging.java
index 6de28b7..c119b63 100644
--- a/core/java/android/net/NetworkBadging.java
+++ b/core/java/android/net/NetworkBadging.java
@@ -66,15 +66,7 @@
      */
     @NonNull public static Drawable getWifiIcon(
             @IntRange(from=0, to=4) int signalLevel, @Badging int badging, @Nullable Theme theme) {
-        Resources resources = Resources.getSystem();
-        if (badging == BADGING_NONE) {
-            return resources.getDrawable(getWifiSignalResource(signalLevel), theme);
-        }
-        Drawable[] layers = new Drawable[] {
-                resources.getDrawable(getBadgedWifiSignalResource(signalLevel), theme),
-                resources.getDrawable(getWifiBadgeResource(badging), theme)
-        };
-        return new LayerDrawable(layers);
+        return Resources.getSystem().getDrawable(getWifiSignalResource(signalLevel), theme);
     }
 
     /**
@@ -134,31 +126,4 @@
                 throw new IllegalArgumentException("Invalid signal level: " + signalLevel);
         }
     }
-
-    /**
-     * Returns the wifi quality badge resource id for the the given badging balue.
-     *
-     * <p>This badge should be displayed with the badge signal resource retrieved from
-     * {@link #getBadgedWifiSignalResource(int)}.
-     *
-     * @param badging {@see NetworkBadging#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
-     * @return the @DrawableRes for the icon or {@link View#NO_ID} for
-     *         {@link NetworkBadging#BADGING_NONE}
-     * @throws IllegalArgumentException for an invalid badging value.
-     * @hide
-     */
-    @DrawableRes private static int getWifiBadgeResource(@Badging int badging) {
-        switch (badging) {
-            case BADGING_NONE:
-                return View.NO_ID;
-            case BADGING_SD:
-                return com.android.internal.R.drawable.ic_signal_wifi_badged_sd;
-            case BADGING_HD:
-                return com.android.internal.R.drawable.ic_signal_wifi_badged_hd;
-            case BADGING_4K:
-                return com.android.internal.R.drawable.ic_signal_wifi_badged_4k;
-            default:
-                throw new IllegalArgumentException("No resource found for badge: " + badging);
-        }
-    }
 }
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 43fab03..4d94a55 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.GET_SIGNATURES;
 import static android.net.NetworkPolicy.CYCLE_NONE;
 
+import android.annotation.SystemService;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +41,7 @@
  *
  * {@hide}
  */
+@SystemService(Context.NETWORK_POLICY_SERVICE)
 public class NetworkPolicyManager {
 
     /* POLICY_* are masks and can be ORed, although currently they are not.*/
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 9f6e45c..7e0c9ce 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -19,9 +19,11 @@
 import android.Manifest.permission;
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -34,12 +36,6 @@
 /**
  * Class that manages communication between network subsystems and a network scorer.
  *
- * <p>You can get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String)}:
- *
- * <pre>NetworkScoreManager manager =
- *     (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE)</pre>
- *
  * <p>A network scorer is any application which:
  * <ul>
  * <li>Declares the {@link permission#SCORE_NETWORKS} permission.
@@ -51,6 +47,7 @@
  * @hide
  */
 @SystemApi
+@SystemService(Context.NETWORK_SCORE_SERVICE)
 public class NetworkScoreManager {
     /**
      * Activity action: ask the user to change the active network scorer. This will show a dialog
@@ -243,6 +240,7 @@
      * @hide
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
     public NetworkScorerAppData getActiveScorer() {
         try {
             return mService.getActiveScorer();
@@ -276,6 +274,7 @@
      * @return whether the update was successful.
      * @throws SecurityException if the caller is not the active scorer.
      */
+    @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
     public boolean updateScores(ScoredNetwork[] networks) throws SecurityException {
         try {
             return mService.updateScores(networks);
@@ -296,6 +295,7 @@
      * @return whether the clear was successful.
      * @throws SecurityException if the caller is not the active scorer or privileged.
      */
+    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
     public boolean clearScores() throws SecurityException {
         try {
             return mService.clearScores();
@@ -316,6 +316,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
     public boolean setActiveScorer(String packageName) throws SecurityException {
         try {
             return mService.setActiveScorer(packageName);
@@ -331,6 +332,7 @@
      *
      * @throws SecurityException if the caller is neither the active scorer nor the system.
      */
+    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
     public void disableScoring() throws SecurityException {
         try {
             mService.disableScoring();
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index fc66395..f934616 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.DownloadManager;
 import android.app.backup.BackupManager;
@@ -243,6 +244,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public static void setThreadStatsUid(int uid) {
         NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
     }
@@ -255,6 +257,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public static void clearThreadStatsUid() {
         NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
     }
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index c6daa15..2d9860c 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -19,6 +19,7 @@
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.Activity;
 import android.app.PendingIntent;
@@ -177,6 +178,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CONTROL_VPN)
     public static void prepareAndAuthorize(Context context) {
         IConnectivityManager cm = getService();
         String packageName = context.getPackageName();
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 1dde3ca..2d480a1 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -17,6 +17,7 @@
 package android.net.nsd;
 
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.os.Handler;
@@ -113,11 +114,9 @@
  * http://www.iana.org/form/ports-service. Existing services can be found at
  * http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
  *
- * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.NSD_SERVICE)}.
- *
  * {@see NsdServiceInfo}
  */
+@SystemService(Context.NSD_SERVICE)
 public final class NsdManager {
     private static final String TAG = NsdManager.class.getSimpleName();
     private static final boolean DBG = false;
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 783c25a..48869c7 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -18,6 +18,7 @@
 
 import java.util.HashMap;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
@@ -725,6 +726,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean enable() {
         try {
             return sService.enable();
@@ -753,6 +755,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean disable() {
         try {
             return sService.disable(true);
@@ -767,6 +770,7 @@
      * @hide
     */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean disable(boolean persist) {
         try {
             return sService.disable(persist);
@@ -1552,6 +1556,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean enableNdefPush() {
         if (!sHasNfcFeature) {
             throw new UnsupportedOperationException();
@@ -1570,6 +1575,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean disableNdefPush() {
         synchronized (NfcAdapter.class) {
             if (!sHasNfcFeature) {
@@ -1736,6 +1742,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
                                        String[] tagTechnologies) {
         synchronized (NfcAdapter.class) {
@@ -1785,6 +1792,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
         synchronized (NfcAdapter.class) {
             if (!sHasNfcFeature) {
diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java
index ea08014..50d6745 100644
--- a/core/java/android/nfc/NfcManager.java
+++ b/core/java/android/nfc/NfcManager.java
@@ -16,6 +16,7 @@
 
 package android.nfc;
 
+import android.annotation.SystemService;
 import android.content.Context;
 
 /**
@@ -34,9 +35,9 @@
  * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p>
  * </div>
  *
- * @see Context#getSystemService
  * @see NfcAdapter#getDefaultAdapter(android.content.Context)
  */
+@SystemService(Context.NFC_SERVICE)
 public final class NfcManager {
     private final NfcAdapter mAdapter;
 
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 734d89e..f715f50 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.annotation.SystemService;
+import android.content.Context;
 import android.hardware.health.V1_0.Constants;
 import com.android.internal.app.IBatteryStats;
 
@@ -24,6 +26,7 @@
  * in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent, and
  * provides a method for querying battery and charging properties.
  */
+@SystemService(Context.BATTERY_SERVICE)
 public class BatteryManager {
     /**
      * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index ecc4dec..635df4c 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -201,7 +201,7 @@
      * New in version 22:
      *   - BLE scan result background count, BLE unoptimized scan time
      */
-    static final String CHECKIN_VERSION = "22";
+    static final String CHECKIN_VERSION = "23";
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
@@ -3051,6 +3051,7 @@
             boolean wifiOnly) {
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
+        final long rawRealtimeMs = (rawRealtime + 500) / 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
         final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
         final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
@@ -3437,7 +3438,6 @@
                     final int count = bleTimer.getCountLocked(which);
                     final Timer bleTimerBg = u.getBluetoothScanBackgroundTimer();
                     final int countBg = bleTimerBg != null ? bleTimerBg.getCountLocked(which) : 0;
-                    final long rawRealtimeMs = (rawRealtime + 500) / 1000;
                     // 'actualTime' are unpooled and always since reset (regardless of 'which')
                     final long actualTime = bleTimer.getTotalDurationMsLocked(rawRealtimeMs);
                     final long actualTimeBg = bleTimerBg != null ?
@@ -3486,11 +3486,11 @@
 
             if (u.getAggregatedPartialWakelockTimer() != null) {
                 final Timer timer = u.getAggregatedPartialWakelockTimer();
-                // Convert from microseconds to milliseconds with rounding
-                final long totTimeMs = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                // Times are since reset (regardless of 'which')
+                final long totTimeMs = timer.getTotalDurationMsLocked(rawRealtimeMs);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTimeMs = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0;
                 dumpLine(pw, uid, category, AGGREGATED_WAKELOCK_DATA, totTimeMs, bgTimeMs);
             }
 
@@ -3527,7 +3527,7 @@
                 final int count = timer.getCountLocked(which);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTime = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
                 final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 if (totalTime != 0) {
                     dumpLine(pw, uid, category, SYNC_DATA, "\"" + syncs.keyAt(isy) + "\"",
@@ -3543,7 +3543,7 @@
                 final int count = timer.getCountLocked(which);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTime = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
                 final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 if (totalTime != 0) {
                     dumpLine(pw, uid, category, JOB_DATA, "\"" + jobs.keyAt(ij) + "\"",
@@ -3574,7 +3574,6 @@
                         final int count = timer.getCountLocked(which);
                         final Timer bgTimer = se.getSensorBackgroundTime();
                         final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : 0;
-                        final long rawRealtimeMs = (rawRealtime + 500) / 1000;
                         // 'actualTime' are unpooled and always since reset (regardless of 'which')
                         final long actualTime = timer.getTotalDurationMsLocked(rawRealtimeMs);
                         final long bgActualTime = bgTimer != null ?
@@ -3715,6 +3714,7 @@
             int reqUid, boolean wifiOnly) {
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
+        final long rawRealtimeMs = (rawRealtime + 500) / 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
 
         final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
@@ -4655,7 +4655,6 @@
                     final int count = bleTimer.getCountLocked(which);
                     final Timer bleTimerBg = u.getBluetoothScanBackgroundTimer();
                     final int countBg = bleTimerBg != null ? bleTimerBg.getCountLocked(which) : 0;
-                    final long rawRealtimeMs = (rawRealtime + 500) / 1000;
                     // 'actualTime' are unpooled and always since reset (regardless of 'which')
                     final long actualTimeMs = bleTimer.getTotalDurationMsLocked(rawRealtimeMs);
                     final long actualTimeMsBg = bleTimerBg != null ?
@@ -4823,10 +4822,10 @@
                     final Timer aggTimer = u.getAggregatedPartialWakelockTimer();
                     // Convert from microseconds to milliseconds with rounding
                     actualTotalPartialWakelock =
-                            (aggTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                            aggTimer.getTotalDurationMsLocked(rawRealtimeMs);
                     final Timer bgAggTimer = aggTimer.getSubTimer();
                     actualBgPartialWakelock = bgAggTimer != null ?
-                            (bgAggTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0;
+                            bgAggTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0;
                 }
 
                 if (actualTotalPartialWakelock != 0 || actualBgPartialWakelock != 0 ||
@@ -4894,7 +4893,7 @@
                 final int count = timer.getCountLocked(which);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTime = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
                 final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 sb.setLength(0);
                 sb.append(prefix);
@@ -4928,7 +4927,7 @@
                 final int count = timer.getCountLocked(which);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTime = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
                 final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 sb.setLength(0);
                 sb.append(prefix);
@@ -4987,7 +4986,6 @@
                     final int count = timer.getCountLocked(which);
                     final Timer bgTimer = se.getSensorBackgroundTime();
                     final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : 0;
-                    final long rawRealtimeMs = (rawRealtime + 500) / 1000;
                     // 'actualTime' are unpooled and always since reset (regardless of 'which')
                     final long actualTime = timer.getTotalDurationMsLocked(rawRealtimeMs);
                     final long bgActualTime = bgTimer != null ?
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index db84b6f..97f0e0c 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.util.Log;
@@ -36,13 +37,10 @@
  * enqueued data exceeds the maximum size.  You can think of this as a
  * persistent, system-wide, blob-oriented "logcat".
  *
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService}
- * with {@link android.content.Context#DROPBOX_SERVICE}.
- *
  * <p>DropBoxManager entries are not sent anywhere directly, but other system
  * services and debugging tools may scan and upload entries for processing.
  */
+@SystemService(Context.DROPBOX_SERVICE)
 public class DropBoxManager {
     private static final String TAG = "DropBoxManager";
 
diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java
index 67edefc..aad202e 100644
--- a/core/java/android/os/HardwarePropertiesManager.java
+++ b/core/java/android/os/HardwarePropertiesManager.java
@@ -17,6 +17,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.hardware.thermal.V1_0.Constants;
 import android.util.Log;
@@ -28,6 +29,7 @@
  * The HardwarePropertiesManager class provides a mechanism of accessing hardware state of a
  * device: CPU, GPU and battery temperatures, CPU usage per core, fan speed, etc.
  */
+@SystemService(Context.HARDWARE_PROPERTIES_SERVICE)
 public class HardwarePropertiesManager {
 
     private static final String TAG = HardwarePropertiesManager.class.getSimpleName();
diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java
index 976d594..bc8e2e4 100644
--- a/core/java/android/os/IncidentManager.java
+++ b/core/java/android/os/IncidentManager.java
@@ -16,7 +16,9 @@
 
 package android.os;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
 import android.os.IIncidentManager;
@@ -31,6 +33,7 @@
  */
 @SystemApi
 @TestApi
+@SystemService(Context.INCIDENT_SERVICE)
 public class IncidentManager {
     private static final String TAG = "incident";
 
@@ -46,6 +49,10 @@
     /**
      * Take an incident report and put it in dropbox.
      */
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.DUMP,
+            android.Manifest.permission.PACKAGE_USAGE_STATS
+    })
     public void reportIncident(IncidentReportArgs args) {
         final IIncidentManager service = IIncidentManager.Stub.asInterface(
                 ServiceManager.getService("incident"));
@@ -76,6 +83,10 @@
      * {@link android.util.proto.ProtoOutputStream#bytes bytes()} method to retrieve
      * the encoded data for the header.
      */
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.DUMP,
+            android.Manifest.permission.PACKAGE_USAGE_STATS
+    })
     public void reportIncident(String settingName, byte[] headerProto) {
         // Sections
         String setting = Settings.System.getString(mContext.getContentResolver(), settingName);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 7d1369f..a85ed9c 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -17,8 +17,10 @@
 package android.os;
 
 import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.util.Log;
 import java.lang.annotation.Retention;
@@ -32,9 +34,6 @@
  * Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
  * possible, and be sure to release them as soon as possible.
  * </p><p>
- * You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- * </p><p>
  * The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
  * This will create a {@link PowerManager.WakeLock} object.  You can then use methods
  * on the wake lock object to control the power state of the device.
@@ -102,6 +101,7 @@
  * permission in an {@code <uses-permission>} element of the application's manifest.
  * </p>
  */
+@SystemService(Context.POWER_SERVICE)
 public final class PowerManager {
     private static final String TAG = "PowerManager";
 
@@ -689,6 +689,10 @@
      * @hide Requires signature or system permission.
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.DEVICE_POWER,
+            android.Manifest.permission.USER_ACTIVITY
+    })
     public void userActivity(long when, int event, int flags) {
         try {
             mService.userActivity(when, event, flags);
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index d2598c7..ba339a3 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -18,7 +18,10 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -67,6 +70,7 @@
  * recovery system (the separate partition that can be used to install
  * system updates, wipe user data, etc.)
  */
+@SystemService(Context.RECOVERY_SERVICE)
 public class RecoverySystem {
     private static final String TAG = "RecoverySystem";
 
@@ -387,6 +391,7 @@
      * {@hide}
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public static boolean verifyPackageCompatibility(File compatibilityFile) throws IOException {
         try (InputStream inputStream = new FileInputStream(compatibilityFile)) {
             return verifyPackageCompatibility(inputStream);
@@ -409,6 +414,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void processPackage(Context context,
                                       File packageFile,
                                       final ProgressListener listener,
@@ -469,6 +475,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void processPackage(Context context,
                                       File packageFile,
                                       final ProgressListener listener)
@@ -490,6 +497,7 @@
      * @throws IOException  if writing the recovery command file
      * fails, or if the reboot itself fails.
      */
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void installPackage(Context context, File packageFile)
             throws IOException {
         installPackage(context, packageFile, false);
@@ -511,6 +519,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void installPackage(Context context, File packageFile, boolean processed)
             throws IOException {
         synchronized (sRequestLock) {
@@ -602,6 +611,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void scheduleUpdateOnBoot(Context context, File packageFile)
             throws IOException {
         String filename = packageFile.getCanonicalPath();
@@ -639,6 +649,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void cancelScheduledUpdate(Context context)
             throws IOException {
         RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
@@ -777,6 +788,10 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.RECOVERY,
+            android.Manifest.permission.REBOOT
+    })
     public static void rebootWipeAb(Context context, File packageFile, String reason)
             throws IOException {
         String reasonArg = null;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 7bd3bf6..a7fc2e7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
@@ -63,6 +64,7 @@
  * <p>
  * See {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} for more on managed profiles.
  */
+@SystemService(Context.USER_SERVICE)
 public class UserManager {
 
     private static final String TAG = "UserManager";
@@ -1038,12 +1040,12 @@
 
     /**
      * Checks if the calling app is running in a managed profile.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      *
      * @return whether the caller is in a managed profile.
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isManagedProfile() {
         // No need for synchronization.  Once it becomes non-null, it'll be non-null forever.
         // Worst case we might end up calling the AIDL method multiple times but that's fine.
@@ -1067,6 +1069,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isManagedProfile(@UserIdInt int userId) {
         if (userId == UserHandle.myUserId()) {
             return isManagedProfile();
@@ -1252,7 +1255,6 @@
      * @hide
      *
      * Returns who set a user restriction on a user.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      * @param restrictionKey the string key representing the restriction
      * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
      * @return The source of user restriction. Any combination of {@link #RESTRICTION_NOT_SET},
@@ -1263,6 +1265,7 @@
     @Deprecated
     @SystemApi
     @UserRestrictionSource
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public int getUserRestrictionSource(String restrictionKey, UserHandle userHandle) {
         try {
             return mService.getUserRestrictionSource(restrictionKey, userHandle.getIdentifier());
@@ -1275,12 +1278,12 @@
      * @hide
      *
      * Returns a list of users who set a user restriction on a given user.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      * @param restrictionKey the string key representing the restriction
      * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
      * @return a list of user ids enforcing this restriction.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public List<EnforcingUser> getUserRestrictionSources(
             String restrictionKey, UserHandle userHandle) {
         try {
@@ -1622,9 +1625,10 @@
     /**
      * @hide
      *
-     * Returns the preferred account name for user creation. Requires MANAGE_USERS permission.
+     * Returns the preferred account name for user creation.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public String getSeedAccountName() {
         try {
             return mService.getSeedAccountName();
@@ -1636,9 +1640,10 @@
     /**
      * @hide
      *
-     * Returns the preferred account type for user creation. Requires MANAGE_USERS permission.
+     * Returns the preferred account type for user creation.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public String getSeedAccountType() {
         try {
             return mService.getSeedAccountType();
@@ -1650,11 +1655,11 @@
     /**
      * @hide
      *
-     * Returns the preferred account's options bundle for user creation. Requires MANAGE_USERS
-     * permission.
+     * Returns the preferred account's options bundle for user creation.
      * @return Any options set by the requestor that created the user.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public PersistableBundle getSeedAccountOptions() {
         try {
             return mService.getSeedAccountOptions();
@@ -1686,9 +1691,10 @@
 
     /**
      * @hide
-     * Clears the seed information used to create this user. Requires MANAGE_USERS permission.
+     * Clears the seed information used to create this user.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public void clearSeedAccountData() {
         try {
             mService.clearSeedAccountData();
@@ -1771,13 +1777,13 @@
 
     /**
      * Returns serial numbers of all users on this device.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      *
      * @param excludeDying specify if the list should exclude users being removed.
      * @return the list of serial numbers of users that exist on the device.
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public long[] getSerialNumbersOfUsers(boolean excludeDying) {
         try {
             List<UserInfo> users = mService.getUsers(excludeDying);
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 2f0eeca..8078fb8 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.app.ActivityThread;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -27,10 +28,8 @@
  * <p>
  * If your process exits, any vibration you started will stop.
  * </p>
- *
- * To obtain an instance of the system vibrator, call
- * {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as the argument.
  */
+@SystemService(Context.VIBRATOR_SERVICE)
 public abstract class Vibrator {
     private static final String TAG = "Vibrator";
 
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
index 7c0af25..bba4cd1 100644
--- a/core/java/android/os/health/SystemHealthManager.java
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -16,6 +16,7 @@
 
 package android.os.health;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.BatteryStats;
 import android.os.Process;
@@ -40,6 +41,7 @@
  * JobScheduler}), and while that can affect charging rates, it is still preferable
  * to actually draining the battery.
  */
+@SystemService(Context.SYSTEM_HEALTH_SERVICE)
 public class SystemHealthManager {
     private final IBatteryStats mBatteryStats;
 
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index d81ee4e..5046735 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -25,7 +25,9 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.WorkerThread;
 import android.app.ActivityThread;
 import android.content.ContentResolver;
@@ -98,11 +100,8 @@
  * guarantee the security of the OBB file itself: if any program modifies the
  * OBB, there is no guarantee that a read from that OBB will produce the
  * expected output.
- * <p>
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)} with an
- * argument of {@link android.content.Context#STORAGE_SERVICE}.
  */
+@SystemService(Context.STORAGE_SERVICE)
 public class StorageManager {
     private static final String TAG = "StorageManager";
 
@@ -1404,23 +1403,7 @@
 
     /** {@hide} */
     public static File maybeTranslateEmulatedPathToInternal(File path) {
-        final IStorageManager storageManager = IStorageManager.Stub.asInterface(
-                ServiceManager.getService("mount"));
-        try {
-            final VolumeInfo[] vols = storageManager.getVolumes(0);
-            for (VolumeInfo vol : vols) {
-                if ((vol.getType() == VolumeInfo.TYPE_EMULATED
-                        || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) {
-                    final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(),
-                            vol.getInternalPath(), path);
-                    if (internalPath != null && internalPath.exists()) {
-                        return internalPath;
-                    }
-                }
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        // Disabled now that FUSE has been replaced by sdcardfs
         return path;
     }
 
@@ -1701,8 +1684,9 @@
 
     /** @hide */
     @SystemApi
-    public long getAllocatableBytes(@NonNull UUID storageUuid, @AllocateFlags int flags)
-            throws IOException {
+    @SuppressLint("Doclava125")
+    public long getAllocatableBytes(@NonNull UUID storageUuid,
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         try {
             return mStorageManager.getAllocatableBytes(convert(storageUuid), flags);
         } catch (ParcelableException e) {
@@ -1715,8 +1699,9 @@
 
     /** @removed */
     @Deprecated
-    public long getAllocatableBytes(@NonNull File path, @AllocateFlags int flags)
-            throws IOException {
+    @SuppressLint("Doclava125")
+    public long getAllocatableBytes(@NonNull File path,
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         return getAllocatableBytes(getUuidForPath(path), flags);
     }
 
@@ -1749,8 +1734,9 @@
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void allocateBytes(@NonNull UUID storageUuid, @BytesLong long bytes,
-            @AllocateFlags int flags) throws IOException {
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         try {
             mStorageManager.allocateBytes(convert(storageUuid), bytes, flags);
         } catch (ParcelableException e) {
@@ -1762,8 +1748,9 @@
 
     /** @removed */
     @Deprecated
-    public void allocateBytes(@NonNull File path, @BytesLong long bytes, @AllocateFlags int flags)
-            throws IOException {
+    @SuppressLint("Doclava125")
+    public void allocateBytes(@NonNull File path, @BytesLong long bytes,
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         allocateBytes(getUuidForPath(path), bytes, flags);
     }
 
@@ -1798,8 +1785,9 @@
 
     /** @hide */
     @SystemApi
-    public void allocateBytes(FileDescriptor fd, @BytesLong long bytes, @AllocateFlags int flags)
-            throws IOException {
+    @SuppressLint("Doclava125")
+    public void allocateBytes(FileDescriptor fd, @BytesLong long bytes,
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         final File file = ParcelFileDescriptor.getFile(fd);
         for (int i = 0; i < 3; i++) {
             try {
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 8ee0517..e8ff2e2 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.app.Activity;
 import android.app.Application.ActivityLifecycleCallbacks;
 import android.content.ComponentName;
@@ -57,14 +58,6 @@
 
 /**
  * System level service for accessing the printing capabilities of the platform.
- * <p>
- * To obtain a handle to the print manager do the following:
- * </p>
- *
- * <pre>
- * PrintManager printManager =
- *         (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
- * </pre>
  *
  * <h3>Print mechanics</h3>
  * <p>
@@ -109,6 +102,7 @@
  * @see PrintJob
  * @see PrintJobInfo
  */
+@SystemService(Context.PRINT_SERVICE)
 public final class PrintManager {
 
     private static final String LOG_TAG = "PrintManager";
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
index 251d346..6956c8a 100644
--- a/core/java/android/service/autofill/FillContext.java
+++ b/core/java/android/service/autofill/FillContext.java
@@ -114,7 +114,7 @@
      *
      * @hide
      */
-    @NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId[] ids) {
+    @NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId... ids) {
         final LinkedList<ViewNode> nodesToProcess = new LinkedList<>();
         final ViewNode[] foundNodes = new AssistStructure.ViewNode[ids.length];
 
diff --git a/core/java/android/service/oemlock/OemLockManager.java b/core/java/android/service/oemlock/OemLockManager.java
index c4fbe5e..e2ade87 100644
--- a/core/java/android/service/oemlock/OemLockManager.java
+++ b/core/java/android/service/oemlock/OemLockManager.java
@@ -17,7 +17,10 @@
 package android.service.oemlock;
 
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.RemoteException;
 
 /**
@@ -31,6 +34,7 @@
  * @hide
  */
 @SystemApi
+@SystemService(Context.OEM_LOCK_SERVICE)
 public class OemLockManager {
     private IOemLockService mService;
 
@@ -55,6 +59,7 @@
      *
      * @see #isOemUnlockAllowedByCarrier()
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE)
     public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
         try {
             mService.setOemUnlockAllowedByCarrier(allowed, signature);
@@ -69,6 +74,7 @@
      *
      * @see #setOemUnlockAllowedByCarrier(boolean, byte[])
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE)
     public boolean isOemUnlockAllowedByCarrier() {
         try {
             return mService.isOemUnlockAllowedByCarrier();
@@ -86,6 +92,7 @@
      *
      * @see #isOemUnlockAllowedByUser()
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE)
     public void setOemUnlockAllowedByUser(boolean allowed) {
         try {
             mService.setOemUnlockAllowedByUser(allowed);
@@ -100,6 +107,7 @@
      *
      * @see #setOemUnlockAllowedByUser(boolean)
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE)
     public boolean isOemUnlockAllowedByUser() {
         try {
             return mService.isOemUnlockAllowedByUser();
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index 326796a..fa75ad3 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -16,10 +16,14 @@
 
 package android.service.persistentdata;
 
-import android.annotation.SystemApi;
 import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.RemoteException;
-import android.util.Slog;
+import android.service.oemlock.OemLockManager;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -43,6 +47,7 @@
  * @hide
  */
 @SystemApi
+@SystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE)
 public class PersistentDataBlockManager {
     private static final String TAG = PersistentDataBlockManager.class.getSimpleName();
     private IPersistentDataBlockService sService;
@@ -85,6 +90,7 @@
      *
      * @param data the data to write
      */
+    @SuppressLint("Doclava125")
     public int write(byte[] data) {
         try {
             return sService.write(data);
@@ -96,6 +102,7 @@
     /**
      * Returns the data block stored on the persistent partition.
      */
+    @SuppressLint("Doclava125")
     public byte[] read() {
         try {
             return sService.read();
@@ -109,6 +116,7 @@
      *
      * Return -1 on error.
      */
+    @RequiresPermission(android.Manifest.permission.ACCESS_PDB_STATE)
     public int getDataBlockSize() {
         try {
             return sService.getDataBlockSize();
@@ -136,6 +144,7 @@
      * It will also prevent any further {@link #write} operation until reboot,
      * in order to prevent a potential race condition. See b/30352311.
      */
+    @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
     public void wipe() {
         try {
             sService.wipe();
@@ -149,6 +158,7 @@
      *
      * @deprecated use {@link OemLockManager#setOemUnlockAllowedByUser(boolean)} instead.
      */
+    @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
     public void setOemUnlockEnabled(boolean enabled) {
         try {
             sService.setOemUnlockEnabled(enabled);
@@ -162,6 +172,10 @@
      *
      * @deprecated use {@link OemLockManager#isOemUnlockAllowedByUser()} instead.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_OEM_UNLOCK_STATE,
+            android.Manifest.permission.OEM_UNLOCK_STATE
+    })
     public boolean getOemUnlockEnabled() {
         try {
             return sService.getOemUnlockEnabled();
@@ -177,6 +191,10 @@
      * {@link #FLASH_LOCK_UNLOCKED} if device bootloader is unlocked, or {@link #FLASH_LOCK_UNKNOWN}
      * if this information cannot be ascertained on this device.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_OEM_UNLOCK_STATE,
+            android.Manifest.permission.OEM_UNLOCK_STATE
+    })
     @FlashLockState
     public int getFlashLockState() {
         try {
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index ad46d07..47b8d92 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -18,6 +18,7 @@
 
 import android.annotation.LayoutRes;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -47,10 +48,7 @@
  * {@link android.app.Activity#getLayoutInflater()} or
  * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
  * that is already hooked up to the current context and correctly configured
- * for the device you are running on.  For example:
- *
- * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
- *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
+ * for the device you are running on.
  *
  * <p>
  * To create a new LayoutInflater with an additional {@link Factory} for your
@@ -64,9 +62,8 @@
  * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
  * it only works with an XmlPullParser returned from a compiled resource
  * (R.<em>something</em> file.)
- *
- * @see Context#getSystemService
  */
+@SystemService(Context.LAYOUT_INFLATER_SERVICE)
 public abstract class LayoutInflater {
 
     private static final String TAG = LayoutInflater.class.getSimpleName();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index b57ac66..ef78559 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -31,6 +31,7 @@
 import android.graphics.Region;
 import android.os.Build;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -452,6 +453,14 @@
         }
     }
 
+    private void updateOpaqueFlag() {
+        if (!PixelFormat.formatHasAlpha(mRequestedFormat)) {
+            mSurfaceFlags |= SurfaceControl.OPAQUE;
+        } else {
+            mSurfaceFlags &= ~SurfaceControl.OPAQUE;
+        }
+    }
+
     private Rect getParentSurfaceInsets() {
         final ViewRootImpl root = getViewRootImpl();
         if (root == null) {
@@ -522,7 +531,9 @@
                 if (creating) {
                     mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
                     mDeferredDestroySurfaceControl = mSurfaceControl;
-                    mSurfaceControl = new SurfaceControl(mSurfaceSession,
+
+                    updateOpaqueFlag();
+                    mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession,
                             "SurfaceView - " + viewRoot.getTitle().toString(),
                             mSurfaceWidth, mSurfaceHeight, mFormat,
                             mSurfaceFlags);
@@ -1071,4 +1082,126 @@
             return mSurfaceFrame;
         }
     };
+
+    class SurfaceControlWithBackground extends SurfaceControl {
+        private SurfaceControl mBackgroundControl;
+        private boolean mOpaque = true;
+        public boolean mVisible = false;
+
+        public SurfaceControlWithBackground(SurfaceSession s,
+                        String name, int w, int h, int format, int flags)
+                       throws Exception {
+            super(s, name, w, h, format, flags);
+            mBackgroundControl = new SurfaceControl(s, "Background for - " + name, w, h,
+                    PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
+            mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
+        }
+
+        @Override
+        public void setAlpha(float alpha) {
+            super.setAlpha(alpha);
+            mBackgroundControl.setAlpha(alpha);
+        }
+
+        @Override
+        public void setLayer(int zorder) {
+            super.setLayer(zorder);
+            // -3 is below all other child layers as SurfaceView never goes below -2
+            mBackgroundControl.setLayer(-3);
+        }
+
+        @Override
+        public void setPosition(float x, float y) {
+            super.setPosition(x, y);
+            mBackgroundControl.setPosition(x, y);
+        }
+
+        @Override
+        public void setSize(int w, int h) {
+            super.setSize(w, h);
+            mBackgroundControl.setSize(w, h);
+        }
+
+        @Override
+        public void setWindowCrop(Rect crop) {
+            super.setWindowCrop(crop);
+            mBackgroundControl.setWindowCrop(crop);
+        }
+
+        @Override
+        public void setFinalCrop(Rect crop) {
+            super.setFinalCrop(crop);
+            mBackgroundControl.setFinalCrop(crop);
+        }
+
+        @Override
+        public void setLayerStack(int layerStack) {
+            super.setLayerStack(layerStack);
+            mBackgroundControl.setLayerStack(layerStack);
+        }
+
+        @Override
+        public void setOpaque(boolean isOpaque) {
+            super.setOpaque(isOpaque);
+            mOpaque = isOpaque;
+            updateBackgroundVisibility();
+        }
+
+        @Override
+        public void setSecure(boolean isSecure) {
+            super.setSecure(isSecure);
+        }
+
+        @Override
+        public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+            super.setMatrix(dsdx, dtdx, dsdy, dtdy);
+            mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
+        }
+
+        @Override
+        public void hide() {
+            super.hide();
+            mVisible = false;
+            updateBackgroundVisibility();
+        }
+
+        @Override
+        public void show() {
+            super.show();
+            mVisible = true;
+            updateBackgroundVisibility();
+        }
+
+        @Override
+        public void destroy() {
+            super.destroy();
+            mBackgroundControl.destroy();
+         }
+
+        @Override
+        public void release() {
+            super.release();
+            mBackgroundControl.release();
+        }
+
+        @Override
+        public void setTransparentRegionHint(Region region) {
+            super.setTransparentRegionHint(region);
+            mBackgroundControl.setTransparentRegionHint(region);
+        }
+
+        @Override
+        public void deferTransactionUntil(IBinder handle, long frame) {
+            super.deferTransactionUntil(handle, frame);
+            mBackgroundControl.deferTransactionUntil(handle, frame);
+        }
+
+        void updateBackgroundVisibility() {
+            if (mOpaque && mVisible) {
+                mBackgroundControl.show();
+            } else {
+                mBackgroundControl.hide();
+            }
+        }
+    }
 }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 8637593..4b79b8c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4936,9 +4936,6 @@
                 needGlobalAttributesUpdate(true);
             }
             ai.mKeepScreenOn = lastKeepOn;
-            if (!childHasFocus && child.hasFocusable()) {
-                focusableViewAvailable(child);
-            }
         }
 
         if (child.isLayoutDirectionInherited()) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3dd8d2a..4060b9a 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.app.KeyguardManager;
 import android.app.Presentation;
@@ -39,8 +40,6 @@
 
 /**
  * The interface that apps use to talk to the window manager.
- * <p>
- * Use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code> to get one of these.
  * </p><p>
  * Each window manager instance is bound to a particular {@link Display}.
  * To obtain a {@link WindowManager} for a different display, use
@@ -52,10 +51,8 @@
  * {@link Presentation}.  The presentation will automatically obtain a
  * {@link WindowManager} and {@link Context} for that display.
  * </p>
- *
- * @see android.content.Context#getSystemService
- * @see android.content.Context#WINDOW_SERVICE
  */
+@SystemService(Context.WINDOW_SERVICE)
 public interface WindowManager extends ViewManager {
 
     /** @hide */
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 7eb7bd9..41a8b8a 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -24,6 +24,7 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -59,15 +60,6 @@
  * {@link android.view.View} changes etc. Parties interested in handling accessibility
  * events implement and register an accessibility service which extends
  * {@link android.accessibilityservice.AccessibilityService}.
- * <p>
- * To obtain a handle to the accessibility manager do the following:
- * </p>
- * <p>
- * <code>
- * <pre>AccessibilityManager accessibilityManager =
- *        (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);</pre>
- * </code>
- * </p>
  *
  * @see AccessibilityEvent
  * @see AccessibilityNodeInfo
@@ -75,6 +67,7 @@
  * @see Context#getSystemService
  * @see Context#ACCESSIBILITY_SERVICE
  */
+@SystemService(Context.ACCESSIBILITY_SERVICE)
 public final class AccessibilityManager {
     private static final boolean DEBUG = false;
 
diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java
index 14f0b0a..d6455e7 100644
--- a/core/java/android/view/accessibility/CaptioningManager.java
+++ b/core/java/android/view/accessibility/CaptioningManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -34,14 +35,8 @@
 /**
  * Contains methods for accessing and monitoring preferred video captioning state and visual
  * properties.
- * <p>
- * To obtain a handle to the captioning manager, do the following:
- * <p>
- * <code>
- * <pre>CaptioningManager captioningManager =
- *        (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);</pre>
- * </code>
  */
+@SystemService(Context.CAPTIONING_SERVICE)
 public class CaptioningManager {
     /** Default captioning enabled value. */
     private static final int DEFAULT_ENABLED = 0;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 02ecc50..310ec1c 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -23,6 +23,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -55,6 +56,7 @@
  *
  * <p>It is safe to call into this from any thread.
  */
+@SystemService(Context.AUTOFILL_MANAGER_SERVICE)
 public final class AutofillManager {
 
     private static final String TAG = "AutofillManager";
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index da9316c..e2f7979 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -73,8 +74,6 @@
 /**
  * Central system API to the overall input method framework (IMF) architecture,
  * which arbitrates interaction between applications and the current input method.
- * You can retrieve an instance of this interface with
- * {@link Context#getSystemService(String) Context.getSystemService()}.
  *
  * <p>Topics covered here:
  * <ol>
@@ -211,6 +210,7 @@
  * and want to make it available for use.</p>
  * </ul>
  */
+@SystemService(Context.INPUT_METHOD_SERVICE)
 public final class InputMethodManager {
     static final boolean DEBUG = false;
     static final String TAG = "InputMethodManager";
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index 6b641db..efc88e2 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
@@ -33,10 +34,8 @@
 
 /**
  * Interface to the text classification service.
- *
- * <p>You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
  */
+@SystemService(Context.TEXT_CLASSIFICATION_SERVICE)
 public final class TextClassificationManager {
 
     private static final String LOG_TAG = "TextClassificationManager";
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index b4e6c56..d9bfade 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -16,6 +16,7 @@
 
 package android.view.textservice;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -30,8 +31,7 @@
 
 /**
  * System API to the overall text services, which arbitrates interaction between applications
- * and text services. You can retrieve an instance of this interface with
- * {@link Context#getSystemService(String) Context.getSystemService()}.
+ * and text services.
  *
  * The user can change the current text services in Settings. And also applications can specify
  * the target text services.
@@ -61,6 +61,7 @@
  * </ul>
  *
  */
+@SystemService(Context.TEXT_SERVICES_MANAGER_SERVICE)
 public final class TextServicesManager {
     private static final String TAG = TextServicesManager.class.getSimpleName();
     private static final boolean DBG = false;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 1fef7cb..c19ee56 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3842,11 +3842,12 @@
             }
 
             if (mTextView.canRequestAutofill()) {
-                final int mode = mTextView.getText().length() <= 0
-                        ? MenuItem.SHOW_AS_ACTION_IF_ROOM : MenuItem.SHOW_AS_ACTION_NEVER;
-                menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
-                        com.android.internal.R.string.autofill)
-                        .setShowAsAction(mode);
+                final String selected = mTextView.getSelectedText();
+                if (selected == null || selected.isEmpty()) {
+                    menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
+                            com.android.internal.R.string.autofill)
+                            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+                }
             }
 
             if (mTextView.canPasteAsPlainText()) {
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 797cf2b..d327180 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -135,7 +135,7 @@
         channelsList.add(new NotificationChannel(
                 FOREGROUND_SERVICE,
                 context.getString(R.string.notification_channel_foreground_service),
-                NotificationManager.IMPORTANCE_MIN));
+                NotificationManager.IMPORTANCE_LOW));
 
         nm.createNotificationChannels(channelsList);
     }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 1b0d332..235ebc8 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3518,6 +3518,7 @@
     public void removeIsolatedUidLocked(int isolatedUid) {
         mIsolatedUids.delete(isolatedUid);
         mKernelUidCpuTimeReader.removeUid(isolatedUid);
+        mKernelUidCpuFreqTimeReader.removeUid(isolatedUid);
     }
 
     public int mapUid(int uid) {
@@ -10175,7 +10176,16 @@
                 new KernelUidCpuTimeReader.Callback() {
                     @Override
                     public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
-                        final Uid u = getUidStatsLocked(mapUid(uid));
+                        uid = mapUid(uid);
+                        if (Process.isIsolated(uid)) {
+                            // This could happen if the isolated uid mapping was removed before
+                            // that process was actually killed.
+                            mKernelUidCpuTimeReader.removeUid(uid);
+                            Slog.d(TAG, "Got readings for an isolated uid with"
+                                    + " no mapping to owning uid: " + uid);
+                            return;
+                        }
+                        final Uid u = getUidStatsLocked(uid);
 
                         // Accumulate the total system and user time.
                         mTempTotalCpuUserTimeUs += userTimeUs;
@@ -10340,7 +10350,14 @@
 
                     @Override
                     public void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs) {
-                        final Uid u = getUidStatsLocked(mapUid(uid));
+                        uid = mapUid(uid);
+                        if (Process.isIsolated(uid)) {
+                            mKernelUidCpuFreqTimeReader.removeUid(uid);
+                            Slog.d(TAG, "Got freq readings for an isolated uid with"
+                                    + " no mapping to owning uid: " + uid);
+                            return;
+                        }
+                        final Uid u = getUidStatsLocked(uid);
                         if (u.mCpuFreqTimeMs == null) {
                             u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
                         }
@@ -11006,6 +11023,7 @@
      */
     public void removeUidStatsLocked(int uid) {
         mKernelUidCpuTimeReader.removeUid(uid);
+        mKernelUidCpuFreqTimeReader.removeUid(uid);
         mUidStats.remove(uid);
     }
 
diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
index 9fbc4a8..ff521c2 100644
--- a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
@@ -72,6 +72,10 @@
         }
     }
 
+    public void removeUid(int uid) {
+        mLastUidCpuFreqTimeMs.delete(uid);
+    }
+
     @VisibleForTesting
     public void readDelta(BufferedReader reader, @Nullable Callback callback) throws IOException {
         String line = reader.readLine();
diff --git a/core/res/res/drawable/stat_sys_vitals.xml b/core/res/res/drawable/stat_sys_vitals.xml
new file mode 100644
index 0000000..213dd5f
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_vitals.xml
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2017 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<!-- "system vitals", as represented by an EKG trace -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M19.5608645,12.0797103 L17.15,5.15 L15.25,5.15 L11.95,15.95 L9.75,11.5 L7.95,11.55 L7.2,13.3
+        L6.65,14.6 L3.25,14.6 L3.25,16.6 L7.35,16.6 L8,16.6 L8.25,16 L8.9,14.3 L11.2,18.85 L13.15,18.85 L16.25,8.8
+        L17.5310733,12.642689 C17.2014325,12.9992627 17,13.4761078 17,14 C17,15.1045695 17.8954305,16 19,16
+        C20.1045695,16 21,15.1045695 21,14 C21,13.0901368 20.3924276,12.3221796 19.5608645,12.0797103 Z M21,3
+        C22,3 23,4 23,5 L23,19 C23,20 22,21 21,21 L3,21 C1.9,21 1,20.1 1,19 L1,5 C1,4 2,3 3,3 L21,3 Z" />
+</vector>
diff --git a/core/res/res/drawable/sym_def_app_icon.xml b/core/res/res/drawable/sym_def_app_icon.xml
index 9c02402..129d38a 100644
--- a/core/res/res/drawable/sym_def_app_icon.xml
+++ b/core/res/res/drawable/sym_def_app_icon.xml
@@ -1,9 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
-    <background android:drawable="@android:color/white" />
+    <background android:drawable="@drawable/sym_def_app_icon_background" />
     <foreground>
-        <inset android:inset="27.7%">
-            <bitmap android:src="@mipmap/sym_def_app_icon"/>
-        </inset>
+        <bitmap android:src="@mipmap/sym_def_app_icon_foreground"/>
     </foreground>
 </adaptive-icon>
diff --git a/core/res/res/drawable/sym_def_app_icon_background.xml b/core/res/res/drawable/sym_def_app_icon_background.xml
new file mode 100644
index 0000000..5755210
--- /dev/null
+++ b/core/res/res/drawable/sym_def_app_icon_background.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+    android:height="108dp"
+    android:width="108dp"
+    android:viewportHeight="108.0"
+    android:viewportWidth="108.0"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/material_deep_teal_500"
+        android:pathData="M0,0h108v108h-108z"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
+        android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
+        android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
+        android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
+        android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+</vector>
+
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..4e526c9
--- /dev/null
+++ b/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index bf58413..0000000
--- a/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..2c38c71
--- /dev/null
+++ b/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index 47f6f81..0000000
--- a/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..072467e
--- /dev/null
+++ b/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index f60b896..0000000
--- a/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..78a6b7a
--- /dev/null
+++ b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index 6d4f315..0000000
--- a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png
new file mode 100644
index 0000000..68ebe33
--- /dev/null
+++ b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png
Binary files differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644
index 08e54d0..0000000
--- a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 3049488..a328c49 100755
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -23,6 +23,7 @@
     <string-array translatable="false" name="config_cdma_home_system">
         <item>64</item>
         <item>65</item>
+        <item>66</item>
         <item>76</item>
         <item>77</item>
         <item>78</item>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 6f85081..04f182e 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -23,6 +23,7 @@
     <string-array translatable="false" name="config_cdma_home_system">
         <item>64</item>
         <item>65</item>
+        <item>66</item>
         <item>76</item>
         <item>77</item>
         <item>78</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8e6c402..241e565 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1099,6 +1099,11 @@
          that can be set by the user. -->
     <integer name="config_screenBrightnessDoze">1</integer>
 
+    <!-- Whether or not to skip the initial brightness ramps when the display transitions to
+         STATE_ON. Setting this to true will skip the brightness ramp to the last stored active
+         brightness value and will repeat for the following ramp if autobrightness is enabled. -->
+    <bool name="config_skipScreenOnBrightnessRamp">false</bool>
+
     <!-- Allow automatic adjusting of the screen brightness while dozing in low power state. -->
     <bool name="config_allowAutoBrightnessWhileDozing">false</bool>
 
@@ -2531,6 +2536,10 @@
     <!-- The default vibration strength, must be between 1 and 255 inclusive. -->
     <integer name="config_defaultVibrationAmplitude">255</integer>
 
+    <!-- If the device should still vibrate even in low power mode, for certain priority vibrations
+     (e.g. accessibility, alarms). This is mainly for Wear devices that don't have speakers. -->
+    <bool name="config_allowPriorityVibrationsInLowPowerMode">false</bool>
+
     <!-- Number of retries Cell Data should attempt for a given error code before
          restarting the modem.
          Error codes not listed will not lead to modem restarts.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 90ece60..3eebe7e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -191,21 +191,15 @@
 
     <!-- Notification title to tell the user that data service is blocked by access control. -->
     <string name="RestrictedOnDataTitle">No data service</string>
-    <!-- Notification title to tell the user that emergency service is blocked by access control. -->
-    <string name="RestrictedOnEmergencyTitle">No emergency service</string>
+    <!-- Notification title to tell the user that emergency calling is blocked by access control. -->
+    <string name="RestrictedOnEmergencyTitle">No emergency calling</string>
     <!-- Notification title to tell the user that normal service is blocked by access control. -->
     <string name="RestrictedOnNormalTitle">No voice service</string>
     <!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. -->
     <string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string>
 
-    <!-- Notification content to tell the user that data service is blocked by access control. -->
-    <string name="RestrictedOnDataContent">Your carrier has temporarily suspended data service at this location</string>
-    <!-- Notification content to tell the user that emergency service is blocked by access control. -->
-    <string name="RestrictedOnEmergencyContent">Your carrier has temporarily suspended emergency calls at this location</string>
-    <!-- Notification content to tell the user that normal service is blocked by access control. -->
-    <string name="RestrictedOnNormalContent">Your carrier has temporarily suspended voice calls at this location</string>
-    <!-- Notification content to tell the user that all emergency and normal voice services are blocked by access control. -->
-    <string name="RestrictedOnAllVoiceContent">Your carrier has temporarily suspended voice and emergency calls at this location</string>
+    <!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. -->
+    <string name="RestrictedStateContent">Temporarily not offered by the mobile network at your location</string>
 
     <!-- Displayed to tell the user that they should switch their network preference. -->
     <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bfd40bd..7dd4022 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -521,10 +521,7 @@
   <java-symbol type="string" name="RestrictedOnDataTitle" />
   <java-symbol type="string" name="RestrictedOnEmergencyTitle" />
   <java-symbol type="string" name="RestrictedOnNormalTitle" />
-  <java-symbol type="string" name="RestrictedOnAllVoiceContent" />
-  <java-symbol type="string" name="RestrictedOnDataContent" />
-  <java-symbol type="string" name="RestrictedOnEmergencyContent" />
-  <java-symbol type="string" name="RestrictedOnNormalContent" />
+  <java-symbol type="string" name="RestrictedStateContent" />
   <java-symbol type="string" name="notification_channel_network_alert" />
   <java-symbol type="string" name="notification_channel_call_forward" />
   <java-symbol type="string" name="notification_channel_emergency_callback" />
@@ -1755,6 +1752,7 @@
   <java-symbol type="bool" name="config_sf_limitedAlpha" />
   <java-symbol type="bool" name="config_unplugTurnsOnScreen" />
   <java-symbol type="bool" name="config_usbChargingMessage" />
+  <java-symbol type="bool" name="config_skipScreenOnBrightnessRamp" />
   <java-symbol type="bool" name="config_allowAutoBrightnessWhileDozing" />
   <java-symbol type="bool" name="config_allowTheaterModeWakeFromUnplug" />
   <java-symbol type="bool" name="config_allowTheaterModeWakeFromGesture" />
@@ -1808,6 +1806,7 @@
   <java-symbol type="dimen" name="default_minimal_size_pip_resizable_task" />
   <java-symbol type="dimen" name="task_height_of_minimized_mode" />
   <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
+  <java-symbol type="bool" name="config_allowPriorityVibrationsInLowPowerMode" />
   <java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
   <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
   <java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
@@ -3024,4 +3023,5 @@
   <java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
 
   <java-symbol type="integer" name="config_inCallNotificationVolumeRelative" />
+  <java-symbol type="drawable" name="stat_sys_vitals" />
 </resources>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index e3b4740..f931d21 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1036,6 +1036,8 @@
         // old shader's pointer may be reused by another shader allocation later
         if (mShader != shader) {
             mNativeShader = -1;
+            // Release any native references to the old shader content
+            nSetShader(mNativePaint, 0);
         }
         // Defer setting the shader natively until getNativeInstance() is called
         mShader = shader;
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 00b5eda..90d6ab8 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -834,6 +834,16 @@
             final Animator localAnimator = animator.clone();
             final String targetName = mTargetNameMap.get(animator);
             final Object target = mVectorDrawable.getTargetByName(targetName);
+            if (!mShouldIgnoreInvalidAnim) {
+                if (target == null) {
+                    throw new IllegalStateException("Target with the name \"" + targetName
+                            + "\" cannot be found in the VectorDrawable to be animated.");
+                } else if (!(target instanceof VectorDrawable.VectorDrawableState)
+                        && !(target instanceof VectorDrawable.VObject)) {
+                    throw new UnsupportedOperationException("Target should be either VGroup, VPath,"
+                            + " or ConstantState, " + target.getClass() + " is not supported");
+                }
+            }
             localAnimator.setTarget(target);
             return localAnimator;
         }
@@ -1321,16 +1331,10 @@
                         throw new IllegalArgumentException("ClipPath only supports PathData " +
                                 "property");
                     }
-
                 }
             } else if (target instanceof VectorDrawable.VectorDrawableState) {
                 createRTAnimatorForRootGroup(values, animator,
                         (VectorDrawable.VectorDrawableState) target, startTime);
-            } else if (!mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
-                // Should never get here
-                throw new UnsupportedOperationException("Target should be either VGroup, VPath, " +
-                        "or ConstantState, " + target == null ? "Null target" : target.getClass() +
-                        " is not supported");
             }
         }
 
diff --git a/location/java/android/location/CountryDetector.java b/location/java/android/location/CountryDetector.java
index ce3c56f..ec6dfb7 100644
--- a/location/java/android/location/CountryDetector.java
+++ b/location/java/android/location/CountryDetector.java
@@ -18,6 +18,8 @@
 
 import java.util.HashMap;
 
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -40,13 +42,10 @@
  * To be notified of the future country change, use the
  * {@link #addCountryListener}
  * <p>
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.COUNTRY_DETECTOR)}.
  *
  * @hide
  */
+@SystemService(Context.COUNTRY_DETECTOR)
 public class CountryDetector {
 
     /**
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index f9385c6..26ac2a2 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -20,7 +20,9 @@
 
 import android.Manifest;
 import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -47,11 +49,6 @@
  * {@link Intent} when the device enters the proximity of a given
  * geographical location.
  *
- * <p>You do not
- * instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.LOCATION_SERVICE)}.
- *
  * <p class="note">Unless noted, all Location API methods require
  * the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or
  * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permissions.
@@ -60,8 +57,8 @@
  * return location results, but the update rate will be throttled and the exact
  * location will be obfuscated to a coarse level of accuracy.
  */
-public class LocationManager
-{
+@SystemService(Context.LOCATION_SERVICE)
+public class LocationManager {
     private static final String TAG = "LocationManager";
 
     private final Context mContext;
@@ -831,6 +828,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(LocationRequest request, LocationListener listener,
             Looper looper) {
         checkListener(listener);
@@ -859,6 +857,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(LocationRequest request, PendingIntent intent) {
         checkPendingIntent(intent);
         requestLocationUpdates(request, null, null, intent);
@@ -1820,6 +1819,7 @@
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
         return false;
     }
@@ -1857,6 +1857,7 @@
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
     }
 
@@ -1877,6 +1878,7 @@
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
         return false;
     }
@@ -1891,6 +1893,7 @@
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
     }
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 0b5dff2..20deeb16 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -19,9 +19,11 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
@@ -58,10 +60,8 @@
 
 /**
  * AudioManager provides access to volume and ringer mode control.
- * <p>
- * Use <code>Context.getSystemService(Context.AUDIO_SERVICE)</code> to get
- * an instance of this class.
  */
+@SystemService(Context.AUDIO_SERVICE)
 public class AudioManager {
 
     private Context mOriginalContext;
@@ -2827,6 +2827,7 @@
      *    {@link #SUCCESS} otherwise.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public int registerAudioPolicy(@NonNull AudioPolicy policy) {
         if (policy == null) {
             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
@@ -2852,6 +2853,7 @@
      * @param policy the non-null {@link AudioPolicy} to unregister.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
         if (policy == null) {
             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index 228a6de..dd731df 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -136,7 +136,13 @@
 
     private void teardownConnection() {
         if (mConnection != null) {
-            mInputStream = null;
+            if (mInputStream != null) {
+                try {
+                    mInputStream.close();
+                } catch (IOException e) {
+                }
+                mInputStream = null;
+            }
 
             mConnection.disconnect();
             mConnection = null;
@@ -298,8 +304,7 @@
             mCurrentOffset = offset;
         } catch (IOException e) {
             mTotalSize = -1;
-            mInputStream = null;
-            mConnection = null;
+            teardownConnection();
             mCurrentOffset = -1;
 
             throw e;
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 44494a6..91dada7 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -20,6 +20,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemService;
 import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -61,6 +62,7 @@
  * <p>The media router API is not thread-safe; all interactions with it must be
  * done from the main thread of the process.</p>
  */
+@SystemService(Context.MEDIA_ROUTER_SERVICE)
 public class MediaRouter {
     private static final String TAG = "MediaRouter";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 07c8ae8..a015732 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -16,7 +16,9 @@
 
 package android.media.midi;
 
+import android.annotation.SystemService;
 import android.bluetooth.BluetoothDevice;
+import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Bundle;
@@ -28,13 +30,8 @@
 
 /**
  * This class is the public application interface to the MIDI service.
- *
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- *
- * {@samplecode
- * MidiManager manager = (MidiManager) getSystemService(Context.MIDI_SERVICE);}
  */
+@SystemService(Context.MIDI_SERVICE)
 public final class MidiManager {
     private static final String TAG = "MidiManager";
 
diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java
index f4a548b..9f2c08e 100644
--- a/media/java/android/media/projection/MediaProjectionManager.java
+++ b/media/java/android/media/projection/MediaProjectionManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -33,14 +34,8 @@
 
 /**
  * Manages the retrieval of certain types of {@link MediaProjection} tokens.
- *
- * <p>
- * Get an instance of this class by calling {@link
- * android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument {@link
- * android.content.Context#MEDIA_PROJECTION_SERVICE}.
- * </p>
  */
+@SystemService(Context.MEDIA_PROJECTION_SERVICE)
 public final class MediaProjectionManager {
     private static final String TAG = "MediaProjectionManager";
     /** @hide */
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 83793ae..e02a4dc 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -18,7 +18,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.media.AudioManager;
@@ -42,13 +44,11 @@
  * Provides support for interacting with {@link MediaSession media sessions}
  * that applications have published to express their ongoing media playback
  * state.
- * <p>
- * Use <code>Context.getSystemService(Context.MEDIA_SESSION_SERVICE)</code> to
- * get an instance of this class.
  *
  * @see MediaSession
  * @see MediaController
  */
+@SystemService(Context.MEDIA_SESSION_SERVICE)
 public final class MediaSessionManager {
     private static final String TAG = "SessionManager";
 
@@ -357,6 +357,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER)
     public void setOnVolumeKeyLongPressListener(
             OnVolumeKeyLongPressListener listener, @Nullable Handler handler) {
         synchronized (mLock) {
@@ -392,6 +393,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER)
     public void setOnMediaKeyListener(OnMediaKeyListener listener, @Nullable Handler handler) {
         synchronized (mLock) {
             try {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index d5296ae..a48abff 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -20,6 +20,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.SoundTrigger;
@@ -235,6 +236,7 @@
      * {@link Callback}.
      * @return Indicates whether the call succeeded or not.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
         if (DBG) {
             Slog.d(TAG, "startRecognition()");
@@ -258,6 +260,7 @@
     /**
      * Stops recognition for the associated model.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public boolean stopRecognition() {
         int status = STATUS_OK;
         try {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index fdd7fc2..7f8140a 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -18,7 +18,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.os.Handler;
@@ -39,6 +41,7 @@
  * @hide
  */
 @SystemApi
+@SystemService(Context.SOUND_TRIGGER_SERVICE)
 public final class SoundTriggerManager {
     private static final boolean DBG = false;
     private static final String TAG = "SoundTriggerManager";
@@ -65,6 +68,7 @@
     /**
      * Updates the given sound trigger model.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public void updateModel(Model model) {
         try {
             mSoundTriggerService.updateSoundModel(model.getGenericSoundModel());
@@ -77,6 +81,7 @@
      * Returns the sound trigger model represented by the given UUID. An instance of {@link Model}
      * is returned.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public Model getModel(UUID soundModelId) {
         try {
             return new Model(mSoundTriggerService.getSoundModel(
@@ -89,6 +94,7 @@
     /**
      * Deletes the sound model represented by the provided UUID.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public void deleteModel(UUID soundModelId) {
         try {
             mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId));
@@ -110,6 +116,7 @@
      * @return Instance of {@link SoundTriggerDetector} or null on error.
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId,
             @NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) {
         if (soundModelId == null) {
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 68ee02c..28fd338 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -21,6 +21,8 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.Rect;
 import android.media.PlaybackParams;
@@ -57,9 +59,7 @@
 
 /**
  * Central system API to the overall TV input framework (TIF) architecture, which arbitrates
- * interaction between applications and the selected TV inputs. You can retrieve an instance of
- * this interface with {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.TV_INPUT_SERVICE)}.
+ * interaction between applications and the selected TV inputs.
  *
  * <p>There are three primary parties involved in the TV input framework (TIF) architecture:
  *
@@ -78,6 +78,7 @@
  * programs.
  * </ul>
  */
+@SystemService(Context.TV_INPUT_SERVICE)
 public final class TvInputManager {
     private static final String TAG = "TvInputManager";
 
@@ -1516,6 +1517,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT)
     public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId) {
         try {
             return mService.getAvailableTvStreamConfigList(inputId, mUserId);
@@ -1534,6 +1536,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT)
     public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config) {
         try {
             return mService.captureFrame(inputId, surface, config, mUserId);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
index 6678f8b..5680d9f 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
@@ -1139,9 +1139,18 @@
         }
         List<Integer> modeList = new ArrayList<Integer>();
         for (int mode : modes) {
-            modeList.add(mode);
+            // Skip vendor-added modes
+            if (mode <= CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) {
+                modeList.add(mode);
+            }
         }
         checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty());
+        modes = new int[modeList.size()];
+        for (int i = 0; i < modeList.size(); i++) {
+            modes[i] = modeList.get(i);
+        }
+
+        checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty());
 
         // All camera device must support ON
         checkTrueForKey(modesKey, "values " + modeList.toString() + " must contain ON mode",
@@ -1227,7 +1236,17 @@
             return new int[0];
         }
 
-        List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(afModes));
+        List<Integer> modesList = new ArrayList<Integer>();
+        for (int afMode : afModes) {
+            // Skip vendor-added AF modes
+            if (afMode > CameraCharacteristics.CONTROL_AF_MODE_EDOF) continue;
+            modesList.add(afMode);
+        }
+        afModes = new int[modesList.size()];
+        for (int i = 0; i < modesList.size(); i++) {
+            afModes[i] = modesList.get(i);
+        }
+
         if (isHardwareLevelLimitedOrBetter()) {
             // Some LEGACY mode devices do not support AF OFF
             checkTrueForKey(key, " All camera devices must support OFF mode",
@@ -1417,6 +1436,16 @@
         return fpsRanges;
     }
 
+    public static String getAeModeName(int aeMode) {
+        return (aeMode >= AE_MODE_NAMES.length) ? String.format("VENDOR_AE_MODE_%d", aeMode) :
+            AE_MODE_NAMES[aeMode];
+    }
+
+    public static String getAfModeName(int afMode) {
+        return (afMode >= AF_MODE_NAMES.length) ? String.format("VENDOR_AF_MODE_%d", afMode) :
+            AF_MODE_NAMES[afMode];
+    }
+
     /**
      * Get the highest supported target FPS range.
      * Prioritizes maximizing the min FPS, then the max FPS without lowering min FPS.
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
index 82da9a3..e4e0f7f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
@@ -26,13 +26,13 @@
     private int mLastDensity;
 
     public InterestingConfigChanges() {
-        this(0);
+        this(ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT
+                | ActivityInfo.CONFIG_ASSETS_PATHS);
     }
 
-    public InterestingConfigChanges(int extraFlags) {
-        mFlags = extraFlags | ActivityInfo.CONFIG_LOCALE
-                | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT
-                | ActivityInfo.CONFIG_ASSETS_PATHS;
+    public InterestingConfigChanges(int flags) {
+        mFlags = flags;
     }
 
     public boolean applyNewConfig(Resources res) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index b3565ea..623d1a6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -335,6 +335,7 @@
         if (security != SECURITY_NONE) {
             builder.append(',').append(securityToString(security, pskType));
         }
+        builder.append(",mRssi=").append(mRssi);
         builder.append(",level=").append(getLevel());
         if (mRankingScore != Integer.MIN_VALUE) {
             builder.append(",rankingScore=").append(mRankingScore);
@@ -745,8 +746,12 @@
             visibility.append(" rssi=").append(mInfo.getRssi());
             visibility.append(" ");
             visibility.append(" score=").append(mInfo.score);
-            visibility.append(" rankingScore=").append(getRankingScore());
-            visibility.append(" badge=").append(getBadge());
+            if (mRankingScore != Integer.MIN_VALUE) {
+              visibility.append(" rankingScore=").append(getRankingScore());
+            }
+            if (mBadge != NetworkBadging.BADGING_NONE) {
+              visibility.append(" badge=").append(getBadge());
+            }
             visibility.append(String.format(" tx=%.1f,", mInfo.txSuccessRate));
             visibility.append(String.format("%.1f,", mInfo.txRetriesRate));
             visibility.append(String.format("%.1f ", mInfo.txBadRate));
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 20cc5a6..40a59cf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -136,8 +136,6 @@
 
     private final NetworkScoreManager mNetworkScoreManager;
     private final WifiNetworkScoreCache mScoreCache;
-    private boolean mNetworkScoringUiEnabled;
-    private final ContentObserver mObserver;
 
     @GuardedBy("mLock")
     private final Set<NetworkKey> mRequestedScores = new ArraySet<>();
@@ -225,16 +223,6 @@
                 updateNetworkScores();
             }
         });
-
-        mObserver = new ContentObserver(mWorkHandler) {
-            @Override
-            public void onChange(boolean selfChange) {
-                mNetworkScoringUiEnabled =
-                        Settings.Global.getInt(
-                                mContext.getContentResolver(),
-                                Settings.Global.NETWORK_SCORING_UI_ENABLED, 0) == 1;
-            }
-        };
     }
 
     /**
@@ -308,12 +296,6 @@
         synchronized (mLock) {
             registerScoreCache();
 
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.NETWORK_SCORING_UI_ENABLED),
-                    false /* notifyForDescendants */,
-                    mObserver);
-            mObserver.onChange(false /* selfChange */); // Set mScoringUiEnabled
-
             resumeScanning();
             if (!mRegistered) {
                 mContext.registerReceiver(mReceiver, mFilter);
@@ -360,7 +342,6 @@
             }
             unregisterAndClearScoreCache();
             pauseScanning();
-            mContext.getContentResolver().unregisterContentObserver(mObserver);
 
             mWorkHandler.removePendingMessages();
             mMainHandler.removePendingMessages();
@@ -580,7 +561,7 @@
 
         requestScoresForNetworkKeys(scoresToRequest);
         for (AccessPoint ap : accessPoints) {
-            ap.update(mScoreCache, mNetworkScoringUiEnabled);
+            ap.update(mScoreCache, false /* mNetworkScoringUiEnabled */);
         }
 
         // Pre-sort accessPoints to speed preference insertion
@@ -678,7 +659,7 @@
                     updated = true;
                     if (previouslyConnected != ap.isActive()) reorder = true;
                 }
-                if (ap.update(mScoreCache, mNetworkScoringUiEnabled)) {
+                if (ap.update(mScoreCache, false /* mNetworkScoringUiEnabled */)) {
                     reorder = true;
                     updated = true;
                 }
@@ -701,7 +682,8 @@
         synchronized (mLock) {
             boolean updated = false;
             for (int i = 0; i < mInternalAccessPoints.size(); i++) {
-                if (mInternalAccessPoints.get(i).update(mScoreCache, mNetworkScoringUiEnabled)) {
+                if (mInternalAccessPoints.get(i).update(
+                        mScoreCache, false /* mNetworkScoringUiEnabled */)) {
                     updated = true;
                 }
             }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 086e10c..c526432 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -473,7 +473,7 @@
     }
 
     @Test
-    public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
+    public void scoreCacheUpdateScoresShouldNotChangeSortOrder() throws InterruptedException {
         WifiTracker tracker =  createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         List<AccessPoint> aps = tracker.getAccessPoints();
         assertTrue(aps.size() == 2);
@@ -484,8 +484,8 @@
 
         aps = tracker.getAccessPoints();
         assertTrue(aps.size() == 2);
-        assertEquals(aps.get(0).getSsidStr(), SSID_2);
-        assertEquals(aps.get(1).getSsidStr(), SSID_1);
+        assertEquals(aps.get(0).getSsidStr(), SSID_1);
+        assertEquals(aps.get(1).getSsidStr(), SSID_2);
     }
 
     @Test
@@ -511,7 +511,8 @@
     }
 
     @Test
-    public void scoreCacheUpdateScoresShouldInsertBadgeIntoAccessPoint() throws InterruptedException {
+    public void scoreCacheUpdateScoresShouldNotInsertBadgeIntoAccessPoint()
+            throws InterruptedException {
         WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         updateScoresAndWaitForAccessPointsChangedCallback();
 
@@ -519,9 +520,9 @@
 
         for (AccessPoint ap : aps) {
             if (ap.getSsidStr().equals(SSID_1)) {
-                assertEquals(BADGE_1, ap.getBadge());
+                assertEquals(NetworkBadging.BADGING_NONE, ap.getBadge());
             } else if (ap.getSsidStr().equals(SSID_2)) {
-                assertEquals(BADGE_2, ap.getBadge());
+                assertEquals(NetworkBadging.BADGING_NONE, ap.getBadge());
             }
         }
     }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 455d9cb..f5d7dd8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2212,11 +2212,7 @@
                 throw new IllegalStateException("Key is corrupted", e);
             }
 
-            // Mac the package name and each of the signatures.
-            final String packageName = callingPkg.packageName;
-            byte[] packageNameBytes = packageName.getBytes(StandardCharsets.UTF_8);
-            m.update(getLengthPrefix(packageNameBytes), 0, 4);
-            m.update(packageNameBytes);
+            // Mac each of the developer signatures.
             for (int i = 0; i < callingPkg.signatures.length; i++) {
                 byte[] sig = callingPkg.signatures[i].toByteArray();
                 m.update(getLengthPrefix(sig), 0, 4);
@@ -2231,7 +2227,7 @@
             final String uid = Integer.toString(callingPkg.applicationInfo.uid);
             final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId);
             final boolean success = ssaidSettings.insertSettingLocked(uid, ssaid, null, true,
-                    packageName);
+                callingPkg.packageName);
 
             if (!success) {
                 throw new IllegalStateException("Ssaid settings not accessible");
diff --git a/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml b/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
index 3fb86d0..1b6fa4c 100644
--- a/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
@@ -16,5 +16,5 @@
   -->
 
 <resources>
-    <dimen name="widget_big_font_size">64dp</dimen>
+    <dimen name="widget_big_font_size">72dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml b/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
index 3fb86d0..1b6fa4c 100644
--- a/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
@@ -16,5 +16,5 @@
   -->
 
 <resources>
-    <dimen name="widget_big_font_size">64dp</dimen>
+    <dimen name="widget_big_font_size">72dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 3ca6e69..41c723e 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -41,7 +41,7 @@
     <!-- Default clock parameters -->
     <dimen name="bottom_text_spacing_digital">-1dp</dimen>
     <dimen name="widget_label_font_size">14sp</dimen>
-    <dimen name="widget_big_font_size">64dp</dimen>
+    <dimen name="widget_big_font_size">72dp</dimen>
 
     <!-- The y translation to apply at the start in appear animations. -->
     <dimen name="appear_y_translation_start">32dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 0cf8ff0..8ba33c3 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -264,6 +264,9 @@
         mProviders.put(AccessibilityManagerWrapper.class,
                 () -> new AccessibilityManagerWrapper(mContext));
 
+        mProviders.put(ForegroundServiceController.class,
+                () -> new ForegroundServiceControllerImpl(mContext));
+
         mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
 
         // Put all dependencies above here so the factory can override them if it wants.
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
new file mode 100644
index 0000000..a2c9ab4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.service.notification.StatusBarNotification;
+
+public interface ForegroundServiceController {
+    /**
+     * @param sbn notification that was just posted
+     * @param importance
+     */
+    void addNotification(StatusBarNotification sbn, int importance);
+
+    /**
+     * @param sbn notification that was just changed in some way
+     * @param newImportance
+     */
+    void updateNotification(StatusBarNotification sbn, int newImportance);
+
+    /**
+     * @param sbn notification that was just canceled
+     */
+    boolean removeNotification(StatusBarNotification sbn);
+
+    /**
+     * @param userId
+     * @return true if this user has services missing notifications and therefore needs a
+     * disclosure notification.
+     */
+    boolean isDungeonNeededForUser(int userId);
+
+    /**
+     * @param sbn
+     * @return true if sbn is the system-provided "dungeon" (list of running foreground services).
+     */
+    boolean isDungeonNotification(StatusBarNotification sbn);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
new file mode 100644
index 0000000..c930d56
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto;
+
+import java.util.Arrays;
+
+/**
+ * Foreground service controller, a/k/a Dianne's Dungeon.
+ */
+public class ForegroundServiceControllerImpl
+        implements ForegroundServiceController {
+    private static final String TAG = "FgServiceController";
+    private static final boolean DBG = false;
+
+    private final SparseArray<UserServices> mUserServices = new SparseArray<>();
+    private final Object mMutex = new Object();
+
+    public ForegroundServiceControllerImpl(Context context) {
+    }
+
+    @Override
+    public boolean isDungeonNeededForUser(int userId) {
+        synchronized (mMutex) {
+            final UserServices services = mUserServices.get(userId);
+            if (services == null) return false;
+            return services.isDungeonNeeded();
+        }
+    }
+
+    @Override
+    public void addNotification(StatusBarNotification sbn, int importance) {
+        updateNotification(sbn, importance);
+    }
+
+    @Override
+    public boolean removeNotification(StatusBarNotification sbn) {
+        synchronized (mMutex) {
+            final UserServices userServices = mUserServices.get(sbn.getUserId());
+            if (userServices == null) {
+                if (DBG) {
+                    Log.w(TAG, String.format(
+                            "user %d with no known notifications got removeNotification for %s",
+                            sbn.getUserId(), sbn));
+                }
+                return false;
+            }
+            if (isDungeonNotification(sbn)) {
+                // if you remove the dungeon entirely, we take that to mean there are
+                // no running services
+                userServices.setRunningServices(null);
+                return true;
+            } else {
+                // this is safe to call on any notification, not just FLAG_FOREGROUND_SERVICE
+                return userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
+            }
+        }
+    }
+
+    @Override
+    public void updateNotification(StatusBarNotification sbn, int newImportance) {
+        synchronized (mMutex) {
+            UserServices userServices = mUserServices.get(sbn.getUserId());
+            if (userServices == null) {
+                userServices = new UserServices();
+                mUserServices.put(sbn.getUserId(), userServices);
+            }
+
+            if (isDungeonNotification(sbn)) {
+                final Bundle extras = sbn.getNotification().extras;
+                if (extras != null) {
+                    final String[] svcs = extras.getStringArray(Notification.EXTRA_FOREGROUND_APPS);
+                    userServices.setRunningServices(svcs); // null ok
+                }
+            } else {
+                userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
+                if (0 != (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)
+                        && newImportance > NotificationManager.IMPORTANCE_MIN) {
+                    userServices.addNotification(sbn.getPackageName(), sbn.getKey());
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean isDungeonNotification(StatusBarNotification sbn) {
+        return sbn.getId() == SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES
+                && sbn.getTag() == null
+                && sbn.getPackageName().equals("android");
+    }
+
+    /**
+     * Struct to track relevant packages and notifications for a userid's foreground services.
+     */
+    private static class UserServices {
+        private String[] mRunning = null;
+        private ArrayMap<String, ArraySet<String>> mNotifications = new ArrayMap<>(1);
+        public void setRunningServices(String[] pkgs) {
+            mRunning = pkgs != null ? Arrays.copyOf(pkgs, pkgs.length) : null;
+        }
+        public void addNotification(String pkg, String key) {
+            if (mNotifications.get(pkg) == null) {
+                mNotifications.put(pkg, new ArraySet<String>());
+            }
+            mNotifications.get(pkg).add(key);
+        }
+        public boolean removeNotification(String pkg, String key) {
+            final boolean found;
+            final ArraySet<String> keys = mNotifications.get(pkg);
+            if (keys == null) {
+                found = false;
+            } else {
+                found = keys.remove(key);
+                if (keys.size() == 0) {
+                    mNotifications.remove(pkg);
+                }
+            }
+            return found;
+        }
+        public boolean isDungeonNeeded() {
+            if (mRunning != null) {
+                for (String pkg : mRunning) {
+                    final ArraySet<String> set = mNotifications.get(pkg);
+                    if (set == null || set.size() == 0) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 09fdf5a..3b81cc4 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -92,7 +92,9 @@
         mAssistDisclosure = new AssistDisclosure(context, new Handler());
 
         registerVoiceInteractionSessionListener();
-        mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION);
+        mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
+                | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
+                | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
         onConfigurationChanged(context.getResources().getConfiguration());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 8ac97f3..ee155d9 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -49,7 +49,8 @@
     private final HashMap<String, ArrayList<FragmentListener>> mListeners = new HashMap<>();
     private final View mRootView;
     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
-            ActivityInfo.CONFIG_FONT_SCALE);
+            ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
     private final FragmentService mManager;
     private final PluginFragmentManager mPlugins = new PluginFragmentManager();
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 5414aad..f98310d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -239,7 +239,11 @@
             }
         }
 
-        loadConfigurationsAndApply(mContext.getResources().getConfiguration());
+        // Initialize the last orientation and apply the current configuration
+        Configuration initialConfig = mContext.getResources().getConfiguration();
+        mLastOrientation = initialConfig.orientation;
+        loadConfigurationsAndApply(initialConfig);
+
         mMediaSessionManager =
                 (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 682c56c..488fc03 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -18,12 +18,14 @@
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_DATE;
 
+import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.RippleDrawable;
 import android.os.UserManager;
@@ -42,6 +44,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.keyguard.KeyguardStatusView;
+import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
@@ -423,6 +426,13 @@
 
     @Override
     public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
+        if (picture != null &&
+                UserManager.get(mContext).isGuestUser(ActivityManager.getCurrentUser())) {
+            picture = picture.getConstantState().newDrawable().mutate();
+            picture.setColorFilter(
+                    Utils.getColorAttr(mContext, android.R.attr.colorForeground),
+                    Mode.SRC_IN);
+        }
         mMultiUserAvatar.setImageDrawable(picture);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index ecbc4f7..9557262 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -140,7 +140,8 @@
         if (mState.value) {
             mController.setZen(ZEN_MODE_OFF, null, TAG);
         } else {
-            mController.setZen(ZEN_MODE_ALARMS, null, TAG);
+            int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
+            mController.setZen(zen, null, TAG);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 7697061..ba3bcc7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -514,6 +514,9 @@
             RecentsActivityLaunchState launchState = config.getLaunchState();
             launchState.reset();
         }
+
+        // Force a gc to attempt to clean up bitmap references more quickly (b/38258699)
+        Recents.getSystemServices().gc();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index cbfa0e5..1f13830 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -362,6 +362,19 @@
     }
 
     /**
+     * Requests a gc() from the background thread.
+     */
+    public void gc() {
+        BackgroundThread.getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                System.gc();
+                System.runFinalization();
+            }
+        });
+    }
+
+    /**
      * @return whether the provided {@param className} is blacklisted
      */
     public boolean isBlackListedActivity(String className) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java
index 5e87e2a..716d1bc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java
@@ -54,7 +54,6 @@
     public static final int FOCUS_STATE = 8;
 
     private SparseLongArray mPropStartDelay;
-    private SparseLongArray mPropInitialPlayTime;
     private SparseLongArray mPropDuration;
     private SparseArray<Interpolator> mPropInterpolators;
     private Animator.AnimatorListener mListener;
@@ -122,10 +121,6 @@
         animator.setStartDelay(getStartDelay(propertyType));
         animator.setDuration(getDuration(propertyType));
         animator.setInterpolator(getInterpolator(propertyType));
-        long initialPlayTime = getInitialPlayTime(propertyType);
-        if (initialPlayTime != 0) {
-            animator.setCurrentPlayTime(initialPlayTime);
-        }
         return animator;
     }
 
@@ -141,17 +136,6 @@
     }
 
     /**
-     * Sets a initial play time for a specific property.
-     */
-    public AnimationProps setInitialPlayTime(@PropType int propertyType, int initialPlayTime) {
-        if (mPropInitialPlayTime == null) {
-            mPropInitialPlayTime = new SparseLongArray();
-        }
-        mPropInitialPlayTime.append(propertyType, initialPlayTime);
-        return this;
-    }
-
-    /**
      * Returns the start delay for a specific property.
      */
     public long getStartDelay(@PropType int propertyType) {
@@ -217,20 +201,6 @@
     }
 
     /**
-     * Returns the initial play time for a specific property, falling back to the general initial
-     * play time if there is no specific property interpolator.
-     */
-    public long getInitialPlayTime(@PropType int propertyType) {
-        if (mPropInitialPlayTime != null) {
-            if (mPropInitialPlayTime.indexOfKey(propertyType) != -1) {
-                return mPropInitialPlayTime.get(propertyType);
-            }
-            return mPropInitialPlayTime.get(ALL, 0);
-        }
-        return 0;
-    }
-
-    /**
      * Sets an animator listener for this animation.
      */
     public AnimationProps setListener(Animator.AnimatorListener listener) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
new file mode 100644
index 0000000..e32da2d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.view.animation.PathInterpolator;
+
+/**
+ * A helper interpolator to stagger the entrance animation in recents by offsetting the start time
+ */
+public class RecentsEntrancePathInterpolator extends PathInterpolator {
+    final float mStartOffsetFraction;
+
+    /**
+     * Create an interpolator for a cubic Bezier curve with an offset play time. The end points
+     * <code>(0, 0)</code> and <code>(1, 1)</code> are assumed.
+     *
+     * @param controlX1 The x coordinate of the first control point of the cubic Bezier.
+     * @param controlY1 The y coordinate of the first control point of the cubic Bezier.
+     * @param controlX2 The x coordinate of the second control point of the cubic Bezier.
+     * @param controlY2 The y coordinate of the second control point of the cubic Bezier.
+     * @param startOffsetFraction The fraction from 0 to 1 to start the animation from
+     */
+    public RecentsEntrancePathInterpolator(float controlX1, float controlY1, float controlX2,
+            float controlY2, float startOffsetFraction) {
+        super(controlX1, controlY1, controlX2, controlY2);
+        mStartOffsetFraction = startOffsetFraction;
+    }
+
+    @Override
+    public float getInterpolation(float t) {
+        return super.getInterpolation(t + mStartOffsetFraction);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index f1314aba..0fc68e6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -82,8 +82,6 @@
 
     private static final int ENTER_FROM_HOME_ALPHA_DURATION = 100;
     public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 300;
-    private static final Interpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR =
-            Interpolators.LINEAR_OUT_SLOW_IN;
     private static final Interpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR = Interpolators.LINEAR;
 
     public static final int EXIT_TO_HOME_TRANSLATION_DURATION = 200;
@@ -260,17 +258,18 @@
             } else if (launchState.launchedFromHome) {
                 // Animate the tasks up, but offset the animations to be relative to the front-most
                 // task animation
+                final float startOffsetFraction = (float) (Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS,
+                        taskIndexFromFront) * mEnterAndExitFromHomeTranslationOffset) /
+                        ENTER_FROM_HOME_TRANSLATION_DURATION;
                 AnimationProps taskAnimation = new AnimationProps()
-                        .setInitialPlayTime(AnimationProps.BOUNDS,
-                                Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) *
-                                        mEnterAndExitFromHomeTranslationOffset)
                         .setStartDelay(AnimationProps.ALPHA,
                                 Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) *
                                         FRAME_OFFSET_MS)
                         .setDuration(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_DURATION)
                         .setDuration(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_DURATION)
                         .setInterpolator(AnimationProps.BOUNDS,
-                                ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR)
+                                new RecentsEntrancePathInterpolator(0f, 0f, 0.2f, 1f,
+                                        startOffsetFraction))
                         .setInterpolator(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_INTERPOLATOR)
                         .setListener(postAnimationTrigger.decrementOnAnimationEnd());
                 postAnimationTrigger.increment();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 0b09acc..3b37437 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -91,6 +91,9 @@
     }
 
     private void removeDivider() {
+        if (mView != null) {
+            mView.onDividerRemoved();
+        }
         mWindowManager.remove();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 9e2ec57..6dc7870 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -162,6 +162,9 @@
     private DividerState mState;
     private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
 
+    // The view is removed or in the process of been removed from the system.
+    private boolean mRemoved;
+
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -323,6 +326,11 @@
         EventBus.getDefault().unregister(this);
     }
 
+    void onDividerRemoved() {
+        mRemoved = true;
+        mHandler.removeMessages(MSG_RESIZE_STACK);
+    }
+
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         if (mStableInsets.left != insets.getStableInsetLeft()
@@ -917,6 +925,10 @@
     }
 
     public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
+        if (mRemoved) {
+            // This divider view has been removed so shouldn't have any additional influence.
+            return;
+        }
         calculateBoundsForPosition(position, mDockSide, mDockedRect);
 
         if (mDockedRect.equals(mLastResizeRect) && !mEntranceAnimationRunning) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index a81b140..1c1be98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -357,15 +357,21 @@
         updateShelfIconColor();
     }
 
-    private void updateShelfIconColor() {
+    @VisibleForTesting
+    void updateShelfIconColor() {
         StatusBarIconView expandedIcon = mEntry.expandedIcon;
         boolean isPreL = Boolean.TRUE.equals(expandedIcon.getTag(R.id.icon_is_pre_L));
         boolean colorize = !isPreL || NotificationUtils.isGrayscale(expandedIcon,
                 NotificationColorUtil.getInstance(mContext));
         int color = StatusBarIconView.NO_COLOR;
         if (colorize) {
-            color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded(),
-                    getBackgroundColorWithoutTint());
+            NotificationHeaderView header = getVisibleNotificationHeader();
+            if (header != null) {
+                color = header.getOriginalIconColor();
+            } else {
+                color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded(),
+                        getBackgroundColorWithoutTint());
+            }
         }
         expandedIcon.setStaticDrawableColor(color);
     }
@@ -1389,6 +1395,7 @@
         if (mIsSummaryWithChildren) {
             mChildrenContainer.setDark(dark, fade, delay);
         }
+        updateShelfIconColor();
     }
 
     public boolean isExpandable() {
@@ -1728,6 +1735,7 @@
         NotificationContentView showingLayout = getShowingLayout();
         showingLayout.updateBackgroundColor(animated);
         mPrivateLayout.updateExpandButtons(isExpandable());
+        updateShelfIconColor();
         showingLayout.setDark(isDark(), false /* animate */, 0 /* delay */);
         mShowingPublicInitialized = true;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 1844946..58844ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -24,6 +24,8 @@
 import android.content.pm.PackageManager;
 import android.content.Context;
 import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.service.notification.NotificationListenerService;
@@ -38,8 +40,11 @@
 import android.Manifest;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.NotificationColorUtil;
+import com.android.systemui.Dependency;
+import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.statusbar.notification.InflationException;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -141,12 +146,12 @@
 
             // Construct the icon.
             icon = new StatusBarIconView(context,
-                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
+                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
             icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
 
             // Construct the expanded icon.
             expandedIcon = new StatusBarIconView(context,
-                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
+                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
             expandedIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
             final StatusBarIcon ic = new StatusBarIcon(
                     sbn.getUser(),
@@ -182,9 +187,11 @@
          * @param n the notification to read the icon from.
          * @throws InflationException
          */
-        public void updateIcons(Context context, Notification n) throws InflationException {
+        public void updateIcons(Context context, StatusBarNotification sbn)
+                throws InflationException {
             if (icon != null) {
                 // Update the icon
+                Notification n = sbn.getNotification();
                 final StatusBarIcon ic = new StatusBarIcon(
                         notification.getUser(),
                         notification.getPackageName(),
@@ -192,8 +199,8 @@
                         n.iconLevel,
                         n.number,
                         StatusBarIconView.contentDescForNotification(context, n));
-                icon.setNotification(n);
-                expandedIcon.setNotification(n);
+                icon.setNotification(sbn);
+                expandedIcon.setNotification(sbn);
                 if (!icon.set(ic) || !expandedIcon.set(ic)) {
                     throw new InflationException("Couldn't update icon: " + ic);
                 }
@@ -339,6 +346,7 @@
             mEntries.put(entry.notification.getKey(), entry);
         }
         mGroupManager.onEntryAdded(entry);
+
         updateRankingAndSort(mRankingMap);
     }
 
@@ -466,6 +474,10 @@
         Collections.sort(mSortedAndFiltered, mRankingComparator);
     }
 
+    /**
+     * @param sbn
+     * @return true if this notification should NOT be shown right now
+     */
     public boolean shouldFilterOut(StatusBarNotification sbn) {
         if (!(mEnvironment.isDeviceProvisioned() ||
                 showNotificationEvenIfUnprovisioned(sbn))) {
@@ -487,6 +499,13 @@
                 && mGroupManager.isChildInGroupWithSummary(sbn)) {
             return true;
         }
+
+        final ForegroundServiceController fsc = Dependency.get(ForegroundServiceController.class);
+        if (fsc.isDungeonNotification(sbn) && !fsc.isDungeonNeededForUser(sbn.getUserId())) {
+            // this is a foreground-service disclosure for a user that does not need to show one
+            return true;
+        }
+
         return false;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 8368143..bbcbfd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -456,9 +456,8 @@
             }
             int shelfColor = icon.getStaticDrawableColor();
             if (!noIcon && shelfColor != StatusBarIconView.NO_COLOR) {
-                int notificationColor
-                        = row.getVisibleNotificationHeader().getOriginalNotificationColor();
-                shelfColor = NotificationUtils.interpolateColors(notificationColor, shelfColor,
+                int iconColor = row.getVisibleNotificationHeader().getOriginalIconColor();
+                shelfColor = NotificationUtils.interpolateColors(iconColor, shelfColor,
                         iconState.iconAppearAmount);
             }
             iconState.iconColor = shelfColor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 85475b6..3c7ddb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -34,6 +34,7 @@
 import android.graphics.drawable.Icon;
 import android.os.Parcelable;
 import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
@@ -99,7 +100,7 @@
     private int mNumberX;
     private int mNumberY;
     private String mNumberText;
-    private Notification mNotification;
+    private StatusBarNotification mNotification;
     private final boolean mBlocked;
     private int mDensity;
     private float mIconScale = 1.0f;
@@ -127,11 +128,11 @@
     };
     private final NotificationIconDozeHelper mDozer;
 
-    public StatusBarIconView(Context context, String slot, Notification notification) {
-        this(context, slot, notification, false);
+    public StatusBarIconView(Context context, String slot, StatusBarNotification sbn) {
+        this(context, slot, sbn, false);
     }
 
-    public StatusBarIconView(Context context, String slot, Notification notification,
+    public StatusBarIconView(Context context, String slot, StatusBarNotification sbn,
             boolean blocked) {
         super(context);
         mDozer = new NotificationIconDozeHelper(context);
@@ -141,7 +142,7 @@
         mNumberPain.setTextAlign(Paint.Align.CENTER);
         mNumberPain.setColor(context.getColor(R.drawable.notification_number_text_color));
         mNumberPain.setAntiAlias(true);
-        setNotification(notification);
+        setNotification(sbn);
         maybeUpdateIconScaleDimens();
         setScaleType(ScaleType.CENTER);
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
@@ -207,9 +208,11 @@
         }
     }
 
-    public void setNotification(Notification notification) {
+    public void setNotification(StatusBarNotification notification) {
         mNotification = notification;
-        setContentDescription(notification);
+        if (notification != null) {
+            setContentDescription(notification.getNotification());
+        }
     }
 
     public StatusBarIconView(Context context, AttributeSet attrs) {
@@ -315,6 +318,10 @@
         return true;
     }
 
+    public Icon getSourceIcon() {
+        return mIcon.icon;
+    }
+
     private Drawable getIcon(StatusBarIcon icon) {
         return getIcon(getContext(), icon);
     }
@@ -354,7 +361,7 @@
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
         if (mNotification != null) {
-            event.setParcelableData(mNotification);
+            event.setParcelableData(mNotification.getNotification());
         }
     }
 
@@ -456,6 +463,10 @@
             + " notification=" + mNotification + ")";
     }
 
+    public StatusBarNotification getNotification() {
+        return mNotification;
+    }
+
     public String getSlot() {
         return mSlot;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 52838b0..5bfdd1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -4,11 +4,15 @@
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.Icon;
 import android.support.annotation.NonNull;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.util.ArraySet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
 
+import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.NotificationColorUtil;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -180,14 +184,54 @@
             }
         }
 
+        // In case we are changing the suppression of a group, the replacement shouldn't flicker
+        // and it should just be replaced instead. We therefore look for notifications that were
+        // just replaced by the child or vice-versa to suppress this.
 
+        ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons = new ArrayMap<>();
         ArrayList<View> toRemove = new ArrayList<>();
         for (int i = 0; i < hostLayout.getChildCount(); i++) {
             View child = hostLayout.getChildAt(i);
+            if (!(child instanceof StatusBarIconView)) {
+                continue;
+            }
             if (!toShow.contains(child)) {
-                toRemove.add(child);
+                boolean iconWasReplaced = false;
+                StatusBarIconView removedIcon = (StatusBarIconView) child;
+                String removedGroupKey = removedIcon.getNotification().getGroupKey();
+                for (int j = 0; j < toShow.size(); j++) {
+                    StatusBarIconView candidate = toShow.get(j);
+                    if (candidate.getSourceIcon().sameAs((removedIcon.getSourceIcon()))
+                            && candidate.getNotification().getGroupKey().equals(removedGroupKey)) {
+                        if (!iconWasReplaced) {
+                            iconWasReplaced = true;
+                        } else {
+                            iconWasReplaced = false;
+                            break;
+                        }
+                    }
+                }
+                if (iconWasReplaced) {
+                    ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(removedGroupKey);
+                    if (statusBarIcons == null) {
+                        statusBarIcons = new ArrayList<>();
+                        replacingIcons.put(removedGroupKey, statusBarIcons);
+                    }
+                    statusBarIcons.add(removedIcon.getStatusBarIcon());
+                }
+                toRemove.add(removedIcon);
             }
         }
+        // removing all duplicates
+        ArrayList<String> duplicates = new ArrayList<>();
+        for (String key : replacingIcons.keySet()) {
+            ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(key);
+            if (statusBarIcons.size() != 1) {
+                duplicates.add(key);
+            }
+        }
+        replacingIcons.removeAll(duplicates);
+        hostLayout.setReplacingIcons(replacingIcons);
 
         final int toRemoveCount = toRemove.size();
         for (int i = 0; i < toRemoveCount; i++) {
@@ -217,6 +261,7 @@
             hostLayout.addView(expected, i);
         }
         hostLayout.setChangingViewPositions(false);
+        hostLayout.setReplacingIcons(null);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index f94bb0c..a4fadc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -21,9 +21,13 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.drawable.Icon;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.util.ArraySet;
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
@@ -33,6 +37,7 @@
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 import com.android.systemui.statusbar.stack.ViewState;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 
 /**
@@ -117,6 +122,7 @@
     private float mVisualOverflowAdaption;
     private boolean mDisallowNextAnimation;
     private boolean mAnimationsEnabled = true;
+    private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIcons;
 
     public NotificationIconContainer(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -183,11 +189,17 @@
     @Override
     public void onViewAdded(View child) {
         super.onViewAdded(child);
+        boolean isReplacingIcon = isReplacingIcon(child);
         if (!mChangingViewPositions) {
-            mIconStates.put(child, new IconState());
+            IconState v = new IconState();
+            if (isReplacingIcon) {
+                v.justAdded = false;
+                v.justReplaced = true;
+            }
+            mIconStates.put(child, v);
         }
         int childIndex = indexOfChild(child);
-        if (childIndex < getChildCount() - 1
+        if (childIndex < getChildCount() - 1 && !isReplacingIcon
             && mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) {
             if (mAddAnimationStartIndex < 0) {
                 mAddAnimationStartIndex = childIndex;
@@ -200,13 +212,34 @@
         }
     }
 
+    private boolean isReplacingIcon(View child) {
+        if (mReplacingIcons == null) {
+            return false;
+        }
+        if (!(child instanceof StatusBarIconView)) {
+            return false;
+        }
+        StatusBarIconView iconView = (StatusBarIconView) child;
+        Icon sourceIcon = iconView.getSourceIcon();
+        String groupKey = iconView.getNotification().getGroupKey();
+        ArrayList<StatusBarIcon> statusBarIcons = mReplacingIcons.get(groupKey);
+        if (statusBarIcons != null) {
+            StatusBarIcon replacedIcon = statusBarIcons.get(0);
+            if (sourceIcon.sameAs(replacedIcon.icon)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     public void onViewRemoved(View child) {
         super.onViewRemoved(child);
         if (child instanceof StatusBarIconView) {
+            boolean isReplacingIcon = isReplacingIcon(child);
             final StatusBarIconView icon = (StatusBarIconView) child;
             if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
-                    && child.getVisibility() == VISIBLE) {
+                    && child.getVisibility() == VISIBLE && isReplacingIcon) {
                 int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
                 if (mAddAnimationStartIndex < 0) {
                     mAddAnimationStartIndex = animationStartIndex;
@@ -216,9 +249,11 @@
             }
             if (!mChangingViewPositions) {
                 mIconStates.remove(child);
-                addTransientView(icon, 0);
-                icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
-                        () -> removeTransientView(icon));
+                if (!isReplacingIcon) {
+                    addTransientView(icon, 0);
+                    icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
+                            () -> removeTransientView(icon));
+                }
             }
         }
     }
@@ -473,11 +508,16 @@
         mAnimationsEnabled = enabled;
     }
 
+    public void setReplacingIcons(ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons) {
+        mReplacingIcons = replacingIcons;
+    }
+
     public class IconState extends ViewState {
         public float iconAppearAmount = 1.0f;
         public float clampedAppearAmount = 1.0f;
         public int visibleState;
         public boolean justAdded = true;
+        private boolean justReplaced;
         public boolean needsCannedAnimation;
         public boolean useFullTransitionAmount;
         public boolean useLinearTransitionAmount;
@@ -496,9 +536,9 @@
                         && !mDisallowNextAnimation
                         && !noAnimations;
                 if (animationsAllowed) {
-                    if (justAdded) {
+                    if (justAdded || justReplaced) {
                         super.applyToView(icon);
-                        if (iconAppearAmount != 0.0f) {
+                        if (justAdded && iconAppearAmount != 0.0f) {
                             icon.setAlpha(0.0f);
                             icon.setVisibleState(StatusBarIconView.STATE_HIDDEN,
                                     false /* animate */);
@@ -557,6 +597,7 @@
                 }
             }
             justAdded = false;
+            justReplaced = false;
             needsCannedAnimation = false;
             justUndarkened = false;
         }
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 4e28e90..f4f48a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -36,11 +36,17 @@
 import android.animation.AnimatorListenerAdapter;
 import android.annotation.NonNull;
 import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
 import android.app.ActivityOptions;
+import android.app.INotificationManager;
+import android.app.KeyguardManager;
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.RemoteInput;
 import android.app.StatusBarManager;
+import android.app.TaskStackBuilder;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
@@ -49,8 +55,11 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -75,7 +84,9 @@
 import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.PowerManager;
@@ -83,54 +94,73 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.SystemService;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
+import android.view.IWindowManager;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.ThreadedRenderer;
 import android.view.View;
+import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.widget.DateTimeView;
 import android.widget.ImageView;
+import android.widget.RemoteViews;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.NotificationMessagingUtil;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.ActivityStarterDelegate;
+import com.android.systemui.DejankUtils;
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dependency;
 import com.android.systemui.EventLogTags;
+import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.Interpolators;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.assist.AssistManager;
@@ -141,12 +171,14 @@
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.PluginFragmentListener;
 import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
@@ -194,11 +226,15 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 import com.android.systemui.statusbar.policy.PreviewInflater;
+import com.android.systemui.statusbar.policy.RemoteInputView;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+        .OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.util.NotificationChannels;
 import com.android.systemui.util.leak.LeakDetector;
 import com.android.systemui.volume.VolumeComponent;
 
@@ -209,48 +245,10 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import android.app.ActivityManager.StackId;
-import android.app.INotificationManager;
-import android.app.KeyguardManager;
-import android.app.NotificationChannel;
-import android.app.RemoteInput;
-import android.app.TaskStackBuilder;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
-import android.os.Build;
-import android.os.Handler;
-import android.service.notification.NotificationListenerService;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
-import android.text.TextUtils;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-import android.view.IWindowManager;
-import android.view.ViewAnimationUtils;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.RemoteViews;
-import android.widget.Toast;
-
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SwipeHelper;
-import com.android.systemui.SystemUI;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.statusbar.policy.RemoteInputView;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
-import com.android.systemui.util.NotificationChannels;
-
 import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 import java.util.Stack;
 
@@ -473,6 +471,7 @@
     int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
     private final Rect mLastFullscreenStackBounds = new Rect();
     private final Rect mLastDockedStackBounds = new Rect();
+    private final Rect mTmpRect = new Rect();
 
     // last value sent to window manager
     private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
@@ -718,6 +717,7 @@
     private ConfigurationListener mConfigurationListener;
     private boolean mReinflateNotificationsOnUserSwitched;
     private HashMap<String, Entry> mPendingNotifications = new HashMap<>();
+    private ForegroundServiceController mForegroundServiceController;
 
     private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
         final int N = array.size();
@@ -761,6 +761,8 @@
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
         mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
 
+        mForegroundServiceController = Dependency.get(ForegroundServiceController.class);
+
         mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
         mDisplay = mWindowManager.getDefaultDisplay();
         updateDisplaySize();
@@ -1370,20 +1372,33 @@
         int numChildren = mStackScroller.getChildCount();
 
         final ArrayList<View> viewsToHide = new ArrayList<View>(numChildren);
+        final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren);
         for (int i = 0; i < numChildren; i++) {
             final View child = mStackScroller.getChildAt(i);
             if (child instanceof ExpandableNotificationRow) {
-                if (mStackScroller.canChildBeDismissed(child)) {
-                    if (child.getVisibility() == View.VISIBLE) {
-                        viewsToHide.add(child);
-                    }
-                }
                 ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                boolean parentVisible = false;
+                boolean hasClipBounds = child.getClipBounds(mTmpRect);
+                if (mStackScroller.canChildBeDismissed(child)) {
+                    viewsToRemove.add(row);
+                    if (child.getVisibility() == View.VISIBLE
+                            && (!hasClipBounds || mTmpRect.height() > 0)) {
+                        viewsToHide.add(child);
+                        parentVisible = true;
+                    }
+                } else if (child.getVisibility() == View.VISIBLE
+                        && (!hasClipBounds || mTmpRect.height() > 0)) {
+                    parentVisible = true;
+                }
                 List<ExpandableNotificationRow> children = row.getNotificationChildren();
-                if (row.areChildrenExpanded() && children != null) {
+                if (children != null) {
                     for (ExpandableNotificationRow childRow : children) {
-                        if (mStackScroller.canChildBeDismissed(childRow)) {
-                            if (childRow.getVisibility() == View.VISIBLE) {
+                        viewsToRemove.add(childRow);
+                        if (parentVisible && row.areChildrenExpanded()
+                                && mStackScroller.canChildBeDismissed(childRow)) {
+                            hasClipBounds = childRow.getClipBounds(mTmpRect);
+                            if (childRow.getVisibility() == View.VISIBLE
+                                    && (!hasClipBounds || mTmpRect.height() > 0)) {
                                 viewsToHide.add(childRow);
                             }
                         }
@@ -1391,7 +1406,7 @@
                 }
             }
         }
-        if (viewsToHide.isEmpty()) {
+        if (viewsToRemove.isEmpty()) {
             animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
             return;
         }
@@ -1400,6 +1415,13 @@
             @Override
             public void run() {
                 mStackScroller.setDismissAllInProgress(false);
+                for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
+                    if (mStackScroller.canChildBeDismissed(rowToRemove)) {
+                        removeNotification(rowToRemove.getEntry().key, null);
+                    } else {
+                        rowToRemove.resetTranslation();
+                    }
+                }
                 try {
                     mBarService.onClearAllNotifications(mCurrentUserId);
                 } catch (Exception ex) { }
@@ -1578,6 +1600,10 @@
             }
         }
         abortExistingInflation(key);
+
+        mForegroundServiceController.addNotification(notification,
+                mNotificationData.getImportance(key));
+
         mPendingNotifications.put(key, shadeEntry);
     }
 
@@ -1716,6 +1742,10 @@
             return;
         }
 
+        if (entry != null) {
+            mForegroundServiceController.removeNotification(entry.notification);
+        }
+
         if (entry != null && entry.row != null) {
             entry.row.setRemoved();
             mStackScroller.cleanUpViewState(entry.row);
@@ -3547,6 +3577,12 @@
                     // Do it after DismissAction has been processed to conserve the needed ordering.
                     mHandler.post(this::runPostCollapseRunnables);
                 }
+            } else if (isInLaunchTransition() && mNotificationPanel.isLaunchTransitionFinished()) {
+
+                // We are not dismissing the shade, but the launch transition is already finished,
+                // so nobody will call readyForKeyguardDone anymore. Post it such that
+                // keyguardDonePending gets called first.
+                mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone);
             }
             return deferred;
         }, cancelAction, afterKeyguardGone);
@@ -6085,6 +6121,9 @@
     }
 
     public boolean isLockscreenPublicMode(int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            return mLockscreenPublicMode.get(mCurrentUserId, false);
+        }
         return mLockscreenPublicMode.get(userId, false);
     }
 
@@ -6763,9 +6802,12 @@
         entry.notification = notification;
         mGroupManager.onEntryUpdated(entry, oldNotification);
 
-        entry.updateIcons(mContext, n);
+        entry.updateIcons(mContext, notification);
         inflateViews(entry, mStackScroller);
 
+        mForegroundServiceController.updateNotification(notification,
+                mNotificationData.getImportance(key));
+
         boolean shouldPeek = shouldPeek(entry, notification);
         boolean alertAgain = alertAgain(entry, n);
 
@@ -6783,6 +6825,7 @@
             boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
             Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
         }
+
         setAreThereNotifications();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index e86a34a..f6d36e8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -60,7 +60,8 @@
     private final Context mContext;
     private final VolumeDialogControllerImpl mController;
     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
-            ActivityInfo.CONFIG_FONT_SCALE);
+            ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
+            | ActivityInfo.CONFIG_ASSETS_PATHS);
     private final Extension mExtension;
     private VolumeDialog mDialog;
     private VolumePolicy mVolumePolicy = new VolumePolicy(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
new file mode 100644
index 0000000..1f5255a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.annotation.UserIdInt;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import com.android.internal.messages.nano.SystemMessageProto;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ForegroundServiceControllerTest extends SysuiTestCase {
+    public static @UserIdInt int USERID_ONE = 10; // UserManagerService.MIN_USER_ID;
+    public static @UserIdInt int USERID_TWO = USERID_ONE + 1;
+
+    private ForegroundServiceController fsc;
+
+    @Before
+    public void setUp() throws Exception {
+        fsc = new ForegroundServiceControllerImpl(mContext);
+    }
+
+    @Test
+    public void testNotificationCRUD() {
+        StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, "com.example.app1");
+        StatusBarNotification sbn_user2_app2_fg = makeMockFgSBN(USERID_TWO, "com.example.app2");
+        StatusBarNotification sbn_user1_app3_fg = makeMockFgSBN(USERID_ONE, "com.example.app3");
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user2_app1 = makeMockSBN(USERID_TWO, "com.example.app1",
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+
+        assertFalse(fsc.removeNotification(sbn_user1_app3_fg));
+        assertFalse(fsc.removeNotification(sbn_user2_app2_fg));
+        assertFalse(fsc.removeNotification(sbn_user1_app1_fg));
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.removeNotification(sbn_user2_app1));
+
+        fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user2_app2_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user1_app3_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user2_app1, NotificationManager.IMPORTANCE_DEFAULT);
+
+        // these are never added to the tracker
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.removeNotification(sbn_user2_app1));
+
+        fsc.updateNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.updateNotification(sbn_user2_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        // should still not be there
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.removeNotification(sbn_user2_app1));
+
+        fsc.updateNotification(sbn_user2_app2_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.updateNotification(sbn_user1_app3_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.updateNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+
+        assertTrue(fsc.removeNotification(sbn_user1_app3_fg));
+        assertFalse(fsc.removeNotification(sbn_user1_app3_fg));
+
+        assertTrue(fsc.removeNotification(sbn_user2_app2_fg));
+        assertFalse(fsc.removeNotification(sbn_user2_app2_fg));
+
+        assertTrue(fsc.removeNotification(sbn_user1_app1_fg));
+        assertFalse(fsc.removeNotification(sbn_user1_app1_fg));
+
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.removeNotification(sbn_user2_app1));
+    }
+
+    @Test
+    public void testDungeonPredicate() {
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user1_dungeon = makeMockSBN(USERID_ONE, "android",
+                SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
+                null, Notification.FLAG_NO_CLEAR);
+
+        assertTrue(fsc.isDungeonNotification(sbn_user1_dungeon));
+        assertFalse(fsc.isDungeonNotification(sbn_user1_app1));
+    }
+
+    @Test
+    public void testDungeonCRUD() {
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user1_dungeon = makeMockSBN(USERID_ONE, "android",
+                SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
+                null, Notification.FLAG_NO_CLEAR);
+
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user1_dungeon, NotificationManager.IMPORTANCE_DEFAULT);
+
+        fsc.removeNotification(sbn_user1_dungeon);
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+    }
+
+    @Test
+    public void testNeedsDungeonAfterRemovingUnrelatedNotification() {
+        final String PKG1 = "com.example.app100";
+
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1);
+
+        // first add a normal notification
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        // nothing required yet
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        // now the app starts a fg service
+        fsc.addNotification(makeMockDungeon(USERID_ONE, new String[]{ PKG1 }),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        // add the fg notification
+        fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // app1 has got it covered
+        // remove the boring notification
+        fsc.removeNotification(sbn_user1_app1);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // app1 has STILL got it covered
+        assertTrue(fsc.removeNotification(sbn_user1_app1_fg));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+    }
+
+    @Test
+    public void testSimpleAddRemove() {
+        final String PKG1 = "com.example.app1";
+        final String PKG2 = "com.example.app2";
+
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+
+        // no services are "running"
+        fsc.addNotification(makeMockDungeon(USERID_ONE, null),
+                NotificationManager.IMPORTANCE_DEFAULT);
+
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        fsc.updateNotification(makeMockDungeon(USERID_ONE, new String[]{PKG1}),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // switch to different package
+        fsc.updateNotification(makeMockDungeon(USERID_ONE, new String[]{PKG2}),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        fsc.updateNotification(makeMockDungeon(USERID_TWO, new String[]{PKG1}),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_TWO)); // finally user2 needs one too
+
+        fsc.updateNotification(makeMockDungeon(USERID_ONE, new String[]{PKG2, PKG1}),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        fsc.removeNotification(makeMockDungeon(USERID_ONE, null /*unused*/));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        fsc.removeNotification(makeMockDungeon(USERID_TWO, null /*unused*/));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+    }
+
+    @Test
+    public void testDungeonBasic() {
+        final String PKG1 = "com.example.app0";
+
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1);
+
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT); // not fg
+        fsc.addNotification(makeMockDungeon(USERID_ONE, new String[]{ PKG1 }),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // app1 has got it covered
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // let's take out the other notification and see what happens.
+
+        fsc.removeNotification(sbn_user1_app1);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // still covered by sbn_user1_app1_fg
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // let's attempt to downgrade the notification from FLAG_FOREGROUND and see what we get
+        StatusBarNotification sbn_user1_app1_fg_sneaky = makeMockFgSBN(USERID_ONE, PKG1);
+        sbn_user1_app1_fg_sneaky.getNotification().flags = 0;
+        fsc.updateNotification(sbn_user1_app1_fg_sneaky, NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // ok, ok, we'll put it back
+        sbn_user1_app1_fg_sneaky.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+        fsc.updateNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        assertTrue(fsc.removeNotification(sbn_user1_app1_fg_sneaky));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // now let's test an upgrade
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+        sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
+        fsc.updateNotification(sbn_user1_app1,
+                NotificationManager.IMPORTANCE_DEFAULT); // this is now a fg notification
+
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+
+        // remove it, make sure we're out of compliance again
+        assertTrue(fsc.removeNotification(sbn_user1_app1)); // was fg, should return true
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+
+        // finally, let's turn off the service
+        fsc.addNotification(makeMockDungeon(USERID_ONE, null),
+                NotificationManager.IMPORTANCE_DEFAULT);
+
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+    }
+
+    private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
+            int flags) {
+        final Notification n = mock(Notification.class);
+        n.flags = flags;
+        return makeMockSBN(userid, pkg, id, tag, n);
+    }
+    private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
+            Notification n) {
+        final StatusBarNotification sbn = mock(StatusBarNotification.class);
+        when(sbn.getNotification()).thenReturn(n);
+        when(sbn.getId()).thenReturn(id);
+        when(sbn.getPackageName()).thenReturn(pkg);
+        when(sbn.getTag()).thenReturn(null);
+        when(sbn.getUserId()).thenReturn(userid);
+        when(sbn.getUser()).thenReturn(new UserHandle(userid));
+        when(sbn.getKey()).thenReturn("MOCK:"+userid+"|"+pkg+"|"+id+"|"+tag);
+        return sbn;
+    }
+    private StatusBarNotification makeMockFgSBN(int userid, String pkg) {
+        return makeMockSBN(userid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE);
+    }
+    private StatusBarNotification makeMockDungeon(int userid, String[] pkgs) {
+        final Notification n = mock(Notification.class);
+        n.flags = Notification.FLAG_ONGOING_EVENT;
+        final Bundle extras = new Bundle();
+        if (pkgs != null) extras.putStringArray(Notification.EXTRA_FOREGROUND_APPS, pkgs);
+        n.extras = extras;
+        final StatusBarNotification sbn = makeMockSBN(userid, "android",
+                SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
+                null, n);
+        sbn.getNotification().extras = extras;
+        return sbn;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index 1161987..2e547e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
@@ -87,5 +88,18 @@
         verify(mockContainer).reInflateViews(any(), any());
     }
 
+    @Test
+    public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception {
+        ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
+        row.setSensitive(true, true);
+        row.setHideSensitive(true, false, 0, 0);
+        verify(row).updateShelfIconColor();
+    }
 
+    @Test
+    public void testIconColorShouldBeUpdatedWhenSettingDark() throws Exception {
+        ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
+        row.setDark(true, false, 0);
+        verify(row).updateShelfIconColor();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 55ec307..db6647c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -72,7 +72,7 @@
     NotificationData mNotificationData;
     PowerManager mPowerManager;
     SystemServicesProxy mSystemServicesProxy;
-
+    NotificationPanelView mNotificationPanelView;
     private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
 
     @Before
@@ -85,6 +85,7 @@
         mHeadsUpManager = mock(HeadsUpManager.class);
         mNotificationData = mock(NotificationData.class);
         mSystemServicesProxy = mock(SystemServicesProxy.class);
+        mNotificationPanelView = mock(NotificationPanelView.class);
         IPowerManager powerManagerService = mock(IPowerManager.class);
         HandlerThread handlerThread = new HandlerThread("TestThread");
         handlerThread.start();
@@ -95,7 +96,7 @@
         mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
         mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
                 mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
-                mNotificationData, mPowerManager, mSystemServicesProxy);
+                mNotificationData, mPowerManager, mSystemServicesProxy, mNotificationPanelView);
 
         doAnswer(invocation -> {
             OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
@@ -287,7 +288,7 @@
         public TestableStatusBar(StatusBarKeyguardViewManager man,
                 UnlockMethodCache unlock, KeyguardIndicationController key,
                 NotificationStackScrollLayout stack, HeadsUpManager hum, NotificationData nd,
-                PowerManager pm, SystemServicesProxy ssp) {
+                PowerManager pm, SystemServicesProxy ssp, NotificationPanelView panelView) {
             mStatusBarKeyguardViewManager = man;
             mUnlockMethodCache = unlock;
             mKeyguardIndicationController = key;
@@ -297,6 +298,7 @@
             mUseHeadsUp = true;
             mPowerManager = pm;
             mSystemServicesProxy = ssp;
+            mNotificationPanel = panelView;
         }
 
         @Override
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 980a7d4..073d7b2 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -774,20 +774,29 @@
                 break;
             }
 
-            final AutofillValue currentValue = viewState.getCurrentValue();
-            if (currentValue == null || currentValue.isEmpty()) {
-                if (sDebug) {
-                    Slog.d(TAG, "showSaveLocked(): empty value for required " + id );
+            AutofillValue value = viewState.getCurrentValue();
+            if (value == null || value.isEmpty()) {
+                final AutofillValue initialValue = getValueFromContexts(id);
+                if (initialValue != null) {
+                    if (sDebug) {
+                        Slog.d(TAG, "Value of required field " + id + " didn't change; "
+                                + "using initial value (" + initialValue + ") instead");
+                    }
+                    value = initialValue;
+                } else {
+                    if (sDebug) {
+                        Slog.d(TAG, "showSaveLocked(): empty value for required " + id );
+                    }
+                    allRequiredAreNotEmpty = false;
+                    break;
                 }
-                allRequiredAreNotEmpty = false;
-                break;
             }
             final AutofillValue filledValue = viewState.getAutofilledValue();
 
-            if (!currentValue.equals(filledValue)) {
+            if (!value.equals(filledValue)) {
                 if (sDebug) {
                     Slog.d(TAG, "showSaveLocked(): found a change on required " + id + ": "
-                            + filledValue + " => " + currentValue);
+                            + filledValue + " => " + value);
                 }
                 atLeastOneChanged = true;
             }
@@ -845,6 +854,31 @@
     }
 
     /**
+     * Gets the latest non-empty value for the given id in the autofill contexts.
+     */
+    @Nullable
+    private AutofillValue getValueFromContexts(AutofillId id) {
+        AutofillValue value = null;
+        final int numContexts = mContexts.size();
+        for (int i = 0; i < numContexts; i++) {
+            final FillContext context = mContexts.get(i);
+            // TODO: create a function that gets just one node so it doesn't create an array
+            // unnecessarily
+            final ViewNode[] nodes = context.findViewNodesByAutofillIds(id);
+            if (nodes != null) {
+                AutofillValue candidate = nodes[0].getAutofillValue();
+                if (sDebug) {
+                    Slog.d(TAG, "getValueFromContexts(" + id + ") at " + i + ": " + candidate);
+                }
+                if (candidate != null && !candidate.isEmpty()) {
+                    value = candidate;
+                }
+            }
+        }
+        return value;
+    }
+
+    /**
      * Calls service when user requested save.
      */
     void callSaveLocked() {
@@ -1009,7 +1043,7 @@
                     || action == ACTION_VIEW_ENTERED) {
                 if (sVerbose) Slog.v(TAG, "Creating viewState for " + id + " on " + action);
                 boolean isIgnored = isIgnoredLocked(id);
-                viewState = new ViewState(this, id, value, this,
+                viewState = new ViewState(this, id, this,
                         isIgnored ? ViewState.STATE_IGNORED : ViewState.STATE_INITIAL);
                 mViewStates.put(id, viewState);
                 if (isIgnored) {
@@ -1307,7 +1341,7 @@
         if (viewState != null)  {
             viewState.setState(state);
         } else {
-            viewState = new ViewState(this, id, null, this, state);
+            viewState = new ViewState(this, id, this, state);
             if (sVerbose) {
                 Slog.v(TAG, "Adding autofillable view with id " + id + " and state " + state);
             }
@@ -1370,10 +1404,16 @@
         }
     }
 
+    @Override
+    public String toString() {
+        return "Session: [id=" + id + ", pkg=" + mPackageName + "]";
+    }
+
     void dumpLocked(String prefix, PrintWriter pw) {
         final String prefix2 = prefix + "  ";
         pw.print(prefix); pw.print("id: "); pw.println(id);
         pw.print(prefix); pw.print("uid: "); pw.println(uid);
+        pw.print(prefix); pw.print("mPackagename: "); pw.println(mPackageName);
         pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
         pw.print(prefix); pw.print("mResponses: ");
         if (mResponses == null) {
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index cd8f4a5..51659bb 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -74,16 +74,14 @@
     private final Session mSession;
 
     private FillResponse mResponse;
-    private AutofillValue mInitialValue;
     private AutofillValue mCurrentValue;
     private AutofillValue mAutofilledValue;
     private Rect mVirtualBounds;
     private int mState;
 
-    ViewState(Session session, AutofillId id, AutofillValue value, Listener listener, int state) {
+    ViewState(Session session, AutofillId id, Listener listener, int state) {
         mSession = session;
         this.id = id;
-        mInitialValue = value;
         mListener = listener;
         mState = state;
     }
@@ -118,11 +116,6 @@
     }
 
     @Nullable
-    AutofillValue getInitialValue() {
-        return mInitialValue;
-    }
-
-    @Nullable
     FillResponse getResponse() {
         return mResponse;
     }
@@ -189,8 +182,8 @@
 
     @Override
     public String toString() {
-        return "ViewState: [id=" + id + ", initialValue=" + mInitialValue
-                + ", currentValue=" + mCurrentValue + ", autofilledValue=" + mAutofilledValue
+        return "ViewState: [id=" + id + ", currentValue=" + mCurrentValue
+                + ", autofilledValue=" + mAutofilledValue
                 + ", bounds=" + mVirtualBounds + ", state=" + getStateAsString() + "]";
     }
 
@@ -207,7 +200,6 @@
                 pw.println(mResponse.getRequestId());
             }
         }
-        pw.print(prefix); pw.print("initialValue:" ); pw.println(mInitialValue);
         pw.print(prefix); pw.print("currentValue:" ); pw.println(mCurrentValue);
         pw.print(prefix); pw.print("autofilledValue:" ); pw.println(mAutofilledValue);
         pw.print(prefix); pw.print("virtualBounds:" ); pw.println(mVirtualBounds);
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index c3d55054..8ffe8f5 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -332,6 +332,10 @@
 
     @android.annotation.UiThread
     private void hideSaveUiUiThread(@Nullable AutoFillUiCallback callback) {
+        if (sVerbose) {
+            Slog.v(TAG, "hideSaveUiUiThread(): mSaveUi=" + mSaveUi + ", callback=" + callback
+                    + ", mCallback=" + mCallback);
+        }
         if (mSaveUi != null && (callback == null || callback == mCallback)) {
             mSaveUi.destroy();
             mSaveUi = null;
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d566d3d..e9c98e9 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -398,6 +398,12 @@
             } catch (WindowManager.BadTokenException e) {
                 if (sDebug) Slog.d(TAG, "Filed with with token " + params.token + " gone.");
                 mCallback.onDestroy();
+            } catch (IllegalStateException e) {
+                // WM throws an ISE if mContentView was added twice; this should never happen -
+                // since show() and hide() are always called in the UIThread - but when it does,
+                // it should not crash the system.
+                Slog.e(TAG, "Exception showing window " + params, e);
+                mCallback.onDestroy();
             }
         }
 
@@ -405,10 +411,18 @@
          * Hides the window.
          */
         void hide() {
-            if (mShowing) {
-                mContentView.setOnTouchListener(null);
-                mWm.removeView(mContentView);
-                mShowing = false;
+            try {
+                if (mShowing) {
+                    mContentView.setOnTouchListener(null);
+                    mWm.removeView(mContentView);
+                    mShowing = false;
+                }
+            } catch (IllegalStateException e) {
+                // WM might thrown an ISE when removing the mContentView; this should never
+                // happen - since show() and hide() are always called in the UIThread - but if it
+                // does, it should not crash the system.
+                Slog.e(TAG, "Exception hiding window ", e);
+                mCallback.onDestroy();
             }
         }
 
@@ -489,7 +503,7 @@
                         final String value = item.getValue();
                         // No value, i.e. null, matches any filter
                         if (value == null
-                                || value.toLowerCase().contains(constraintLowerCase)) {
+                                || value.toLowerCase().startsWith(constraintLowerCase)) {
                             filteredItems.add(item);
                         }
                     }
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index d25ffce..491af91 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -17,6 +17,7 @@
 package com.android.server.autofill.ui;
 
 import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sVerbose;
 
 import android.annotation.NonNull;
 import android.app.Dialog;
@@ -63,7 +64,7 @@
 
         @Override
         public void onSave() {
-            if (sDebug) Slog.d(TAG, "onSave(): " + mDone);
+            if (sDebug) Slog.d(TAG, "OneTimeListener.onSave(): " + mDone);
             if (mDone) {
                 return;
             }
@@ -73,7 +74,7 @@
 
         @Override
         public void onCancel(IntentSender listener) {
-            if (sDebug) Slog.d(TAG, "onCancel(): " + mDone);
+            if (sDebug) Slog.d(TAG, "OneTimeListener.onCancel(): " + mDone);
             if (mDone) {
                 return;
             }
@@ -83,7 +84,7 @@
 
         @Override
         public void onDestroy() {
-            if (sDebug) Slog.d(TAG, "onDestroy(): " + mDone);
+            if (sDebug) Slog.d(TAG, "OneTimeListener.onDestroy(): " + mDone);
             if (mDone) {
                 return;
             }
@@ -158,9 +159,8 @@
             subTitleView.setVisibility(View.VISIBLE);
         }
 
-        Slog.i(TAG, "Showing save dialog: " + mTitle);
         if (sDebug) {
-            Slog.d(TAG, "SubTitle: " + mSubTitle);
+            Slog.d(TAG, "on constructor: title=" + mTitle + ", subTitle=" + mSubTitle);
         }
 
         final TextView noButton = view.findViewById(R.id.autofill_save_no);
@@ -169,15 +169,15 @@
         } else {
             noButton.setText(R.string.autofill_save_no);
         }
-        noButton.setOnClickListener((v) -> mListener.onCancel(
-                info.getNegativeActionListener()));
+        View.OnClickListener cancelListener =
+                (v) -> mListener.onCancel(info.getNegativeActionListener());
+        noButton.setOnClickListener(cancelListener);
 
         final View yesButton = view.findViewById(R.id.autofill_save_yes);
         yesButton.setOnClickListener((v) -> mListener.onSave());
 
         final View closeButton = view.findViewById(R.id.autofill_save_close);
-        closeButton.setOnClickListener((v) -> mListener.onCancel(
-                info.getNegativeActionListener()));
+        closeButton.setOnClickListener(cancelListener);
 
         mDialog = new Dialog(context, R.style.Theme_DeviceDefault_Light_Panel);
         mDialog.setContentView(view);
@@ -195,13 +195,16 @@
         params.width = WindowManager.LayoutParams.MATCH_PARENT;
         params.accessibilityTitle = context.getString(R.string.autofill_save_accessibility_title);
 
+        Slog.i(TAG, "Showing save dialog: " + mTitle);
         mDialog.show();
     }
 
     void destroy() {
+        if (sDebug) Slog.d(TAG, "destroy()");
         throwIfDestroyed();
         mListener.onDestroy();
         mHandler.removeCallbacksAndMessages(mListener);
+        if (sVerbose) Slog.v(TAG, "destroy(): dismissing dialog");
         mDialog.dismiss();
         mDestroyed = true;
     }
@@ -212,6 +215,11 @@
         }
     }
 
+    @Override
+    public String toString() {
+        return mTitle == null ? "NO TITLE" : mTitle.toString();
+    }
+
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("title: "); pw.println(mTitle);
         pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle);
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 03e9dd2..16e63b3 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -73,6 +73,7 @@
 
     private final LinkedList<VibrationInfo> mPreviousVibrations;
     private final int mPreviousVibrationsLimit;
+    private final boolean mAllowPriorityVibrationsInLowPowerMode;
     private final boolean mSupportsAmplitudeControl;
     private final int mDefaultVibrationAmplitude;
     private final VibrationEffect[] mFallbackEffects;
@@ -213,6 +214,9 @@
         mDefaultVibrationAmplitude = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_defaultVibrationAmplitude);
 
+        mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode);
+
         mPreviousVibrations = new LinkedList<>();
 
         IntentFilter filter = new IntentFilter();
@@ -456,7 +460,7 @@
     }
 
     private void startVibrationLocked(final Vibration vib) {
-        if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
+        if (!isAllowedToVibrate(vib)) {
             if (DEBUG) {
                 Slog.e(TAG, "Vibrate ignored, low power mode");
             }
@@ -505,6 +509,26 @@
         }
     }
 
+    private boolean isAllowedToVibrate(Vibration vib) {
+        if (!mLowPowerMode) {
+            return true;
+        }
+        if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
+            return true;
+        }
+        if (!mAllowPriorityVibrationsInLowPowerMode) {
+            return false;
+        }
+        if (vib.mUsageHint == AudioAttributes.USAGE_ALARM ||
+            vib.mUsageHint == AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY ||
+            vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST) {
+
+            return true;
+        }
+
+        return false;
+    }
+
     private boolean shouldVibrateForRingtone() {
         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         int ringerMode = audioManager.getRingerModeInternal();
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 36c3f7d..f0b1b3b 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -23,8 +23,10 @@
 import android.accounts.AccountAuthenticatorResponse;
 import android.accounts.AccountManager;
 import android.accounts.AccountManagerInternal;
+import android.accounts.AccountManagerResponse;
 import android.accounts.AuthenticatorDescription;
 import android.accounts.CantAddAccountActivity;
+import android.accounts.ChooseAccountActivity;
 import android.accounts.GrantCredentialsPermissionActivity;
 import android.accounts.IAccountAuthenticator;
 import android.accounts.IAccountAuthenticatorResponse;
@@ -71,6 +73,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
@@ -748,6 +751,11 @@
         }
     }
 
+    private boolean isVisible(int visibility) {
+        return visibility == AccountManager.VISIBILITY_VISIBLE ||
+            visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE;
+    }
+
     /**
      * Updates visibility for given account name and package.
      *
@@ -800,8 +808,10 @@
                 if (notify) {
                     for (Entry<String, Integer> packageToVisibility : packagesToVisibility
                             .entrySet()) {
-                        if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(),
-                                resolveAccountVisibility(account, packageName, accounts))) {
+                        int oldVisibility = packageToVisibility.getValue();
+                        int currentVisibility =
+                            resolveAccountVisibility(account, packageName, accounts);
+                        if (isVisible(oldVisibility) != isVisible(currentVisibility)) {
                             notifyPackage(packageToVisibility.getKey(), accounts);
                         }
                     }
@@ -1178,8 +1188,7 @@
 
                             for (Entry<String, Integer> packageToVisibility :
                                     packagesToVisibility.entrySet()) {
-                                if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(),
-                                        AccountManager.VISIBILITY_NOT_VISIBLE)) {
+                                if (isVisible(packageToVisibility.getValue())) {
                                     notifyPackage(packageToVisibility.getKey(), accounts);
                                 }
                             }
@@ -1215,14 +1224,6 @@
         }
     }
 
-    private boolean shouldNotifyOnVisibilityChange(int oldVisibility, int newVisibility) {
-        boolean oldVisible = (oldVisibility == AccountManager.VISIBILITY_VISIBLE) ||
-            (oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
-        boolean newVisible = (newVisibility == AccountManager.VISIBILITY_VISIBLE) ||
-            (newVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
-        return oldVisible == newVisible;
-    }
-
     private SparseBooleanArray getUidsOfInstalledOrUpdatedPackagesAsUser(int userId) {
         // Get the UIDs of all apps that might have data on the device. We want
         // to preserve user data if the app might otherwise be storing data.
@@ -4042,6 +4043,7 @@
         private volatile int mCurrentAccount = 0;
         private final int mCallingUid;
         private final String mPackageName;
+        private final boolean mIncludeManagedNotVisible;
 
         public GetAccountsByTypeAndFeatureSession(
                 UserAccounts accounts,
@@ -4049,19 +4051,21 @@
                 String type,
                 String[] features,
                 int callingUid,
-                String packageName) {
+                String packageName,
+                boolean includeManagedNotVisible) {
             super(accounts, response, type, false /* expectActivityLaunch */,
                     true /* stripAuthTokenFromResult */, null /* accountName */,
                     false /* authDetailsRequired */);
             mCallingUid = callingUid;
             mFeatures = features;
             mPackageName = packageName;
+            mIncludeManagedNotVisible = includeManagedNotVisible;
         }
 
         @Override
         public void run() throws RemoteException {
             mAccountsOfType = getAccountsFromCache(mAccounts, mAccountType,
-                    mCallingUid, mPackageName, false /* include managed not visible*/);
+                    mCallingUid, mPackageName, mIncludeManagedNotVisible);
             // check whether each account matches the requested features
             mAccountsWithFeatures = new ArrayList<>(mAccountsOfType.length);
             mCurrentAccount = 0;
@@ -4422,10 +4426,120 @@
                 && (type != null && !isAccountManagedByCaller(type, callingUid, userId))) {
                 return EMPTY_ACCOUNT_ARRAY;
         }
+        if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) && type == null) {
+            return getAccountsAsUserForPackage(type, userId,
+                packageName, packageUid, opPackageName, false /* includeUserManagedNotVisible */);
+        }
         return getAccountsAsUserForPackage(type, userId,
                 packageName, packageUid, opPackageName, true /* includeUserManagedNotVisible */);
     }
 
+    private boolean needToStartChooseAccountActivity(Account[] accounts, String callingPackage) {
+        if (accounts.length < 1) return false;
+        if (accounts.length > 1) return true;
+        Account account = accounts[0];
+        UserAccounts userAccounts = getUserAccounts(UserHandle.getCallingUserId());
+        int visibility = resolveAccountVisibility(account, callingPackage, userAccounts);
+        if (visibility == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE) return true;
+        return false;
+    }
+
+    private void startChooseAccountActivityWithAccounts(
+        IAccountManagerResponse response, Account[] accounts) {
+        Intent intent = new Intent(mContext, ChooseAccountActivity.class);
+        intent.putExtra(AccountManager.KEY_ACCOUNTS, accounts);
+        intent.putExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE,
+                new AccountManagerResponse(response));
+
+        mContext.startActivityAsUser(intent, UserHandle.of(UserHandle.getCallingUserId()));
+    }
+
+    private void handleGetAccountsResult(
+        IAccountManagerResponse response,
+        Account[] accounts,
+        String callingPackage) {
+
+        if (needToStartChooseAccountActivity(accounts, callingPackage)) {
+            startChooseAccountActivityWithAccounts(response, accounts);
+            return;
+        }
+        if (accounts.length == 1) {
+            Bundle bundle = new Bundle();
+            bundle.putString(AccountManager.KEY_ACCOUNT_NAME, accounts[0].name);
+            bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, accounts[0].type);
+            onResult(response, bundle);
+            return;
+        }
+        // No qualified account exists, return an empty Bundle.
+        onResult(response, new Bundle());
+    }
+
+    @Override
+    public void getAccountByTypeAndFeatures(
+        IAccountManagerResponse response,
+        String accountType,
+        String[] features,
+        String opPackageName) {
+
+        int callingUid = Binder.getCallingUid();
+        mAppOpsManager.checkPackage(callingUid, opPackageName);
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "getAccount: accountType " + accountType
+                    + ", response " + response
+                    + ", features " + Arrays.toString(features)
+                    + ", caller's uid " + callingUid
+                    + ", pid " + Binder.getCallingPid());
+        }
+        if (response == null) throw new IllegalArgumentException("response is null");
+        if (accountType == null) throw new IllegalArgumentException("accountType is null");
+
+        int userId = UserHandle.getCallingUserId();
+
+        long identityToken = clearCallingIdentity();
+        try {
+            UserAccounts userAccounts = getUserAccounts(userId);
+            if (ArrayUtils.isEmpty(features)) {
+                Account[] accountsWithManagedNotVisible = getAccountsFromCache(
+                    userAccounts, accountType, callingUid, opPackageName,
+                    true /* include managed not visible */);
+                handleGetAccountsResult(
+                    response, accountsWithManagedNotVisible, opPackageName);
+                return;
+            }
+
+            IAccountManagerResponse retrieveAccountsResponse =
+                new IAccountManagerResponse.Stub() {
+                @Override
+                public void onResult(Bundle value) throws RemoteException {
+                    Parcelable[] parcelables = value.getParcelableArray(
+                        AccountManager.KEY_ACCOUNTS);
+                    Account[] accounts = new Account[parcelables.length];
+                    for (int i = 0; i < parcelables.length; i++) {
+                        accounts[i] = (Account) parcelables[i];
+                    }
+                    handleGetAccountsResult(
+                        response, accounts, opPackageName);
+                }
+
+                @Override
+                public void onError(int errorCode, String errorMessage)
+                        throws RemoteException {
+                    // Will not be called in this case.
+                }
+            };
+            new GetAccountsByTypeAndFeatureSession(
+                    userAccounts,
+                    retrieveAccountsResponse,
+                    accountType,
+                    features,
+                    callingUid,
+                    opPackageName,
+                    true /* include managed not visible */).bind();
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
+    }
+
     @Override
     public void getAccountsByFeatures(
             IAccountManagerResponse response,
@@ -4458,6 +4572,7 @@
             }
             return;
         }
+
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts userAccounts = getUserAccounts(userId);
@@ -4475,7 +4590,8 @@
                     type,
                     features,
                     callingUid,
-                    opPackageName).bind();
+                    opPackageName,
+                    false /* include managed not visible */).bind();
         } finally {
             restoreCallingIdentity(identityToken);
         }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2680b425..c417484 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -162,7 +162,7 @@
 
     /**
      * Information about an app that is currently running one or more foreground services.
-     * (This mapps directly to the running apps we show in the notification.)
+     * (This maps directly to the running apps we show in the notification.)
      */
     static final class ActiveForegroundApp {
         String mPackageName;
@@ -813,6 +813,8 @@
             String title;
             String msg;
             String[] pkgs;
+            final long nowElapsed = SystemClock.elapsedRealtime();
+            long oldestStartTime = nowElapsed;
             if (active.size() == 1) {
                 intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                 intent.setData(Uri.fromParts("package", active.get(0).mPackageName, null));
@@ -820,11 +822,13 @@
                         R.string.foreground_service_app_in_background, active.get(0).mLabel);
                 msg = context.getString(R.string.foreground_service_tap_for_details);
                 pkgs = new String[] { active.get(0).mPackageName };
+                oldestStartTime = active.get(0).mStartTime;
             } else {
                 intent = new Intent(Settings.ACTION_FOREGROUND_SERVICES_SETTINGS);
                 pkgs = new String[active.size()];
                 for (int i = 0; i < active.size(); i++) {
                     pkgs[i] = active.get(i).mPackageName;
+                    oldestStartTime = Math.min(oldestStartTime, active.get(i).mStartTime);
                 }
                 intent.putExtra("packages", pkgs);
                 title = context.getString(
@@ -841,9 +845,10 @@
                     new Notification.Builder(context,
                             SystemNotificationChannels.FOREGROUND_SERVICE)
                             .addExtras(notificationBundle)
-                            .setSmallIcon(R.drawable.ic_check_circle_24px)
+                            .setSmallIcon(R.drawable.stat_sys_vitals)
                             .setOngoing(true)
-                            .setShowWhen(false)
+                            .setShowWhen(oldestStartTime < nowElapsed)
+                            .setWhen(System.currentTimeMillis() - (nowElapsed - oldestStartTime))
                             .setColor(context.getColor(
                                     com.android.internal.R.color.system_notification_accent_color))
                             .setContentTitle(title)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f3ecfeb..c958313 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19158,10 +19158,11 @@
                     final Uri data = intent.getData();
                     final String ssp;
                     if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
-                        final ApplicationInfo aInfo =
-                                getPackageManagerInternalLocked().getApplicationInfo(
-                                        ssp,
-                                        userId);
+                        ApplicationInfo aInfo = null;
+                        try {
+                            aInfo = AppGlobals.getPackageManager()
+                                    .getApplicationInfo(ssp, 0 /*flags*/, userId);
+                        } catch (RemoteException ignore) {}
                         if (aInfo == null) {
                             Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
                                     + " ssp=" + ssp + " data=" + data);
@@ -24281,7 +24282,6 @@
     }
 
     void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
-        final PackageManagerInternal packageManager = getPackageManagerInternalLocked();
         final boolean updateFrameworkRes = packagesToUpdate.contains("android");
         for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
             final ProcessRecord app = mLruProcesses.get(i);
@@ -24298,8 +24298,8 @@
                 final String packageName = app.pkgList.keyAt(j);
                 if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
                     try {
-                        final ApplicationInfo ai = packageManager.getApplicationInfo(
-                                packageName, app.userId);
+                        final ApplicationInfo ai = AppGlobals.getPackageManager()
+                                .getApplicationInfo(packageName, 0 /*flags*/, app.userId);
                         if (ai != null) {
                             app.thread.scheduleApplicationInfoChanged(ai);
                         }
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index ea9ff59..8297169 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -16,7 +16,6 @@
 
 package com.android.server.am;
 
-import android.app.ActivityManager;
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.ITaskStackListener;
 import android.app.ActivityManager.TaskDescription;
@@ -31,27 +30,27 @@
 import java.util.ArrayList;
 
 class TaskChangeNotificationController {
-    static final int LOG_STACK_STATE_MSG = 1;
-    static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2;
-    static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3;
-    static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4;
-    static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5;
-    static final int NOTIFY_FORCED_RESIZABLE_MSG = 6;
-    static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7;
-    static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8;
-    static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9;
-    static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10;
-    static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11;
-    static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12;
-    static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
-    static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
-    static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
-    static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
-    static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
-    static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
+    private static final int LOG_STACK_STATE_MSG = 1;
+    private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2;
+    private static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3;
+    private static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4;
+    private static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5;
+    private static final int NOTIFY_FORCED_RESIZABLE_MSG = 6;
+    private static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7;
+    private static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8;
+    private static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9;
+    private static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10;
+    private static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11;
+    private static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12;
+    private static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
+    private static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
+    private static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
+    private static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
+    private static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
+    private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
 
     // Delay in notifying task stack change listeners (in millis)
-    static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
+    private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
 
     private final ActivityManagerService mService;
     private final ActivityStackSupervisor mStackSupervisor;
@@ -242,7 +241,7 @@
         }
     }
 
-    void forAllRemoteListeners(TaskStackConsumer callback, Message message) {
+    private void forAllRemoteListeners(TaskStackConsumer callback, Message message) {
         synchronized (mService) {
             for (int i = mRemoteTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
                 try {
@@ -256,7 +255,7 @@
         }
     }
 
-    void forAllLocalListeners(TaskStackConsumer callback, Message message) {
+    private void forAllLocalListeners(TaskStackConsumer callback, Message message) {
         synchronized (mService) {
             for (int i = mLocalTaskStackListeners.size() - 1; i >= 0; i--) {
                 try {
@@ -329,8 +328,9 @@
 
     void notifyActivityDismissingDockedStack() {
         mHandler.removeMessages(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
-        final Message message = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
-        forAllLocalListeners(mNotifyActivityDismissingDockedStack, message);
+        final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
+        forAllLocalListeners(mNotifyActivityDismissingDockedStack, msg);
+        msg.sendToTarget();
     }
 
     void notifyActivityForcedResizable(int taskId, int reason, String packageName) {
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 1504538..3ca65cd 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1858,7 +1858,7 @@
                     account.account.name, account.userId, account.account.type);
 
             pw.println("=======================================================================");
-            final PrintTable table = new PrintTable(12);
+            final PrintTable table = new PrintTable(13);
             table.set(0, 0,
                     "Authority", // 0
                     "Syncable",  // 1
@@ -1871,7 +1871,8 @@
                     "User",      // 8
                     "Tot",       // 9
                     "Time",      // 10
-                    "Last Sync" // 11
+                    "Last Sync", // 11
+                    "Etc"        // 12
             );
 
             final List<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> sorted =
@@ -1921,6 +1922,7 @@
                     }
                 }
 
+                row1 = row;
                 if (status.lastSuccessTime != 0) {
                     table.set(row1++, 11, SyncStorageEngine.SOURCES[status.lastSuccessSource]
                             + " " + "SUCCESS");
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 9dc317a..e82724d 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -104,6 +104,11 @@
     // Trigger proximity if distance is less than 5 cm.
     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
 
+    // State machine constants for tracking initial brightness ramp skipping when enabled.
+    private static final int RAMP_STATE_SKIP_NONE = 0;
+    private static final int RAMP_STATE_SKIP_INITIAL = 1;
+    private static final int RAMP_STATE_SKIP_AUTOBRIGHT = 2;
+
     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
@@ -239,6 +244,9 @@
     // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
     private int mReportedScreenStateToPolicy;
 
+    // If the last recorded screen state was dozing or not.
+    private boolean mDozing;
+
     // Remembers whether certain kinds of brightness adjustments
     // were recently applied so that we can decide how to transition.
     private boolean mAppliedAutoBrightness;
@@ -249,6 +257,15 @@
     private final int mBrightnessRampRateFast;
     private final int mBrightnessRampRateSlow;
 
+    // Whether or not to skip the initial brightness ramps into STATE_ON.
+    private final boolean mSkipScreenOnBrightnessRamp;
+
+    // A record of state for skipping brightness ramps.
+    private int mSkipRampState = RAMP_STATE_SKIP_NONE;
+
+    // The first autobrightness value set when entering RAMP_STATE_SKIP_INITIAL.
+    private int mInitialAutoBrightness;
+
     // The controller for the automatic brightness level.
     private AutomaticBrightnessController mAutomaticBrightnessController;
 
@@ -312,6 +329,8 @@
                 com.android.internal.R.integer.config_brightness_ramp_rate_fast);
         mBrightnessRampRateSlow = resources.getInteger(
                 com.android.internal.R.integer.config_brightness_ramp_rate_slow);
+        mSkipScreenOnBrightnessRamp = resources.getBoolean(
+                com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
 
         int lightSensorRate = resources.getInteger(
                 com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
@@ -731,8 +750,29 @@
         // Animate the screen brightness when the screen is on or dozing.
         // Skip the animation when the screen is off or suspended or transition to/from VR.
         if (!mPendingScreenOff) {
+            if (mSkipScreenOnBrightnessRamp) {
+
+                if (state == Display.STATE_ON) {
+                    if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
+                        mInitialAutoBrightness = brightness;
+                        mSkipRampState = RAMP_STATE_SKIP_INITIAL;
+                    } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
+                            && mUseSoftwareAutoBrightnessConfig
+                            && brightness != mInitialAutoBrightness) {
+                        mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
+                    } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
+                        mSkipRampState = RAMP_STATE_SKIP_NONE;
+                    }
+                } else {
+                    mSkipRampState = RAMP_STATE_SKIP_NONE;
+                }
+            }
+
             boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
-            if ((state == Display.STATE_ON || state == Display.STATE_DOZE) && !wasOrWillBeInVr) {
+            if ((state == Display.STATE_ON
+                    && mSkipRampState == RAMP_STATE_SKIP_NONE
+                    || state == Display.STATE_DOZE)
+                    && !wasOrWillBeInVr) {
                 animateScreenBrightness(brightness,
                         slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
             } else {
@@ -790,6 +830,9 @@
             mUnfinishedBusiness = false;
             mCallbacks.releaseSuspendBlocker();
         }
+
+        // Record if dozing for future comparison.
+        mDozing = state != Display.STATE_ON;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 9862516..e2fd0ac 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -369,8 +369,8 @@
                     mPendingBacklight = backlight;
 
                     boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
-                    mStateChangeInProgress = stateChanged;
-                    mBacklightChangeInProgress = backlightChanged;
+                    mStateChangeInProgress = stateChanged || mStateChangeInProgress;
+                    mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
 
                     if (!changeInProgress) {
                         mLock.notifyAll();
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 1b984a4..dbccc07 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -86,7 +86,6 @@
     private boolean mCurrentDreamCanDoze;
     private boolean mCurrentDreamIsDozing;
     private boolean mCurrentDreamIsWaking;
-    private Runnable mStopDreamRunnable;
     private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
     private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
 
@@ -350,11 +349,6 @@
 
     private void startDreamLocked(final ComponentName name,
             final boolean isTest, final boolean canDoze, final int userId) {
-        if (mStopDreamRunnable != null) {
-            mHandler.removeCallbacks(mStopDreamRunnable);
-            mStopDreamRunnable = null;
-        }
-
         if (Objects.equal(mCurrentDreamName, name)
                 && mCurrentDreamIsTest == isTest
                 && mCurrentDreamCanDoze == canDoze
@@ -392,15 +386,13 @@
                 mCurrentDreamIsWaking = true;
             }
 
-            mStopDreamRunnable = new Runnable() {
+            mHandler.post(new Runnable() {
                 @Override
                 public void run() {
                     Slog.i(TAG, "Performing gentle wake from dream.");
                     mController.stopDream(immediate);
-                    mStopDreamRunnable = null;
                 }
-            };
-            mHandler.post(mStopDreamRunnable);
+            });
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index ac7b763..d1aecb1 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -936,7 +936,7 @@
         // permissions if the version on the system image does not declare them.
         if (!isDefaultPhoneOrSms && pkg.isUpdatedSystemApp()) {
             PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
-            if (sysPs != null) {
+            if (sysPs != null && sysPs.pkg != null) {
                 if (sysPs.pkg.requestedPermissions.isEmpty()) {
                     return;
                 }
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 29f9f7c..4a5ce12 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -34,6 +34,7 @@
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
@@ -100,7 +101,6 @@
         private static final boolean DEBUG = false;
         private static final String TAG = "LauncherAppsService";
         private final Context mContext;
-        private final PackageManager mPm;
         private final UserManager mUm;
         private final ActivityManagerInternal mActivityManagerInternal;
         private final ShortcutServiceInternal mShortcutServiceInternal;
@@ -113,7 +113,6 @@
 
         public LauncherAppsImpl(Context context) {
             mContext = context;
-            mPm = mContext.getPackageManager();
             mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
             mActivityManagerInternal = Preconditions.checkNotNull(
                     LocalServices.getService(ActivityManagerInternal.class));
@@ -263,15 +262,17 @@
         void verifyCallingPackage(String callingPackage) {
             int packageUid = -1;
             try {
-                packageUid = mPm.getPackageUidAsUser(callingPackage,
+                packageUid = AppGlobals.getPackageManager().getPackageUid(callingPackage,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                                 | PackageManager.MATCH_UNINSTALLED_PACKAGES,
                         UserHandle.getUserId(getCallingUid()));
-            } catch (NameNotFoundException e) {
+            } catch (RemoteException ignore) {
+            }
+            if (packageUid < 0) {
                 Log.e(TAG, "Package not found: " + callingPackage);
             }
-            if (packageUid != Binder.getCallingUid()) {
+            if (packageUid != injectBinderCallingUid()) {
                 throw new SecurityException("Calling package name mismatch");
             }
         }
@@ -315,13 +316,15 @@
                 return null;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                return pm.getActivityInfo(component,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                return pmInt.getActivityInfo(component,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -344,12 +347,15 @@
                 return null;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = injectClearCallingIdentity();
             try {
-                List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(intent,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 return new ParceledListSlice<>(apps);
             } finally {
                 injectRestoreCallingIdentity(ident);
@@ -390,13 +396,15 @@
                 return false;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                PackageInfo info = pm.getPackageInfo(packageName,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                PackageInfo info = pmInt.getPackageInfo(packageName,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 return info != null && info.applicationInfo.enabled;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -414,11 +422,13 @@
                 return null;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                ApplicationInfo info = pm.getApplicationInfo(packageName, flags,
-                        user.getIdentifier());
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                ApplicationInfo info = pmInt.getApplicationInfo(packageName, flags,
+                        callingUid, user.getIdentifier());
                 return info;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -573,13 +583,15 @@
                 return false;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                ActivityInfo info = pm.getActivityInfo(component,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                ActivityInfo info = pmInt.getActivityInfo(component,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 return info != null;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -604,13 +616,15 @@
                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
             launchIntent.setPackage(component.getPackageName());
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                ActivityInfo info = pm.getActivityInfo(component,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                ActivityInfo info = pmInt.getActivityInfo(component,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 if (!info.exported) {
                     throw new SecurityException("Cannot launch non-exported components "
                             + component);
@@ -619,10 +633,10 @@
                 // Check that the component actually has Intent.CATEGORY_LAUCNCHER
                 // as calling startActivityAsUser ignores the category and just
                 // resolves based on the component if present.
-                List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,
+                List<ResolveInfo> apps = pmInt.queryIntentActivities(launchIntent,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 final int size = apps.size();
                 for (int i = 0; i < size; ++i) {
                     ActivityInfo activityInfo = apps.get(i).activityInfo;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 99eda86..e62b107 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2186,12 +2186,12 @@
 
     private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
             String[] grantedPermissions) {
-        SettingBase sb = (SettingBase) pkg.mExtras;
-        if (sb == null) {
+        PackageSetting ps = (PackageSetting) pkg.mExtras;
+        if (ps == null) {
             return;
         }
 
-        PermissionsState permissionsState = sb.getPermissionsState();
+        PermissionsState permissionsState = ps.getPermissionsState();
 
         final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
                 | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -3516,7 +3516,7 @@
      *     and {@code 0}</li>
      * <li>The calling application has the permission
      *     {@link android.Manifest.permission#ACCESS_INSTANT_APPS}</li>
-     * <li>[TODO] The calling application is the default launcher on the
+     * <li>The calling application is the default launcher on the
      *     system partition.</li>
      * </ol>
      */
@@ -3593,13 +3593,14 @@
 
     @Override
     public void checkPackageStartable(String packageName, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             throw new SecurityException("Instant applications don't have access to this method");
         }
         final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
-            if (ps == null) {
+            if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) {
                 throw new SecurityException("Package " + packageName + " was not found!");
             }
 
@@ -3650,22 +3651,27 @@
     @Override
     public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
         return getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
-                flags, userId);
+                flags, Binder.getCallingUid(), userId);
     }
 
     @Override
     public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage,
             int flags, int userId) {
         return getPackageInfoInternal(versionedPackage.getPackageName(),
-                versionedPackage.getVersionCode(), flags, userId);
+                versionedPackage.getVersionCode(), flags, Binder.getCallingUid(), userId);
     }
 
+    /**
+     * Important: The provided filterCallingUid is used exclusively to filter out packages
+     * that can be seen based on user state. It's typically the original caller uid prior
+     * to clearing. Because it can only be provided by trusted code, it's value can be
+     * trusted and will be used as-is; unlike userId which will be validated by this method.
+     */
     private PackageInfo getPackageInfoInternal(String packageName, int versionCode,
-            int flags, int userId) {
+            int flags, int filterCallingUid, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForPackage(flags, userId, packageName);
-        enforceCrossUserPermission(callingUid, userId,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */, "get package info");
 
         // reader
@@ -3677,10 +3683,10 @@
             if (matchFactoryOnly) {
                 final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                 if (ps != null) {
-                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                    if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                         return null;
                     }
-                    if (filterAppAccessLPr(ps, callingUid, userId)) {
+                    if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
                         return null;
                     }
                     return generatePackageInfo(ps, flags, userId);
@@ -3695,10 +3701,10 @@
                 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
             if (p != null) {
                 final PackageSetting ps = (PackageSetting) p.mExtras;
-                if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                     return null;
                 }
-                if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
+                if (ps != null && filterAppAccessLPr(ps, filterCallingUid, userId)) {
                     return null;
                 }
                 return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
@@ -3706,10 +3712,10 @@
             if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps == null) return null;
-                if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                     return null;
                 }
-                if (filterAppAccessLPr(ps, callingUid, userId)) {
+                if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
                     return null;
                 }
                 return generatePackageInfo(ps, flags, userId);
@@ -3868,15 +3874,26 @@
 
     @Override
     public String[] currentToCanonicalPackageNames(String[] names) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return names;
         }
-        String[] out = new String[names.length];
+        final String[] out = new String[names.length];
         // reader
         synchronized (mPackages) {
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
             for (int i=names.length-1; i>=0; i--) {
-                PackageSetting ps = mSettings.mPackages.get(names[i]);
-                out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
+                final PackageSetting ps = mSettings.mPackages.get(names[i]);
+                boolean translateName = false;
+                if (ps != null && ps.realName != null) {
+                    final boolean targetIsInstantApp = ps.getInstantApp(callingUserId);
+                    translateName = !targetIsInstantApp
+                            || canViewInstantApps
+                            || mInstantAppRegistry.isInstantAccessGranted(callingUserId,
+                                    UserHandle.getAppId(callingUid), ps.appId);
+                }
+                out[i] = translateName ? ps.realName : names[i];
             }
         }
         return out;
@@ -3884,15 +3901,28 @@
 
     @Override
     public String[] canonicalToCurrentPackageNames(String[] names) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return names;
         }
-        String[] out = new String[names.length];
+        final String[] out = new String[names.length];
         // reader
         synchronized (mPackages) {
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
             for (int i=names.length-1; i>=0; i--) {
-                String cur = mSettings.getRenamedPackageLPr(names[i]);
-                out[i] = cur != null ? cur : names[i];
+                final String cur = mSettings.getRenamedPackageLPr(names[i]);
+                boolean translateName = false;
+                if (cur != null) {
+                    final PackageSetting ps = mSettings.mPackages.get(names[i]);
+                    final boolean targetIsInstantApp =
+                            ps != null && ps.getInstantApp(callingUserId);
+                    translateName = !targetIsInstantApp
+                            || canViewInstantApps
+                            || mInstantAppRegistry.isInstantAccessGranted(callingUserId,
+                                    UserHandle.getAppId(callingUid), ps.appId);
+                }
+                out[i] = translateName ? cur : names[i];
             }
         }
         return out;
@@ -4046,14 +4076,14 @@
     }
 
     private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
-            int uid, int userId) {
+            int filterCallingUid, int userId) {
         if (!sUserManager.exists(userId)) return null;
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps != null) {
-            if (filterSharedLibPackageLPr(ps, uid, userId, flags)) {
+            if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                 return null;
             }
-            if (filterAppAccessLPr(ps, uid, userId)) {
+            if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
                 return null;
             }
             if (ps.pkg == null) {
@@ -4076,6 +4106,17 @@
 
     @Override
     public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
+        return getApplicationInfoInternal(packageName, flags, Binder.getCallingUid(), userId);
+    }
+
+    /**
+     * Important: The provided filterCallingUid is used exclusively to filter out applications
+     * that can be seen based on user state. It's typically the original caller uid prior
+     * to clearing. Because it can only be provided by trusted code, it's value can be
+     * trusted and will be used as-is; unlike userId which will be validated by this method.
+     */
+    private ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
+            int filterCallingUid, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForApplication(flags, userId, packageName);
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -4094,10 +4135,10 @@
             if (p != null) {
                 PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps == null) return null;
-                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                     return null;
                 }
-                if (filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+                if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
                     return null;
                 }
                 // Note: isEnabledLP() does not apply here - always return info
@@ -4115,7 +4156,7 @@
             if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
                 // Already generates the external package name
                 return generateApplicationInfoFromSettingsLPw(packageName,
-                        Binder.getCallingUid(), flags, userId);
+                        flags, filterCallingUid, userId);
             }
         }
         return null;
@@ -4545,10 +4586,20 @@
 
     @Override
     public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+        return getActivityInfoInternal(component, flags, Binder.getCallingUid(), userId);
+    }
+
+    /**
+     * Important: The provided filterCallingUid is used exclusively to filter out activities
+     * that can be seen based on user state. It's typically the original caller uid prior
+     * to clearing. Because it can only be provided by trusted code, it's value can be
+     * trusted and will be used as-is; unlike userId which will be validated by this method.
+     */
+    private ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
+            int filterCallingUid, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(callingUid, userId,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */, "get activity info");
         synchronized (mPackages) {
             PackageParser.Activity a = mActivities.mActivities.get(component);
@@ -4557,7 +4608,7 @@
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
-                if (filterAppAccessLPr(ps, callingUid, component, TYPE_ACTIVITY, userId)) {
+                if (filterAppAccessLPr(ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) {
                     return null;
                 }
                 return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
@@ -4853,9 +4904,13 @@
         }
     }
 
-    private void updateSequenceNumberLP(String packageName, int[] userList) {
+    private void updateSequenceNumberLP(PackageSetting pkgSetting, int[] userList) {
         for (int i = userList.length - 1; i >= 0; --i) {
             final int userId = userList[i];
+            // don't add instant app to the list of updates
+            if (pkgSetting.getInstantApp(userId)) {
+                continue;
+            }
             SparseArray<String> changedPackages = mChangedPackages.get(userId);
             if (changedPackages == null) {
                 changedPackages = new SparseArray<>();
@@ -4866,12 +4921,12 @@
                 sequenceNumbers = new HashMap<>();
                 mChangedPackagesSequenceNumbers.put(userId, sequenceNumbers);
             }
-            final Integer sequenceNumber = sequenceNumbers.get(packageName);
+            final Integer sequenceNumber = sequenceNumbers.get(pkgSetting.name);
             if (sequenceNumber != null) {
                 changedPackages.remove(sequenceNumber);
             }
-            changedPackages.put(mChangedPackagesSequenceNumber, packageName);
-            sequenceNumbers.put(packageName, mChangedPackagesSequenceNumber);
+            changedPackages.put(mChangedPackagesSequenceNumber, pkgSetting.name);
+            sequenceNumbers.put(pkgSetting.name, mChangedPackagesSequenceNumber);
         }
         mChangedPackagesSequenceNumber++;
     }
@@ -5302,28 +5357,33 @@
             Log.e(TAG, "No such user:" + userId);
             return;
         }
+        final int callingUid = Binder.getCallingUid();
 
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
                 "grantRuntimePermission");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "grantRuntimePermission");
 
         final int uid;
-        final SettingBase sb;
+        final PackageSetting ps;
 
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
             if (pkg == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
-
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 throw new IllegalArgumentException("Unknown permission: " + name);
             }
+            ps = (PackageSetting) pkg.mExtras;
+            if (ps == null
+                    || filterAppAccessLPr(ps, callingUid, userId)) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
 
             enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp);
 
@@ -5338,12 +5398,8 @@
             }
 
             uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
-            sb = (SettingBase) pkg.mExtras;
-            if (sb == null) {
-                throw new IllegalArgumentException("Unknown package: " + packageName);
-            }
 
-            final PermissionsState permissionsState = sb.getPermissionsState();
+            final PermissionsState permissionsState = ps.getPermissionsState();
 
             final int flags = permissionsState.getPermissionFlags(name, userId);
             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
@@ -5365,7 +5421,6 @@
                 return;
             }
 
-            final PackageSetting ps = mSettings.mPackages.get(packageName);
             if (ps.getInstantApp(userId) && !bp.isInstant()) {
                 throw new SecurityException("Cannot grant non-ephemeral permission"
                         + name + " for package " + packageName);
@@ -5449,7 +5504,11 @@
             if (pkg == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
-
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (ps == null
+                    || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 throw new IllegalArgumentException("Unknown permission: " + name);
@@ -5467,12 +5526,7 @@
                 return;
             }
 
-            SettingBase sb = (SettingBase) pkg.mExtras;
-            if (sb == null) {
-                throw new IllegalArgumentException("Unknown package: " + packageName);
-            }
-
-            final PermissionsState permissionsState = sb.getPermissionsState();
+            final PermissionsState permissionsState = ps.getPermissionsState();
 
             final int flags = permissionsState.getPermissionFlags(name, userId);
             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
@@ -5611,7 +5665,8 @@
 
         enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "getPermissionFlags");
 
@@ -5620,18 +5675,16 @@
             if (pkg == null) {
                 return 0;
             }
-
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 return 0;
             }
-
-            SettingBase sb = (SettingBase) pkg.mExtras;
-            if (sb == null) {
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (ps == null
+                    || filterAppAccessLPr(ps, callingUid, userId)) {
                 return 0;
             }
-
-            PermissionsState permissionsState = sb.getPermissionsState();
+            PermissionsState permissionsState = ps.getPermissionsState();
             return permissionsState.getPermissionFlags(name, userId);
         }
     }
@@ -5645,7 +5698,8 @@
 
         enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "updatePermissionFlags");
 
@@ -5663,18 +5717,18 @@
             if (pkg == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (ps == null
+                    || filterAppAccessLPr(ps, callingUid, userId)) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
 
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 throw new IllegalArgumentException("Unknown permission: " + name);
             }
 
-            SettingBase sb = (SettingBase) pkg.mExtras;
-            if (sb == null) {
-                throw new IllegalArgumentException("Unknown package: " + packageName);
-            }
-
-            PermissionsState permissionsState = sb.getPermissionsState();
+            PermissionsState permissionsState = ps.getPermissionsState();
 
             boolean hadState = permissionsState.getRuntimePermissionState(name, userId) != null;
 
@@ -5718,11 +5772,11 @@
             final int packageCount = mPackages.size();
             for (int pkgIndex = 0; pkgIndex < packageCount; pkgIndex++) {
                 final PackageParser.Package pkg = mPackages.valueAt(pkgIndex);
-                SettingBase sb = (SettingBase) pkg.mExtras;
-                if (sb == null) {
+                final PackageSetting ps = (PackageSetting) pkg.mExtras;
+                if (ps == null) {
                     continue;
                 }
-                PermissionsState permissionsState = sb.getPermissionsState();
+                PermissionsState permissionsState = ps.getPermissionsState();
                 changed |= permissionsState.updatePermissionFlagsForAllPermissions(
                         userId, flagMask, flagValues);
             }
@@ -6171,7 +6225,8 @@
 
     @Override
     public int getFlagsForUid(int uid) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return 0;
         }
         synchronized (mPackages) {
@@ -6181,6 +6236,9 @@
                 return sus.pkgFlags;
             } else if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
+                if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                    return 0;
+                }
                 return ps.pkgFlags;
             }
         }
@@ -6189,7 +6247,8 @@
 
     @Override
     public int getPrivateFlagsForUid(int uid) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return 0;
         }
         synchronized (mPackages) {
@@ -6199,6 +6258,9 @@
                 return sus.pkgPrivateFlags;
             } else if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
+                if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                    return 0;
+                }
                 return ps.pkgPrivateFlags;
             }
         }
@@ -6264,7 +6326,7 @@
 
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
             final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
-                    flags, userId, resolveForStart);
+                    flags, callingUid, userId, resolveForStart);
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             final ResolveInfo bestChoice =
@@ -6808,15 +6870,16 @@
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
-        return queryIntentActivitiesInternal(intent, resolvedType, flags, userId, false);
+        return queryIntentActivitiesInternal(
+                intent, resolvedType, flags, Binder.getCallingUid(), userId, false);
     }
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
-            String resolvedType, int flags, int userId, boolean resolveForStart) {
+            String resolvedType, int flags, int filterCallingUid, int userId,
+            boolean resolveForStart) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        final int callingUid = Binder.getCallingUid();
-        final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        enforceCrossUserPermission(callingUid, userId,
+        final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */,
                 "query intent activities");
         final String pkgName = intent.getPackage();
@@ -6828,7 +6891,7 @@
             }
         }
 
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid, resolveForStart,
+        flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart,
                 comp != null || pkgName != null /*onlyExposedExplicitly*/);
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
@@ -8048,13 +8111,14 @@
 
     @Override
     public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return ParceledListSlice.emptyList();
         }
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForPackage(flags, userId, null);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "get installed packages");
 
@@ -8064,9 +8128,12 @@
             if (listUninstalled) {
                 list = new ArrayList<>(mSettings.mPackages.size());
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
                         continue;
                     }
+                    if (filterAppAccessLPr(ps, callingUid, userId)) {
+                        return null;
+                    }
                     final PackageInfo pi = generatePackageInfo(ps, flags, userId);
                     if (pi != null) {
                         list.add(pi);
@@ -8075,10 +8142,13 @@
             } else {
                 list = new ArrayList<>(mPackages.size());
                 for (PackageParser.Package p : mPackages.values()) {
-                    if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
-                            Binder.getCallingUid(), userId, flags)) {
+                    final PackageSetting ps = (PackageSetting) p.mExtras;
+                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
                         continue;
                     }
+                    if (filterAppAccessLPr(ps, callingUid, userId)) {
+                        return null;
+                    }
                     final PackageInfo pi = generatePackageInfo((PackageSetting)
                             p.mExtras, flags, userId);
                     if (pi != null) {
@@ -8165,7 +8235,8 @@
 
     @Override
     public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return ParceledListSlice.emptyList();
         }
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -8184,9 +8255,12 @@
                         effectiveFlags |= PackageManager.MATCH_ANY_USER;
                     }
                     if (ps.pkg != null) {
-                        if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                        if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
                             continue;
                         }
+                        if (filterAppAccessLPr(ps, callingUid, userId)) {
+                            return null;
+                        }
                         ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
                                 ps.readUserState(userId), userId);
                         if (ai != null) {
@@ -8197,7 +8271,7 @@
                         // Shared lib filtering done in generateApplicationInfoFromSettingsLPw
                         // and already converts to externally visible package name
                         ai = generateApplicationInfoFromSettingsLPw(ps.name,
-                                Binder.getCallingUid(), effectiveFlags, userId);
+                                callingUid, effectiveFlags, userId);
                     }
                     if (ai != null) {
                         list.add(ai);
@@ -8211,6 +8285,9 @@
                         if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                             continue;
                         }
+                        if (filterAppAccessLPr(ps, callingUid, userId)) {
+                            return null;
+                        }
                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
                                 ps.readUserState(userId), userId);
                         if (ai != null) {
@@ -9348,6 +9425,11 @@
     @Override
     public boolean performDexOpt(String packageName,
             boolean checkProfiles, int compileReason, boolean force) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return false;
+        }
         return performDexOptWithStatus(packageName, checkProfiles, compileReason, force) !=
                 PackageDexOptimizer.DEX_OPT_FAILED;
     }
@@ -9369,6 +9451,8 @@
             boolean checkProfiles, String targetCompilerFilter, boolean force) {
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return false;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return false;
         }
         int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
                 targetCompilerFilter, force);
@@ -9465,6 +9549,8 @@
             boolean force) {
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return false;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return false;
         }
         mDexManager.reconcileSecondaryDexFiles(packageName);
         return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force);
@@ -9484,6 +9570,8 @@
     public void reconcileSecondaryDexFiles(String packageName) {
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return;
         }
         mDexManager.reconcileSecondaryDexFiles(packageName);
     }
@@ -14261,8 +14349,8 @@
             int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
         PackageSetting pkgSetting;
-        final int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "setApplicationHiddenSetting for user " + userId);
 
@@ -14281,6 +14369,9 @@
                 if (pkgSetting == null) {
                     return false;
                 }
+                if (filterAppAccessLPr(pkgSetting, callingUid, userId)) {
+                    return false;
+                }
                 // Do not allow "android" is being disabled
                 if ("android".equals(packageName)) {
                     Slog.w(TAG, "Cannot hide package: android");
@@ -14297,7 +14388,7 @@
                     return false;
                 }
                 // Only allow protected packages to hide themselves.
-                if (hidden && !UserHandle.isSameApp(uid, pkgSetting.appId)
+                if (hidden && !UserHandle.isSameApp(callingUid, pkgSetting.appId)
                         && mProtectedPackages.isPackageStateProtected(userId, packageName)) {
                     Slog.w(TAG, "Not hiding protected package: " + packageName);
                     return false;
@@ -14360,19 +14451,23 @@
     @Override
     public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "getApplicationHidden for user " + userId);
-        PackageSetting pkgSetting;
+        PackageSetting ps;
         long callingId = Binder.clearCallingIdentity();
         try {
             // writer
             synchronized (mPackages) {
-                pkgSetting = mSettings.mPackages.get(packageName);
-                if (pkgSetting == null) {
+                ps = mSettings.mPackages.get(packageName);
+                if (ps == null) {
                     return true;
                 }
-                return pkgSetting.getHidden(userId);
+                if (filterAppAccessLPr(ps, callingUid, userId)) {
+                    return true;
+                }
+                return ps.getHidden(userId);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -14388,8 +14483,8 @@
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
                 null);
         PackageSetting pkgSetting;
-        final int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "installExistingPackage for user " + userId);
         if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
@@ -14410,6 +14505,20 @@
                 if (pkgSetting == null) {
                     return PackageManager.INSTALL_FAILED_INVALID_URI;
                 }
+                if (!canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) {
+                    // only allow the existing package to be used if it's installed as a full
+                    // application for at least one user
+                    boolean installAllowed = false;
+                    for (int checkUserId : sUserManager.getUserIds()) {
+                        installAllowed = !pkgSetting.getInstantApp(checkUserId);
+                        if (installAllowed) {
+                            break;
+                        }
+                    }
+                    if (!installAllowed) {
+                        return PackageManager.INSTALL_FAILED_INVALID_URI;
+                    }
+                }
                 if (!pkgSetting.getInstalled(userId)) {
                     pkgSetting.setInstalled(true, userId);
                     pkgSetting.setHidden(false, userId);
@@ -14433,7 +14542,7 @@
                 }
                 sendPackageAddedForUser(packageName, pkgSetting, userId);
                 synchronized (mPackages) {
-                    updateSequenceNumberLP(packageName, new int[]{ userId });
+                    updateSequenceNumberLP(pkgSetting, new int[]{ userId });
                 }
             }
         } finally {
@@ -14479,7 +14588,8 @@
     public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
             int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "setPackagesSuspended for user " + userId);
 
@@ -14500,7 +14610,8 @@
                 final int appId;
                 synchronized (mPackages) {
                     final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
-                    if (pkgSetting == null) {
+                    if (pkgSetting == null
+                            || filterAppAccessLPr(pkgSetting, callingUid, userId)) {
                         Slog.w(TAG, "Could not find package setting for package \"" + packageName
                                 + "\". Skipping suspending/un-suspending.");
                         unactionedPackages.add(packageName);
@@ -14824,7 +14935,7 @@
      *
      * @return true if verification should be performed
      */
-    private boolean isVerificationEnabled(int userId, int installFlags) {
+    private boolean isVerificationEnabled(int userId, int installFlags, int installerUid) {
         if (!DEFAULT_VERIFY_ENABLE) {
             return false;
         }
@@ -14845,6 +14956,23 @@
                     android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
                 return false;
             }
+        } else {
+            // only when not installed from ADB, skip verification for instant apps when
+            // the installer and verifier are the same.
+            if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
+                if (mInstantAppInstallerActivity != null
+                        && mInstantAppInstallerActivity.packageName.equals(
+                                mRequiredVerifierPackage)) {
+                    try {
+                        mContext.getSystemService(AppOpsManager.class)
+                                .checkPackage(installerUid, mRequiredVerifierPackage);
+                        if (DEBUG_VERIFY) {
+                            Slog.i(TAG, "disable verification for instant app");
+                        }
+                        return false;
+                    } catch (SecurityException ignore) { }
+                }
+            }
         }
 
         if (ensureVerifyAppsEnabled) {
@@ -14872,10 +15000,16 @@
 
     @Override
     public int getIntentVerificationStatus(String packageName, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
         }
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps == null
+                    || filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+            }
             return mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
         }
     }
@@ -14887,6 +15021,10 @@
 
         boolean result = false;
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+                return false;
+            }
             result = mSettings.updateIntentFilterVerificationStatusLPw(packageName, status, userId);
         }
         if (result) {
@@ -14898,10 +15036,15 @@
     @Override
     public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications(
             String packageName) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return ParceledListSlice.emptyList();
         }
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return ParceledListSlice.emptyList();
+            }
             return new ParceledListSlice<>(mSettings.getIntentFilterVerificationsLPr(packageName));
         }
     }
@@ -14982,7 +15125,9 @@
         // writer
         synchronized (mPackages) {
             PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
-            if (targetPackageSetting == null) {
+            if (targetPackageSetting == null
+                    || filterAppAccessLPr(
+                            targetPackageSetting, callingUid, UserHandle.getUserId(callingUid))) {
                 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
             }
 
@@ -15063,7 +15208,9 @@
             if (ps == null) {
                 throw new IllegalArgumentException("Unknown target package " + packageName);
             }
-
+            if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+                throw new IllegalArgumentException("Unknown target package " + packageName);
+            }
             if (!Objects.equals(callerPackageName, ps.installerPackageName)) {
                 throw new IllegalArgumentException("Calling package " + callerPackageName
                         + " is not installer for " + packageName);
@@ -15668,8 +15815,11 @@
                 final int requiredUid = mRequiredVerifierPackage == null ? -1
                         : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
                                 verifierUser.getIdentifier());
+                final int installerUid =
+                        verificationInfo == null ? -1 : verificationInfo.installerUid;
                 if (!origin.existing && requiredUid != -1
-                        && isVerificationEnabled(verifierUser.getIdentifier(), installFlags)) {
+                        && isVerificationEnabled(
+                                verifierUser.getIdentifier(), installFlags, installerUid)) {
                     final Intent verification = new Intent(
                             Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
                     verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -17067,12 +17217,15 @@
 
     @Override
     public List<String> getPreviousCodePaths(String packageName) {
+        final int callingUid = Binder.getCallingUid();
         final List<String> result = new ArrayList<>();
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        if (getInstantAppPackageName(callingUid) != null) {
             return result;
         }
         final PackageSetting ps = mSettings.mPackages.get(packageName);
-        if (ps != null && ps.oldCodePaths != null) {
+        if (ps != null
+                && ps.oldCodePaths != null
+                && !filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
             result.addAll(ps.oldCodePaths);
         }
         return result;
@@ -18078,7 +18231,7 @@
             }
 
             if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                updateSequenceNumberLP(pkgName, res.newUsers);
+                updateSequenceNumberLP(ps, res.newUsers);
                 updateInstantAppInstallerLocked(pkgName);
             }
         }
@@ -18301,8 +18454,10 @@
     @Override
     public void deletePackageVersioned(VersionedPackage versionedPackage,
             final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
+        final int callingUid = Binder.getCallingUid();
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_PACKAGES, null);
+        final boolean canViewInstantApps = canViewInstantApps(callingUid, userId);
         Preconditions.checkNotNull(versionedPackage);
         Preconditions.checkNotNull(observer);
         Preconditions.checkArgumentInRange(versionedPackage.getVersionCode(),
@@ -18367,33 +18522,45 @@
             public void run() {
                 mHandler.removeCallbacks(this);
                 int returnCode;
-                if (!deleteAllUsers) {
-                    returnCode = deletePackageX(internalPackageName, versionCode,
-                            userId, deleteFlags);
-                } else {
-                    int[] blockUninstallUserIds = getBlockUninstallForUsers(
-                            internalPackageName, users);
-                    // If nobody is blocking uninstall, proceed with delete for all users
-                    if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+                final PackageSetting ps = mSettings.mPackages.get(internalPackageName);
+                boolean doDeletePackage = true;
+                if (ps != null) {
+                    final boolean targetIsInstantApp =
+                            ps.getInstantApp(UserHandle.getUserId(callingUid));
+                    doDeletePackage = !targetIsInstantApp
+                            || canViewInstantApps;
+                }
+                if (doDeletePackage) {
+                    if (!deleteAllUsers) {
                         returnCode = deletePackageX(internalPackageName, versionCode,
                                 userId, deleteFlags);
                     } else {
-                        // Otherwise uninstall individually for users with blockUninstalls=false
-                        final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
-                        for (int userId : users) {
-                            if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
-                                returnCode = deletePackageX(internalPackageName, versionCode,
-                                        userId, userFlags);
-                                if (returnCode != PackageManager.DELETE_SUCCEEDED) {
-                                    Slog.w(TAG, "Package delete failed for user " + userId
-                                            + ", returnCode " + returnCode);
+                        int[] blockUninstallUserIds = getBlockUninstallForUsers(
+                                internalPackageName, users);
+                        // If nobody is blocking uninstall, proceed with delete for all users
+                        if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+                            returnCode = deletePackageX(internalPackageName, versionCode,
+                                    userId, deleteFlags);
+                        } else {
+                            // Otherwise uninstall individually for users with blockUninstalls=false
+                            final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
+                            for (int userId : users) {
+                                if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
+                                    returnCode = deletePackageX(internalPackageName, versionCode,
+                                            userId, userFlags);
+                                    if (returnCode != PackageManager.DELETE_SUCCEEDED) {
+                                        Slog.w(TAG, "Package delete failed for user " + userId
+                                                + ", returnCode " + returnCode);
+                                    }
                                 }
                             }
+                            // The app has only been marked uninstalled for certain users.
+                            // We still need to report that delete was blocked
+                            returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
                         }
-                        // The app has only been marked uninstalled for certain users.
-                        // We still need to report that delete was blocked
-                        returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
                     }
+                } else {
+                    returnCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
                 }
                 try {
                     observer.onPackageDeleted(packageName, returnCode, null);
@@ -18664,7 +18831,7 @@
                     if (pkg != null) {
                         mInstantAppRegistry.onPackageUninstalledLPw(pkg, info.removedUsers);
                     }
-                    updateSequenceNumberLP(packageName, info.removedUsers);
+                    updateSequenceNumberLP(uninstalledPs, info.removedUsers);
                     updateInstantAppInstallerLocked(packageName);
                 }
             }
@@ -19195,6 +19362,10 @@
     @Override
     public boolean getBlockUninstallForUser(String packageName, int userId) {
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps == null || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+                return true;
+            }
             return mSettings.getBlockUninstallLPr(userId, packageName);
         }
     }
@@ -19544,9 +19715,14 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */, "clear application data");
 
+        final PackageSetting ps = mSettings.getPackageLPr(packageName);
+        if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
+            return;
+        }
         if (mProtectedPackages.isPackageDataProtected(userId, packageName)) {
             throw new SecurityException("Cannot clear data for a protected package: "
                     + packageName);
@@ -19804,11 +19980,14 @@
     @Override
     public void deleteApplicationCacheFilesAsUser(final String packageName, final int userId,
             final IPackageDataObserver observer) {
+        final int callingUid = Binder.getCallingUid();
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_CACHE_FILES, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 /* requireFullPermission= */ true, /* checkShell= */ false,
                 "delete application cache files");
+        final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_INSTANT_APPS);
 
         final PackageParser.Package pkg;
         synchronized (mPackages) {
@@ -19818,15 +19997,25 @@
         // Queue up an async operation since the package deletion may take a little while.
         mHandler.post(new Runnable() {
             public void run() {
-                synchronized (mInstallLock) {
-                    final int flags = StorageManager.FLAG_STORAGE_DE
-                            | StorageManager.FLAG_STORAGE_CE;
-                    // We're only clearing cache files, so we don't care if the
-                    // app is unfrozen and still able to run
-                    clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
-                    clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+                final PackageSetting ps = (PackageSetting) pkg.mExtras;
+                boolean doClearData = true;
+                if (ps != null) {
+                    final boolean targetIsInstantApp =
+                            ps.getInstantApp(UserHandle.getUserId(callingUid));
+                    doClearData = !targetIsInstantApp
+                            || hasAccessInstantApps == PackageManager.PERMISSION_GRANTED;
                 }
-                clearExternalStorageDataSync(packageName, userId, false);
+                if (doClearData) {
+                    synchronized (mInstallLock) {
+                        final int flags = StorageManager.FLAG_STORAGE_DE
+                                | StorageManager.FLAG_STORAGE_CE;
+                        // We're only clearing cache files, so we don't care if the
+                        // app is unfrozen and still able to run
+                        clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
+                        clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+                    }
+                    clearExternalStorageDataSync(packageName, userId, false);
+                }
                 if (observer != null) {
                     try {
                         observer.onRemoveCompleted(packageName, true);
@@ -20076,7 +20265,11 @@
                             android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
                 }
             }
-
+            final PackageSetting ps = mSettings.getPackageLPr(packageName);
+            if (ps != null
+                    && filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return;
+            }
             int user = UserHandle.getCallingUserId();
             if (clearPackagePreferredActivitiesLPw(packageName, user)) {
                 scheduleWritePackageRestrictionsLocked(user);
@@ -20726,7 +20919,7 @@
     public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage) {
         mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
-        int callingUid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
         enforceOwnerRights(ownerPackage, callingUid);
         enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
         synchronized (mPackages) {
@@ -20749,7 +20942,7 @@
         if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
             return;
         }
-        int callingUserId = UserHandle.getUserId(callingUid);
+        final int callingUserId = UserHandle.getUserId(callingUid);
         PackageInfo pi = getPackageInfo(pkg, 0, callingUserId);
         if (pi == null) {
             throw new IllegalArgumentException("Unknown package " + pkg + " on user "
@@ -20994,7 +21187,8 @@
         // Limit who can change which apps
         if (!UserHandle.isSameApp(callingUid, pkgSetting.appId)) {
             // Don't allow apps that don't have permission to modify other apps
-            if (!allowedByPermission) {
+            if (!allowedByPermission
+                    || filterAppAccessLPr(pkgSetting, callingUid, userId)) {
                 throw new SecurityException(
                         "Attempt to change component state; "
                         + "pid=" + Binder.getCallingPid()
@@ -21081,7 +21275,7 @@
                 }
             }
             scheduleWritePackageRestrictionsLocked(userId);
-            updateSequenceNumberLP(packageName, new int[] { userId });
+            updateSequenceNumberLP(pkgSetting, new int[] { userId });
             final long callingId = Binder.clearCallingIdentity();
             try {
                 updateInstantAppInstallerLocked(packageName);
@@ -21178,8 +21372,10 @@
                 true /* requireFullPermission */, true /* checkShell */, "stop package");
         // writer
         synchronized (mPackages) {
-            if (mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
-                    allowedByPermission, callingUid, userId)) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (!filterAppAccessLPr(ps, callingUid, userId)
+                    && mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
+                            allowedByPermission, callingUid, userId)) {
                 scheduleWritePackageRestrictionsLocked(userId);
             }
         }
@@ -21187,11 +21383,16 @@
 
     @Override
     public String getInstallerPackageName(String packageName) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return null;
         }
         // reader
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return null;
+            }
             return mSettings.getInstallerPackageNameLPr(packageName);
         }
     }
@@ -23385,13 +23586,14 @@
     public int movePackage(final String packageName, final String volumeUuid) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
 
-        final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
+        final int callingUid = Binder.getCallingUid();
+        final UserHandle user = new UserHandle(UserHandle.getUserId(callingUid));
         final int moveId = mNextMoveId.getAndIncrement();
         mHandler.post(new Runnable() {
             @Override
             public void run() {
                 try {
-                    movePackageInternal(packageName, volumeUuid, moveId, user);
+                    movePackageInternal(packageName, volumeUuid, moveId, callingUid, user);
                 } catch (PackageManagerException e) {
                     Slog.w(TAG, "Failed to move " + packageName, e);
                     mMoveCallbacks.notifyStatusChanged(moveId,
@@ -23403,7 +23605,8 @@
     }
 
     private void movePackageInternal(final String packageName, final String volumeUuid,
-            final int moveId, UserHandle user) throws PackageManagerException {
+            final int moveId, final int callingUid, UserHandle user)
+                    throws PackageManagerException {
         final StorageManager storage = mContext.getSystemService(StorageManager.class);
         final PackageManager pm = mContext.getPackageManager();
 
@@ -23423,10 +23626,11 @@
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
             final PackageSetting ps = mSettings.mPackages.get(packageName);
-            if (pkg == null || ps == null) {
+            if (pkg == null
+                    || ps == null
+                    || filterAppAccessLPr(ps, callingUid, user.getIdentifier())) {
                 throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
             }
-
             if (pkg.applicationInfo.isSystemApp()) {
                 throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE,
                         "Cannot move system application");
@@ -23896,6 +24100,11 @@
                 Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+                Slog.w(TAG, "KeySet requested for filtered package: " + packageName);
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
             KeySetManagerService ksms = mSettings.mKeySetManagerService;
             return new KeySet(ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias));
         }
@@ -23932,7 +24141,8 @@
 
     @Override
     public boolean isPackageSignedByKeySet(String packageName, KeySet ks) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return false;
         }
         if (packageName == null || ks == null) {
@@ -23940,7 +24150,9 @@
         }
         synchronized(mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
-            if (pkg == null) {
+            if (pkg == null
+                    || filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid,
+                            UserHandle.getUserId(callingUid))) {
                 Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -23955,7 +24167,8 @@
 
     @Override
     public boolean isPackageSignedByKeySetExactly(String packageName, KeySet ks) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return false;
         }
         if (packageName == null || ks == null) {
@@ -23963,7 +24176,9 @@
         }
         synchronized(mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
-            if (pkg == null) {
+            if (pkg == null
+                    || filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid,
+                            UserHandle.getUserId(callingUid))) {
                 Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -24280,8 +24495,34 @@
         }
 
         @Override
-        public ApplicationInfo getApplicationInfo(String packageName, int userId) {
-            return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId);
+        public PackageInfo getPackageInfo(
+                String packageName, int flags, int filterCallingUid, int userId) {
+            return PackageManagerService.this
+                    .getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
+                            flags, filterCallingUid, userId);
+        }
+
+        @Override
+        public ApplicationInfo getApplicationInfo(
+                String packageName, int flags, int filterCallingUid, int userId) {
+            return PackageManagerService.this
+                    .getApplicationInfoInternal(packageName, flags, filterCallingUid, userId);
+        }
+
+        @Override
+        public ActivityInfo getActivityInfo(
+                ComponentName component, int flags, int filterCallingUid, int userId) {
+            return PackageManagerService.this
+                    .getActivityInfoInternal(component, flags, filterCallingUid, userId);
+        }
+
+        @Override
+        public List<ResolveInfo> queryIntentActivities(
+                Intent intent, int flags, int filterCallingUid, int userId) {
+            final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
+            return PackageManagerService.this
+                    .queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid,
+                            userId, false /*resolveForStart*/);
         }
 
         @Override
@@ -24612,9 +24853,6 @@
 
     @Override
     public boolean canRequestPackageInstalls(String packageName, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
-            return false;
-        }
         return canRequestPackageInstallsInternal(packageName, 0, userId,
                 true /* throwIfPermNotDeclared*/);
     }
diff --git a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
index 7d53310..3e5e57b 100644
--- a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
+++ b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
@@ -233,7 +233,7 @@
 
     private AccessibilityServiceInfo getInfoForTargetService() {
         final String currentShortcutServiceString = getTargetServiceComponentNameString(
-                mContext, UserHandle.myUserId());
+                mContext, UserHandle.USER_CURRENT);
         if (currentShortcutServiceString == null) {
             return null;
         }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 525e0ff..71ecaf6 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1107,7 +1107,7 @@
                 mAppAnimator.lastFreezeDuration = 0;
                 mService.mAppsFreezingScreen++;
                 if (mService.mAppsFreezingScreen == 1) {
-                    mService.startFreezingDisplayLocked(false, 0, 0);
+                    mService.startFreezingDisplayLocked(false, 0, 0, getDisplayContent());
                     mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
                     mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
                 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b5476d7..ccc8f63 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -987,7 +987,7 @@
         }
 
         if (!rotateSeamlessly) {
-            mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
+            mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1], this);
             // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
             screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
                     mDisplayId);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 1f7ef50..bf8fabd 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -17,15 +17,13 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
-import static android.graphics.Bitmap.Config.ARGB_8888;
-import static android.graphics.Bitmap.Config.HARDWARE;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManager.StackId;
 import android.app.ActivityManager.TaskSnapshot;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.os.Environment;
@@ -89,9 +87,16 @@
     private final ArraySet<Task> mTmpTasks = new ArraySet<>();
     private final Handler mHandler = new Handler();
 
+    /**
+     * Flag indicating whether we are running on an Android TV device.
+     */
+    private final boolean mIsRunningOnTv;
+
     TaskSnapshotController(WindowManagerService service) {
         mService = service;
         mCache = new TaskSnapshotCache(mService, mLoader);
+        mIsRunningOnTv = mService.mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_LEANBACK);
     }
 
     void systemReady() {
@@ -112,7 +117,7 @@
     }
 
     private void handleClosingApps(ArraySet<AppWindowToken> closingApps) {
-        if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+        if (shouldDisableSnapshots()) {
             return;
         }
 
@@ -188,6 +193,10 @@
                 1f /* scale */);
     }
 
+    private boolean shouldDisableSnapshots() {
+        return !ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic() || mIsRunningOnTv;
+    }
+
     private Rect minRect(Rect rect1, Rect rect2) {
         return new Rect(Math.min(rect1.left, rect2.left),
                 Math.min(rect1.top, rect2.top),
@@ -301,7 +310,7 @@
      * Called when screen is being turned off.
      */
     void screenTurningOff(ScreenOffListener listener) {
-        if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+        if (shouldDisableSnapshots()) {
             listener.onScreenOff();
             return;
         }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 3a116bb..551e3bf 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -102,6 +102,8 @@
             | FLAG_SCALED
             | FLAG_SECURE;
 
+    private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+
     private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
     private static final int MSG_REPORT_DRAW = 0;
     private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
@@ -160,7 +162,8 @@
             layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
                     | FLAG_NOT_FOCUSABLE
                     | FLAG_NOT_TOUCHABLE;
-            layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
+            layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT
+                    | (windowPrivateFlags & PRIVATE_FLAG_INHERITS);
             layoutParams.token = token.token;
             layoutParams.width = LayoutParams.MATCH_PARENT;
             layoutParams.height = LayoutParams.MATCH_PARENT;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index eff8ed9..39878cc 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -109,6 +109,7 @@
 
     /** Application tokens that are exiting, but still on screen for animations. */
     final AppTokenList mExitingAppTokens = new AppTokenList();
+    final AppTokenList mTmpAppTokens = new AppTokenList();
 
     /** Detach this stack from its display when animation completes. */
     // TODO: maybe tie this to WindowContainer#removeChild some how...
@@ -1626,9 +1627,14 @@
 
         // TODO: Why aren't we just using the loop above for this? mAppAnimator.animating isn't set
         // below but is set in the loop above. See if it really matters...
-        final int exitingCount = mExitingAppTokens.size();
-        for (int i = 0; i < exitingCount; i++) {
-            final AppWindowAnimator appAnimator = mExitingAppTokens.get(i).mAppAnimator;
+
+        // Clear before using.
+        mTmpAppTokens.clear();
+        // We copy the list as things can be removed from the exiting token list while we are
+        // processing.
+        mTmpAppTokens.addAll(mExitingAppTokens);
+        for (int i = 0; i < mTmpAppTokens.size(); i++) {
+            final AppWindowAnimator appAnimator = mTmpAppTokens.get(i).mAppAnimator;
             appAnimator.wasAnimating = appAnimator.animating;
             if (appAnimator.stepAnimationLocked(currentTime)) {
                 mService.mAnimator.setAnimating(true);
@@ -1641,6 +1647,8 @@
                         "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
             }
         }
+        // Clear to avoid holding reference to tokens.
+        mTmpAppTokens.clear();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9d1b3d9..e5af9d2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -20,7 +20,6 @@
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
 import static android.app.StatusBarManager.DISABLE_MASK;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
@@ -33,6 +32,7 @@
 import static android.os.Process.myPid;
 import static android.os.UserHandle.USER_NULL;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -158,6 +158,7 @@
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
+import android.text.format.DateUtils;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
@@ -601,7 +602,7 @@
 
     final UnknownAppVisibilityController mUnknownAppVisibilityController =
             new UnknownAppVisibilityController(this);
-    final TaskSnapshotController mTaskSnapshotController = new TaskSnapshotController(this);
+    final TaskSnapshotController mTaskSnapshotController;
 
     boolean mIsTouchDevice;
 
@@ -724,6 +725,9 @@
     // For frozen screen animations.
     private int mExitAnimId, mEnterAnimId;
 
+    // The display that the rotation animation is applying to.
+    private int mFrozenDisplayId;
+
     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
     int mTransactionSequence;
@@ -989,6 +993,7 @@
 
         mWindowPlacerLocked = new WindowSurfacePlacer(this);
         mPolicy = policy;
+        mTaskSnapshotController = new TaskSnapshotController(this);
 
         LocalServices.addService(WindowManagerPolicy.class, mPolicy);
 
@@ -2449,7 +2454,7 @@
                 } else {
                     mPolicy.selectRotationAnimationLw(anim);
                 }
-                startFreezingDisplayLocked(false, anim[0], anim[1]);
+                startFreezingDisplayLocked(false, anim[0], anim[1], displayContent);
                 config = new Configuration(mTempConfiguration);
             }
         }
@@ -3596,8 +3601,16 @@
     // only allow disables from pids which have count on, etc.
     @Override
     public void showStrictModeViolation(boolean on) {
-        int pid = Binder.getCallingPid();
-        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
+        final int pid = Binder.getCallingPid();
+        if (on) {
+            // Show the visualization, and enqueue a second message to tear it
+            // down if we don't hear back from the app.
+            mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 1, pid));
+            mH.sendMessageDelayed(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid),
+                    DateUtils.SECOND_IN_MILLIS);
+        } else {
+            mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid));
+        }
     }
 
     private void showStrictModeViolation(int arg, int pid) {
@@ -5555,7 +5568,7 @@
         if (configChanged) {
             mWaitingForConfig = true;
             startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
-                    0 /* enterAnim */);
+                    0 /* enterAnim */, displayContent);
             mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
         }
 
@@ -5862,6 +5875,12 @@
     }
 
     void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
+        startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim,
+                getDefaultDisplayContentLocked());
+    }
+
+    void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim,
+            DisplayContent displayContent) {
         if (mDisplayFrozen) {
             return;
         }
@@ -5882,6 +5901,10 @@
         mDisplayFreezeTime = SystemClock.elapsedRealtime();
         mLastFinishedFreezeSource = null;
 
+        // {@link mDisplayFrozen} prevents us from freezing on multiple displays at the same time.
+        // As a result, we only track the display that has initially froze the screen.
+        mFrozenDisplayId = displayContent.getDisplayId();
+
         mInputMonitor.freezeInputDispatchingLw();
 
         // Clear the last input window -- that is just used for
@@ -5901,10 +5924,8 @@
         if (CUSTOM_SCREEN_ROTATION) {
             mExitAnimId = exitAnim;
             mEnterAnimId = enterAnim;
-            final DisplayContent displayContent = getDefaultDisplayContentLocked();
-            final int displayId = displayContent.getDisplayId();
             ScreenRotationAnimation screenRotationAnimation =
-                    mAnimator.getScreenRotationAnimationLocked(displayId);
+                    mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId);
             if (screenRotationAnimation != null) {
                 screenRotationAnimation.kill();
             }
@@ -5915,8 +5936,10 @@
             // TODO(multidisplay): rotation on main screen only.
             displayContent.updateDisplayInfo();
             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
-                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure, this);
-            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
+                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure,
+                    this);
+            mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
+                    screenRotationAnimation);
         }
     }
 
@@ -5940,6 +5963,13 @@
         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
                 "stopFreezingDisplayLocked: Unfreezing now");
 
+        final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId);
+
+        // We must make a local copy of the displayId as it can be potentially overwritten later on
+        // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result
+        // of update rotation, but we reference the frozen display after that call in this method.
+        final int displayId = mFrozenDisplayId;
+        mFrozenDisplayId = INVALID_DISPLAY;
         mDisplayFrozen = false;
         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
         StringBuilder sb = new StringBuilder(128);
@@ -5958,8 +5988,6 @@
 
         boolean updateRotation = false;
 
-        final DisplayContent displayContent = getDefaultDisplayContentLocked();
-        final int displayId = displayContent.getDisplayId();
         ScreenRotationAnimation screenRotationAnimation =
                 mAnimator.getScreenRotationAnimationLocked(displayId);
         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 686dad4..e12032d 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -52,6 +52,10 @@
     <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
     <uses-permission android:name="android.permission.DELETE_PACKAGES" />
 
+    <!-- Uses API introduced in O (26) -->
+    <uses-sdk android:minSdkVersion="1"
+          android:targetSdkVersion="26"/>
+
     <application>
         <uses-library android:name="android.test.runner" />
 
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 36e9b3f8..791d3e9 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -1484,6 +1484,31 @@
     }
 
     @SmallTest
+    public void testGetAccountsByTypeForPackageWhenTypeIsNull() throws Exception {
+        unlockSystemUser();
+        HashMap<String, Integer> visibility1 = new HashMap<>();
+        visibility1.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+            AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
+
+        HashMap<String, Integer> visibility2 = new HashMap<>();
+        visibility2.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+            AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
+
+        mAms.addAccountExplicitlyWithVisibility(
+            AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "P11", null, visibility1);
+        mAms.addAccountExplicitlyWithVisibility(
+            AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "P12", null, visibility2);
+
+        Account[] accounts = mAms.getAccountsByTypeForPackage(
+            null, "otherPackageName",
+            AccountManagerServiceTestFixtures.CALLER_PACKAGE);
+        // Only get the USER_MANAGED_NOT_VISIBLE account.
+        assertEquals(1, accounts.length);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accounts[0].name);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accounts[0].type);
+    }
+
+    @SmallTest
     public void testGetAuthTokenLabelWithNullAccountType() throws Exception {
         unlockSystemUser();
         try {
@@ -2341,6 +2366,224 @@
     }
 
     @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNullResponse() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.getAccountByTypeAndFeatures(
+                null, // response
+                AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+                AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+                "testpackage"); // opPackageName
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+            // IllegalArgumentException is expected.
+        }
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNullAccountType() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.getAccountByTypeAndFeatures(
+                mMockAccountManagerResponse, // response
+                null, // accountType
+                AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+                "testpackage"); // opPackageName
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+            // IllegalArgumentException is expected.
+        }
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndNoAccount() throws Exception {
+        unlockSystemUser();
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            null,
+            "testpackage");
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(null, accountName);
+        assertEquals(null, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndOneVisibleAccount()
+        throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            null,
+            "testpackage");
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accountName);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndOneNotVisibleAccount()
+        throws Exception {
+        unlockSystemUser();
+        HashMap<String, Integer> visibility = new HashMap<>();
+        visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+            AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
+        mAms.addAccountExplicitlyWithVisibility(
+            AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            null,
+            AccountManagerServiceTestFixtures.CALLER_PACKAGE);
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+        Intent intent = mIntentCaptor.getValue();
+        Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+        assertEquals(1, accounts.length);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndTwoAccounts() throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null);
+
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            null,
+            "testpackage");
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+        Intent intent = mIntentCaptor.getValue();
+        Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+        assertEquals(2, accounts.length);
+        if (accounts[0].equals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS)) {
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, accounts[1]);
+        } else {
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, accounts[0]);
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[1]);
+        }
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndNoAccount() throws Exception {
+        unlockSystemUser();
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            "testpackage");
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(null, accountName);
+        assertEquals(null, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndNoQualifiedAccount()
+        throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            "testpackage");
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(null, accountName);
+        assertEquals(null, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndOneQualifiedAccount()
+        throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            "testpackage");
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accountName);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndOneQualifiedNotVisibleAccount()
+        throws Exception {
+        unlockSystemUser();
+        HashMap<String, Integer> visibility = new HashMap<>();
+        visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+            AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
+        mAms.addAccountExplicitlyWithVisibility(
+            AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            AccountManagerServiceTestFixtures.CALLER_PACKAGE);
+        waitForLatch(latch);
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+        Intent intent = mIntentCaptor.getValue();
+        Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+        assertEquals(1, accounts.length);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndTwoQualifiedAccount()
+        throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, "p12", null);
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p13", null);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            "testpackage");
+        waitForLatch(latch);
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+        Intent intent = mIntentCaptor.getValue();
+        Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+        assertEquals(2, accounts.length);
+        if (accounts[0].equals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS)) {
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, accounts[1]);
+        } else {
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, accounts[0]);
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[1]);
+        }
+    }
+
+    @SmallTest
     public void testGetAccountsByFeaturesWithNullResponse() throws Exception {
         unlockSystemUser();
         try {
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
index d176a0d..73f30d9 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
@@ -34,6 +34,7 @@
     public static final String KEY_OPTIONS_BUNDLE =
             "account_manager_service_test:option_bundle_key";
     public static final String ACCOUNT_NAME_SUCCESS = "success_on_return@fixture.com";
+    public static final String ACCOUNT_NAME_SUCCESS_2 = "success_on_return_2@fixture.com";
     public static final String ACCOUNT_NAME_INTERVENE = "intervene@fixture.com";
     public static final String ACCOUNT_NAME_ERROR = "error@fixture.com";
 
@@ -69,6 +70,8 @@
 
     public static final Account ACCOUNT_SUCCESS =
             new Account(ACCOUNT_NAME_SUCCESS, ACCOUNT_TYPE_1);
+    public static final Account ACCOUNT_SUCCESS_2 =
+            new Account(ACCOUNT_NAME_SUCCESS_2, ACCOUNT_TYPE_1);
     public static final Account ACCOUNT_INTERVENE =
             new Account(ACCOUNT_NAME_INTERVENE, ACCOUNT_TYPE_1);
     public static final Account ACCOUNT_ERROR =
diff --git a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
index eb839a2..8106364 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
@@ -242,6 +242,8 @@
         if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
             // fill bundle with true.
             result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+        } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS_2)) {
+            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
         } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
             // fill bundle with false.
             result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 26a406f..ca74688 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -407,13 +407,15 @@
                         UsbManager.USB_FUNCTION_ADB);
 
                 /**
-                 * Remove MTP from persistent config, to bring usb to a good state
-                 * after fixes to b/31814300. This block can be removed after the update
+                 * Previous versions can set persist config to mtp/ptp but it does not
+                 * get reset on OTA. Reset the property here instead.
                  */
                 String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
-                if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)) {
+                if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)
+                        || UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)) {
                     SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
-                            UsbManager.removeFunction(persisted, UsbManager.USB_FUNCTION_MTP));
+                            UsbManager.removeFunction(UsbManager.removeFunction(persisted,
+                                    UsbManager.USB_FUNCTION_MTP), UsbManager.USB_FUNCTION_PTP));
                 }
 
                 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 0a47a98..d0b36c9 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -17,7 +17,9 @@
 import android.Manifest;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressAutoDoc;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -48,6 +50,7 @@
  * descriptions.
  */
 @SuppressAutoDoc
+@SystemService(Context.TELECOM_SERVICE)
 public class TelecomManager {
 
     /**
@@ -734,6 +737,10 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
         try {
             if (isServiceConnected()) {
@@ -815,6 +822,7 @@
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public List<PhoneAccountHandle> getPhoneAccountsForPackage() {
         try {
             if (isServiceConnected()) {
@@ -942,6 +950,7 @@
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void clearPhoneAccounts() {
         clearAccounts();
     }
@@ -951,6 +960,7 @@
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void clearAccounts() {
         try {
             if (isServiceConnected()) {
@@ -982,6 +992,7 @@
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public ComponentName getDefaultPhoneApp() {
         try {
             if (isServiceConnected()) {
@@ -1198,6 +1209,10 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isRinging() {
         try {
             if (isServiceConnected()) {
@@ -1216,6 +1231,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean endCall() {
         try {
             if (isServiceConnected()) {
@@ -1295,6 +1311,10 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isTtySupported() {
         try {
             if (isServiceConnected()) {
@@ -1573,6 +1593,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void enablePhoneAccount(PhoneAccountHandle handle, boolean isEnabled) {
         ITelecomService service = getTelecomService();
         if (service != null) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7174a70..c6c1be3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -18,7 +18,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
@@ -29,14 +32,8 @@
 
 /**
  * Provides access to telephony configuration values that are carrier-specific.
- * <p>
- * Users should obtain an instance of this class by calling
- * {@code mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);}
- * </p>
- *
- * @see Context#getSystemService
- * @see Context#CARRIER_CONFIG_SERVICE
  */
+@SystemService(Context.CARRIER_CONFIG_SERVICE)
 public class CarrierConfigManager {
     private final static String TAG = "CarrierConfigManager";
 
@@ -1742,6 +1739,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void updateConfigForPhoneId(int phoneId, String simState) {
         try {
             ICarrierConfigLoader loader = getICarrierConfigLoader();
@@ -1763,6 +1761,7 @@
      */
     @NonNull
     @SystemApi
+    @SuppressLint("Doclava125")
     public static PersistableBundle getDefaultConfig() {
         return new PersistableBundle(sDefaults);
     }
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 7d4d90b..1eac263 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
@@ -346,6 +347,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void sendTextMessageWithoutPersisting(
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent) {
@@ -530,6 +532,7 @@
      * @hide
      **/
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void sendMultipartTextMessageWithoutPersisting(
             String destinationAddress, String scAddress, List<String> parts,
             List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 7f616ad..709877d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.content.Intent;
@@ -41,12 +42,10 @@
 /**
  * SubscriptionManager is the application interface to SubscriptionController
  * and provides information about the current Telephony Subscriptions.
- * * <p>
- * You do not instantiate this class directly; instead, you retrieve
- * a reference to an instance through {@link #from}.
  * <p>
  * All SDK public methods require android.Manifest.permission.READ_PHONE_STATE.
  */
+@SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
 public class SubscriptionManager {
     private static final String LOG_TAG = "SubscriptionManager";
     private static final boolean DBG = false;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b8e24f0..6b921c7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -22,8 +22,10 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.WorkerThread;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
@@ -79,11 +81,6 @@
  * types of subscriber information. Applications can also register
  * a listener to receive notification of telephony state changes.
  * <p>
- * You do not instantiate this class directly; instead, you retrieve
- * a reference to an instance through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.TELEPHONY_SERVICE)}.
- *
  * The returned TelephonyManager will use the default subscription for all calls.
  * To call an API for a specific subscription, use {@link #createForSubscriptionId(int)}. e.g.
  * <code>
@@ -96,6 +93,7 @@
  * its manifest file. Where permissions apply, they are noted in the
  * the methods through which you access the protected information.
  */
+@SystemService(Context.TELEPHONY_SERVICE)
 public class TelephonyManager {
     private static final String TAG = "TelephonyManager";
 
@@ -2671,8 +2669,8 @@
      * be implemented instead.
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){
-
     }
 
     /**
@@ -2686,6 +2684,7 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @SuppressLint("Doclava125")
     public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
         return false;
     }
@@ -2704,6 +2703,7 @@
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     @Nullable
     public Bundle getVisualVoicemailSettings(){
         try {
@@ -4855,12 +4855,14 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public String getCdmaMdn() {
         return getCdmaMdn(getSubId());
     }
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public String getCdmaMdn(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4876,12 +4878,14 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public String getCdmaMin() {
         return getCdmaMin(getSubId());
     }
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public String getCdmaMin(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4897,6 +4901,7 @@
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public int checkCarrierPrivilegesForPackage(String pkgName) {
         try {
             ITelephony telephony = getITelephony();
@@ -4912,6 +4917,7 @@
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
         try {
             ITelephony telephony = getITelephony();
@@ -4963,6 +4969,7 @@
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void dial(String number) {
         try {
             ITelephony telephony = getITelephony();
@@ -4975,6 +4982,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CALL_PHONE)
     public void call(String callingPackage, String number) {
         try {
             ITelephony telephony = getITelephony();
@@ -4987,6 +4995,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CALL_PHONE)
     public boolean endCall() {
         try {
             ITelephony telephony = getITelephony();
@@ -5000,6 +5009,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void answerRingingCall() {
         try {
             ITelephony telephony = getITelephony();
@@ -5012,6 +5022,7 @@
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void silenceRinger() {
         try {
             getTelecomService().silenceRinger(getOpPackageName());
@@ -5022,6 +5033,10 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isOffhook() {
         try {
             ITelephony telephony = getITelephony();
@@ -5035,6 +5050,10 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isRinging() {
         try {
             ITelephony telephony = getITelephony();
@@ -5048,6 +5067,10 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isIdle() {
         try {
             ITelephony telephony = getITelephony();
@@ -5061,6 +5084,10 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isRadioOn() {
         try {
             ITelephony telephony = getITelephony();
@@ -5074,6 +5101,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean supplyPin(String pin) {
         try {
             ITelephony telephony = getITelephony();
@@ -5087,6 +5115,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean supplyPuk(String puk, String pin) {
         try {
             ITelephony telephony = getITelephony();
@@ -5100,6 +5129,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public int[] supplyPinReportResult(String pin) {
         try {
             ITelephony telephony = getITelephony();
@@ -5113,6 +5143,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public int[] supplyPukReportResult(String puk, String pin) {
         try {
             ITelephony telephony = getITelephony();
@@ -5232,6 +5263,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean handlePinMmi(String dialString) {
         try {
             ITelephony telephony = getITelephony();
@@ -5245,6 +5277,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean handlePinMmiForSubscriber(int subId, String dialString) {
         try {
             ITelephony telephony = getITelephony();
@@ -5258,6 +5291,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void toggleRadioOnOff() {
         try {
             ITelephony telephony = getITelephony();
@@ -5270,6 +5304,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean setRadio(boolean turnOn) {
         try {
             ITelephony telephony = getITelephony();
@@ -5283,6 +5318,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean setRadioPower(boolean turnOn) {
         try {
             ITelephony telephony = getITelephony();
@@ -5296,6 +5332,7 @@
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void updateServiceLocation() {
         try {
             ITelephony telephony = getITelephony();
@@ -5308,6 +5345,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean enableDataConnectivity() {
         try {
             ITelephony telephony = getITelephony();
@@ -5321,6 +5359,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean disableDataConnectivity() {
         try {
             ITelephony telephony = getITelephony();
@@ -5371,12 +5410,14 @@
      *
      * @see #hasCarrierPrivileges
      */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setDataEnabled(boolean enable) {
         setDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
     }
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setDataEnabled(int subId, boolean enable) {
         try {
             Log.d(TAG, "setDataEnabled: enabled=" + enable);
@@ -5466,6 +5507,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void enableVideoCalling(boolean enable) {
         try {
             ITelephony telephony = getITelephony();
@@ -5478,6 +5520,10 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isVideoCallingEnabled() {
         try {
             ITelephony telephony = getITelephony();
@@ -6346,6 +6392,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public List<TelephonyHistogram> getTelephonyHistograms() {
         try {
             ITelephony service = getITelephony();
@@ -6373,6 +6420,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
         try {
             ITelephony service = getITelephony();
@@ -6391,9 +6439,6 @@
      * Get the allowed carrier list for slotIndex.
      * Require system privileges. In the future we may add this to carrier APIs.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
-     *
      * <p>This method returns valid data on devices with {@link
      * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
      *
@@ -6402,6 +6447,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
         try {
             ITelephony service = getITelephony();
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
index db45b9d..99d44e6 100644
--- a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
@@ -17,7 +17,7 @@
 
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -31,7 +31,7 @@
 /**
  * Main activity of the app.
  */
-public class MainActivity extends ActionBarActivity {
+public class MainActivity extends AppCompatActivity {
 
     private static final String LOG = "MainActivity";
 
diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
index 7632a6e..55440c8 100644
--- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
+++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
@@ -21,7 +21,7 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.os.CountDownTimer;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
 import android.os.Bundle;
 import android.text.method.Touch;
 import android.util.AttributeSet;
@@ -173,7 +173,7 @@
     private float mVelocityX, mVelocityY;
 }
 
-public class TouchLatencyActivity extends ActionBarActivity {
+public class TouchLatencyActivity extends AppCompatActivity {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index b2f1f62..eff8283 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -159,7 +159,7 @@
 // ==========================================================
 cc_test_host {
     name: "aapt2_tests",
-    srcs: ["**/*_test.cpp"],
+    srcs: ["test/Common.cpp", "**/*_test.cpp"],
     static_libs: ["libaapt2", "libgmock"],
     defaults: ["aapt_defaults"],
 }
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 32e0fd5..9503b56 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -623,6 +623,11 @@
     return std::move(string);
   }
 
+  // If the text is empty, and the value is not allowed to be a string, encode it as a @null.
+  if (util::TrimWhitespace(raw_value).empty()) {
+    return ResourceUtils::MakeNull();
+  }
+
   if (allow_raw_value) {
     // We can't parse this so return a RawString if we are allowed.
     return util::make_unique<RawString>(
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index 8258019..5631dc2 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -78,42 +78,32 @@
    * Item, then a
    * RawString is returned. Otherwise this returns false;
    */
-  std::unique_ptr<Item> ParseXml(xml::XmlPullParser* parser,
-                                 const uint32_t type_mask,
+  std::unique_ptr<Item> ParseXml(xml::XmlPullParser* parser, const uint32_t type_mask,
                                  const bool allow_raw_value);
 
   bool ParseResources(xml::XmlPullParser* parser);
   bool ParseResource(xml::XmlPullParser* parser, ParsedResource* out_resource);
 
-  bool ParseItem(xml::XmlPullParser* parser, ParsedResource* out_resource,
-                 uint32_t format);
+  bool ParseItem(xml::XmlPullParser* parser, ParsedResource* out_resource, uint32_t format);
   bool ParseString(xml::XmlPullParser* parser, ParsedResource* out_resource);
 
   bool ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource);
-  bool ParsePublicGroup(xml::XmlPullParser* parser,
-                        ParsedResource* out_resource);
-  bool ParseSymbolImpl(xml::XmlPullParser* parser,
-                       ParsedResource* out_resource);
+  bool ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource);
+  bool ParseSymbolImpl(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out_resource);
-  bool ParseAddResource(xml::XmlPullParser* parser,
-                        ParsedResource* out_resource);
+  bool ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseAttr(xml::XmlPullParser* parser, ParsedResource* out_resource);
-  bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource,
-                     bool weak);
+  bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, bool weak);
   Maybe<Attribute::Symbol> ParseEnumOrFlagItem(xml::XmlPullParser* parser,
                                                const android::StringPiece& tag);
   bool ParseStyle(const ResourceType type, xml::XmlPullParser* parser,
                   ParsedResource* out_resource);
   bool ParseStyleItem(xml::XmlPullParser* parser, Style* style);
-  bool ParseDeclareStyleable(xml::XmlPullParser* parser,
-                             ParsedResource* out_resource);
+  bool ParseDeclareStyleable(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
-  bool ParseIntegerArray(xml::XmlPullParser* parser,
-                         ParsedResource* out_resource);
-  bool ParseStringArray(xml::XmlPullParser* parser,
-                        ParsedResource* out_resource);
-  bool ParseArrayImpl(xml::XmlPullParser* parser, ParsedResource* out_resource,
-                      uint32_t typeMask);
+  bool ParseIntegerArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
+  bool ParseStringArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
+  bool ParseArrayImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, uint32_t typeMask);
   bool ParsePlural(xml::XmlPullParser* parser, ParsedResource* out_resource);
 
   IDiagnostics* diag_;
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index e60ef66..5352ca8 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -25,19 +25,20 @@
 #include "test/Test.h"
 #include "xml/XmlPullParser.h"
 
+using ::aapt::test::ValueEq;
 using ::android::StringPiece;
 using ::testing::Eq;
 using ::testing::NotNull;
+using ::testing::Pointee;
 
 namespace aapt {
 
-constexpr const char* kXmlPreamble =
-    "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+constexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
 
 TEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) {
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
   std::stringstream input(kXmlPreamble);
-  input << "<attr name=\"foo\"/>" << std::endl;
+  input << R"(<attr name="foo"/>)" << std::endl;
   ResourceTable table;
   ResourceParser parser(context->GetDiagnostics(), &table, Source{"test"}, {});
   xml::XmlPullParser xml_parser(input);
@@ -46,19 +47,20 @@
 
 class ResourceParserTest : public ::testing::Test {
  public:
-  void SetUp() override { context_ = test::ContextBuilder().Build(); }
+  void SetUp() override {
+    context_ = test::ContextBuilder().Build();
+  }
 
   ::testing::AssertionResult TestParse(const StringPiece& str) {
     return TestParse(str, ConfigDescription{});
   }
 
-  ::testing::AssertionResult TestParse(const StringPiece& str,
-                                       const ConfigDescription& config) {
+  ::testing::AssertionResult TestParse(const StringPiece& str, const ConfigDescription& config) {
     std::stringstream input(kXmlPreamble);
     input << "<resources>\n" << str << "\n</resources>" << std::endl;
     ResourceParserOptions parserOptions;
-    ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"},
-                          config, parserOptions);
+    ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"}, config,
+                          parserOptions);
     xml::XmlPullParser xmlParser(input);
     if (parser.Parse(&xmlParser)) {
       return ::testing::AssertionSuccess();
@@ -205,18 +207,18 @@
   // a non-existing value, and this causes problems in styles when trying to
   // resolve an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE
   // with a data value of 0.
-  BinaryPrimitive* integer = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
-  ASSERT_NE(nullptr, integer);
-  EXPECT_EQ(uint16_t(android::Res_value::TYPE_REFERENCE), integer->value.dataType);
-  EXPECT_EQ(0u, integer->value.data);
+  Reference* null_ref = test::GetValue<Reference>(&table_, "integer/foo");
+  ASSERT_THAT(null_ref, NotNull());
+  EXPECT_FALSE(null_ref->name);
+  EXPECT_FALSE(null_ref->id);
+  EXPECT_EQ(Reference::Type::kResource, null_ref->reference_type);
 }
 
 TEST_F(ResourceParserTest, ParseEmpty) {
   std::string input = "<integer name=\"foo\">@empty</integer>";
   ASSERT_TRUE(TestParse(input));
 
-  BinaryPrimitive* integer =
-      test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
+  BinaryPrimitive* integer = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
   ASSERT_NE(nullptr, integer);
   EXPECT_EQ(uint16_t(android::Res_value::TYPE_NULL), integer->value.dataType);
   EXPECT_EQ(uint32_t(android::Res_value::DATA_NULL_EMPTY), integer->value.data);
@@ -241,22 +243,18 @@
 // ultimately
 // stored them with the default configuration. Check that we have the same
 // behavior.
-TEST_F(ResourceParserTest,
-       ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) {
+TEST_F(ResourceParserTest, ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) {
   const ConfigDescription watch_config = test::ParseConfigOrDie("watch");
-  std::string input = R"EOF(
-        <attr name="foo" />
-        <declare-styleable name="bar">
-          <attr name="baz" />
-        </declare-styleable>)EOF";
+  std::string input = R"(
+      <attr name="foo" />
+      <declare-styleable name="bar">
+        <attr name="baz" />
+      </declare-styleable>)";
   ASSERT_TRUE(TestParse(input, watch_config));
 
-  EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/foo",
-                                                        watch_config));
-  EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/baz",
-                                                        watch_config));
-  EXPECT_EQ(nullptr, test::GetValueForConfig<Styleable>(
-                         &table_, "styleable/bar", watch_config));
+  EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/foo", watch_config));
+  EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/baz", watch_config));
+  EXPECT_EQ(nullptr, test::GetValueForConfig<Styleable>(&table_, "styleable/bar", watch_config));
 
   EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/foo"));
   EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/baz"));
@@ -833,4 +831,16 @@
   EXPECT_NE(nullptr, ValueCast<RawString>(val->entries[0].value.get()));
 }
 
+TEST_F(ResourceParserTest, ParseElementWithNoValue) {
+  std::string input = R"(
+      <item type="drawable" format="reference" name="foo" />
+      <string name="foo" />)";
+  ASSERT_TRUE(TestParse(input));
+  ASSERT_THAT(test::GetValue(&table_, "drawable/foo"), Pointee(ValueEq(Reference())));
+
+  String* str = test::GetValue<String>(&table_, "string/foo");
+  ASSERT_THAT(str, NotNull());
+  EXPECT_THAT(*str->value, Eq(""));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 818c8ce..deeef6e 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -305,21 +305,25 @@
   return {};
 }
 
-std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const StringPiece& str) {
-  StringPiece trimmed_str(util::TrimWhitespace(str));
-  android::Res_value value = {};
+std::unique_ptr<Item> TryParseNullOrEmpty(const StringPiece& str) {
+  const StringPiece trimmed_str(util::TrimWhitespace(str));
   if (trimmed_str == "@null") {
-    // TYPE_NULL with data set to 0 is interpreted by the runtime as an error.
-    // Instead we set the data type to TYPE_REFERENCE with a value of 0.
-    value.dataType = android::Res_value::TYPE_REFERENCE;
+    return MakeNull();
   } else if (trimmed_str == "@empty") {
-    // TYPE_NULL with value of DATA_NULL_EMPTY is handled fine by the runtime.
-    value.dataType = android::Res_value::TYPE_NULL;
-    value.data = android::Res_value::DATA_NULL_EMPTY;
-  } else {
-    return {};
+    return MakeEmpty();
   }
-  return util::make_unique<BinaryPrimitive>(value);
+  return {};
+}
+
+std::unique_ptr<Reference> MakeNull() {
+  // TYPE_NULL with data set to 0 is interpreted by the runtime as an error.
+  // Instead we set the data type to TYPE_REFERENCE with a value of 0.
+  return util::make_unique<Reference>();
+}
+
+std::unique_ptr<BinaryPrimitive> MakeEmpty() {
+  return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_NULL,
+                                            android::Res_value::DATA_NULL_EMPTY);
 }
 
 std::unique_ptr<BinaryPrimitive> TryParseEnumSymbol(const Attribute* enum_attr,
@@ -569,13 +573,15 @@
 std::unique_ptr<Item> TryParseItemForAttribute(
     const StringPiece& value, uint32_t type_mask,
     const std::function<void(const ResourceName&)>& on_create_reference) {
-  std::unique_ptr<BinaryPrimitive> null_or_empty = TryParseNullOrEmpty(value);
+  using android::ResTable_map;
+
+  auto null_or_empty = TryParseNullOrEmpty(value);
   if (null_or_empty) {
-    return std::move(null_or_empty);
+    return null_or_empty;
   }
 
   bool create = false;
-  std::unique_ptr<Reference> reference = TryParseReference(value, &create);
+  auto reference = TryParseReference(value, &create);
   if (reference) {
     if (create && on_create_reference) {
       on_create_reference(reference->name.value());
@@ -583,39 +589,37 @@
     return std::move(reference);
   }
 
-  if (type_mask & android::ResTable_map::TYPE_COLOR) {
+  if (type_mask & ResTable_map::TYPE_COLOR) {
     // Try parsing this as a color.
-    std::unique_ptr<BinaryPrimitive> color = TryParseColor(value);
+    auto color = TryParseColor(value);
     if (color) {
       return std::move(color);
     }
   }
 
-  if (type_mask & android::ResTable_map::TYPE_BOOLEAN) {
+  if (type_mask & ResTable_map::TYPE_BOOLEAN) {
     // Try parsing this as a boolean.
-    std::unique_ptr<BinaryPrimitive> boolean = TryParseBool(value);
+    auto boolean = TryParseBool(value);
     if (boolean) {
       return std::move(boolean);
     }
   }
 
-  if (type_mask & android::ResTable_map::TYPE_INTEGER) {
+  if (type_mask & ResTable_map::TYPE_INTEGER) {
     // Try parsing this as an integer.
-    std::unique_ptr<BinaryPrimitive> integer = TryParseInt(value);
+    auto integer = TryParseInt(value);
     if (integer) {
       return std::move(integer);
     }
   }
 
-  const uint32_t float_mask = android::ResTable_map::TYPE_FLOAT |
-                              android::ResTable_map::TYPE_DIMENSION |
-                              android::ResTable_map::TYPE_FRACTION;
+  const uint32_t float_mask =
+      ResTable_map::TYPE_FLOAT | ResTable_map::TYPE_DIMENSION | ResTable_map::TYPE_FRACTION;
   if (type_mask & float_mask) {
     // Try parsing this as a float.
-    std::unique_ptr<BinaryPrimitive> floating_point = TryParseFloat(value);
+    auto floating_point = TryParseFloat(value);
     if (floating_point) {
-      if (type_mask &
-          AndroidTypeToAttributeTypeMask(floating_point->value.dataType)) {
+      if (type_mask & AndroidTypeToAttributeTypeMask(floating_point->value.dataType)) {
         return std::move(floating_point);
       }
     }
@@ -630,24 +634,25 @@
 std::unique_ptr<Item> TryParseItemForAttribute(
     const StringPiece& str, const Attribute* attr,
     const std::function<void(const ResourceName&)>& on_create_reference) {
+  using android::ResTable_map;
+
   const uint32_t type_mask = attr->type_mask;
-  std::unique_ptr<Item> value =
-      TryParseItemForAttribute(str, type_mask, on_create_reference);
+  auto value = TryParseItemForAttribute(str, type_mask, on_create_reference);
   if (value) {
     return value;
   }
 
-  if (type_mask & android::ResTable_map::TYPE_ENUM) {
+  if (type_mask & ResTable_map::TYPE_ENUM) {
     // Try parsing this as an enum.
-    std::unique_ptr<BinaryPrimitive> enum_value = TryParseEnumSymbol(attr, str);
+    auto enum_value = TryParseEnumSymbol(attr, str);
     if (enum_value) {
       return std::move(enum_value);
     }
   }
 
-  if (type_mask & android::ResTable_map::TYPE_FLAGS) {
+  if (type_mask & ResTable_map::TYPE_FLAGS) {
     // Try parsing this as a flag.
-    std::unique_ptr<BinaryPrimitive> flag_value = TryParseFlagSymbol(attr, str);
+    auto flag_value = TryParseFlagSymbol(attr, str);
     if (flag_value) {
       return std::move(flag_value);
     }
@@ -655,8 +660,7 @@
   return {};
 }
 
-std::string BuildResourceFileName(const ResourceFile& res_file,
-                                  const NameMangler* mangler) {
+std::string BuildResourceFileName(const ResourceFile& res_file, const NameMangler* mangler) {
   std::stringstream out;
   out << "res/" << res_file.name.type;
   if (res_file.config != ConfigDescription{}) {
@@ -719,9 +723,9 @@
         ref_type = Reference::Type::kAttribute;
       }
 
-      if (data == 0) {
+      if (data == 0u) {
         // A reference of 0, must be the magic @null reference.
-        return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_REFERENCE, 0u);
+        return util::make_unique<Reference>();
       }
 
       // This is a normal reference.
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index da0fc8e..36f6c2b 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -133,7 +133,16 @@
  * Returns a BinaryPrimitve object representing @null or @empty if the string
  * was parsed as one.
  */
-std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const android::StringPiece& str);
+std::unique_ptr<Item> TryParseNullOrEmpty(const android::StringPiece& str);
+
+// Returns a Reference representing @null.
+// Due to runtime compatibility issues, this is encoded as a reference with ID 0.
+// The runtime will convert this to TYPE_NULL.
+std::unique_ptr<Reference> MakeNull();
+
+// Returns a BinaryPrimitive representing @empty. This is encoded as a Res_value with
+// type Res_value::TYPE_NULL and data Res_value::DATA_NULL_EMPTY.
+std::unique_ptr<BinaryPrimitive> MakeEmpty();
 
 /*
  * Returns a BinaryPrimitve object representing a color if the string was parsed
diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp
index 048c692..cdc34f1 100644
--- a/tools/aapt2/ResourceUtils_test.cpp
+++ b/tools/aapt2/ResourceUtils_test.cpp
@@ -19,6 +19,9 @@
 #include "Resource.h"
 #include "test/Test.h"
 
+using ::aapt::test::ValueEq;
+using ::testing::Pointee;
+
 namespace aapt {
 
 TEST(ResourceUtilsTest, ParseBool) {
@@ -200,4 +203,22 @@
   EXPECT_EQ(0u, result->value.data);
 }
 
+TEST(ResourceUtilsTest, NullIsEmptyReference) {
+  auto null_value = ResourceUtils::MakeNull();
+  ASSERT_THAT(null_value, Pointee(ValueEq(Reference())));
+
+  auto value = ResourceUtils::TryParseNullOrEmpty("@null");
+  ASSERT_THAT(value, Pointee(ValueEq(Reference())));
+}
+
+TEST(ResourceUtilsTest, EmptyIsBinaryPrimitive) {
+  auto empty_value = ResourceUtils::MakeEmpty();
+  ASSERT_THAT(empty_value, Pointee(ValueEq(BinaryPrimitive(android::Res_value::TYPE_NULL,
+                                                           android::Res_value::DATA_NULL_EMPTY))));
+
+  auto value = ResourceUtils::TryParseNullOrEmpty("@empty");
+  ASSERT_THAT(value, Pointee(ValueEq(BinaryPrimitive(android::Res_value::TYPE_NULL,
+                                                     android::Res_value::DATA_NULL_EMPTY))));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index abfdec4..e808984 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -94,8 +94,8 @@
 
 bool Reference::Flatten(android::Res_value* out_value) const {
   const ResourceId resid = id.value_or_default(ResourceId(0));
-  const bool dynamic =
-      (resid.package_id() != kFrameworkPackageId && resid.package_id() != kAppPackageId);
+  const bool dynamic = resid.is_valid_dynamic() && resid.package_id() != kFrameworkPackageId &&
+                       resid.package_id() != kAppPackageId;
 
   if (reference_type == Reference::Type::kResource) {
     if (dynamic) {
@@ -119,22 +119,29 @@
 }
 
 void Reference::Print(std::ostream* out) const {
-  *out << "(reference) ";
-  if (reference_type == Reference::Type::kResource) {
-    *out << "@";
-    if (private_reference) {
-      *out << "*";
+  if (reference_type == Type::kResource) {
+    *out << "(reference) @";
+    if (!name && !id) {
+      *out << "null";
+      return;
     }
   } else {
-    *out << "?";
+    *out << "(attr-reference) ?";
+  }
+
+  if (private_reference) {
+    *out << "*";
   }
 
   if (name) {
     *out << name.value();
   }
 
-  if (id && !Res_INTERNALID(id.value().id)) {
-    *out << " " << id.value();
+  if (id && id.value().is_valid_dynamic()) {
+    if (name) {
+      *out << " ";
+    }
+    *out << id.value();
   }
 }
 
@@ -314,7 +321,11 @@
 void BinaryPrimitive::Print(std::ostream* out) const {
   switch (value.dataType) {
     case android::Res_value::TYPE_NULL:
-      *out << "(null)";
+      if (value.data == android::Res_value::DATA_NULL_EMPTY) {
+        *out << "(empty)";
+      } else {
+        *out << "(null)";
+      }
       break;
     case android::Res_value::TYPE_INT_DEC:
       *out << "(integer) " << static_cast<int32_t>(value.data);
diff --git a/tools/aapt2/ResourceValues_test.cpp b/tools/aapt2/ResourceValues_test.cpp
index e154d93..69f8e67 100644
--- a/tools/aapt2/ResourceValues_test.cpp
+++ b/tools/aapt2/ResourceValues_test.cpp
@@ -180,4 +180,14 @@
   EXPECT_TRUE(a->Equals(expected.get()));
 }
 
+// TYPE_NULL is encoded as TYPE_REFERENCE with a value of 0. This is represented in AAPT2
+// by a default constructed Reference value.
+TEST(ResourcesValuesTest, EmptyReferenceFlattens) {
+  android::Res_value value = {};
+  ASSERT_TRUE(Reference().Flatten(&value));
+
+  EXPECT_EQ(android::Res_value::TYPE_REFERENCE, value.dataType);
+  EXPECT_EQ(0x0u, value.data);
+}
+
 } // namespace aapt
diff --git a/tools/aapt2/integration-tests/AppOne/res/values/test.xml b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
index 5104f82..2c9e8b8 100644
--- a/tools/aapt2/integration-tests/AppOne/res/values/test.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
@@ -38,4 +38,7 @@
         <attr name="android:text" />
         <attr name="layout_width" />
     </declare-styleable>
+
+    <!-- Declare an empty, resource -->
+    <item type="drawable" name="undefined" />
 </resources>
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index 18498e3..a8e510c 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -296,7 +296,10 @@
                                     IAaptContext* context, SymbolTable* symbols,
                                     xml::IPackageDeclStack* decls) {
   CHECK(reference != nullptr);
-  CHECK(reference->name || reference->id);
+  if (!reference->name && !reference->id) {
+    // This is @null.
+    return true;
+  }
 
   Reference transformed_reference = *reference;
   TransformReferenceFromNamespace(decls, context->GetCompilationPackage(), &transformed_reference);
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 1d0041b..4b56192 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -343,26 +343,19 @@
     return value;
   }
 
-  bool DeserializeReferenceFromPb(const pb::Reference& pb_ref,
-                                  Reference* out_ref) {
+  bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref) {
     out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
     out_ref->private_reference = pb_ref.private_();
 
-    if (!pb_ref.has_id() && !pb_ref.has_symbol_idx()) {
-      return false;
-    }
-
     if (pb_ref.has_id()) {
       out_ref->id = ResourceId(pb_ref.id());
     }
 
     if (pb_ref.has_symbol_idx()) {
-      const std::string str_symbol =
-          util::GetString(*symbol_pool_, pb_ref.symbol_idx());
+      const std::string str_symbol = util::GetString(*symbol_pool_, pb_ref.symbol_idx());
       ResourceNameRef name_ref;
       if (!ResourceUtils::ParseResourceName(str_symbol, &name_ref, nullptr)) {
-        diag_->Error(DiagMessage(source_) << "invalid reference name '"
-                                          << str_symbol << "'");
+        diag_->Error(DiagMessage(source_) << "invalid reference name '" << str_symbol << "'");
         return false;
       }
 
diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp
index de10bb8..d87d64e 100644
--- a/tools/aapt2/proto/TableProtoSerializer.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer.cpp
@@ -190,8 +190,7 @@
     }
 
     if (ref.name) {
-      StringPool::Ref symbol_ref =
-          symbol_pool_->MakeRef(ref.name.value().ToString());
+      StringPool::Ref symbol_ref = symbol_pool_->MakeRef(ref.name.value().ToString());
       pb_ref->set_symbol_idx(static_cast<uint32_t>(symbol_ref.index()));
     }
 
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 02acedb..f3da780 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -59,8 +59,7 @@
 
   ResourceTableBuilder& AddReference(const android::StringPiece& name, const ResourceId& id,
                                      const android::StringPiece& ref) {
-    return AddValue(name, id,
-                    util::make_unique<Reference>(ParseNameOrDie(ref)));
+    return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref)));
   }
 
   ResourceTableBuilder& AddString(const android::StringPiece& name,
@@ -111,8 +110,8 @@
   ResourceTableBuilder& AddValue(const android::StringPiece& name, const ConfigDescription& config,
                                  const ResourceId& id, std::unique_ptr<Value> value) {
     ResourceName res_name = ParseNameOrDie(name);
-    CHECK(table_->AddResourceAllowMangled(res_name, id, config, {},
-                                          std::move(value), &diagnostics_));
+    CHECK(table_->AddResourceAllowMangled(res_name, id, config, {}, std::move(value),
+                                          GetDiagnostics()));
     return *this;
   }
 
@@ -122,7 +121,7 @@
     Symbol symbol;
     symbol.state = state;
     symbol.allow_new = allow_new;
-    CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, &diagnostics_));
+    CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, GetDiagnostics()));
     return *this;
   }
 
@@ -131,7 +130,6 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceTableBuilder);
 
-  DummyDiagnosticsImpl diagnostics_;
   std::unique_ptr<ResourceTable> table_ = util::make_unique<ResourceTable>();
 };
 
diff --git a/tools/aapt2/test/Common.cpp b/tools/aapt2/test/Common.cpp
new file mode 100644
index 0000000..0fabbc4
--- /dev/null
+++ b/tools/aapt2/test/Common.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test/Common.h"
+
+namespace aapt {
+namespace test {
+
+struct DummyDiagnosticsImpl : public IDiagnostics {
+  void Log(Level level, DiagMessageActual& actual_msg) override {
+    switch (level) {
+      case Level::Note:
+        return;
+
+      case Level::Warn:
+        std::cerr << actual_msg.source << ": warn: " << actual_msg.message << "." << std::endl;
+        break;
+
+      case Level::Error:
+        std::cerr << actual_msg.source << ": error: " << actual_msg.message << "." << std::endl;
+        break;
+    }
+  }
+};
+
+IDiagnostics* GetDiagnostics() {
+  static DummyDiagnosticsImpl diag;
+  return &diag;
+}
+
+template <>
+Value* GetValueForConfigAndProduct<Value>(ResourceTable* table,
+                                          const android::StringPiece& res_name,
+                                          const ConfigDescription& config,
+                                          const android::StringPiece& product) {
+  Maybe<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name));
+  if (result) {
+    ResourceConfigValue* config_value = result.value().entry->FindValue(config, product);
+    if (config_value) {
+      return config_value->value.get();
+    }
+  }
+  return nullptr;
+}
+
+}  // namespace test
+}  // namespace aapt
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index a937de8..0585148 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -46,27 +46,7 @@
 namespace aapt {
 namespace test {
 
-struct DummyDiagnosticsImpl : public IDiagnostics {
-  void Log(Level level, DiagMessageActual& actual_msg) override {
-    switch (level) {
-      case Level::Note:
-        return;
-
-      case Level::Warn:
-        std::cerr << actual_msg.source << ": warn: " << actual_msg.message << "." << std::endl;
-        break;
-
-      case Level::Error:
-        std::cerr << actual_msg.source << ": error: " << actual_msg.message << "." << std::endl;
-        break;
-    }
-  }
-};
-
-inline IDiagnostics* GetDiagnostics() {
-  static DummyDiagnosticsImpl diag;
-  return &diag;
-}
+IDiagnostics* GetDiagnostics();
 
 inline ResourceName ParseNameOrDie(const android::StringPiece& str) {
   ResourceNameRef ref;
@@ -80,7 +60,7 @@
   return config;
 }
 
-template <typename T>
+template <typename T = Value>
 T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece& res_name,
                                const ConfigDescription& config,
                                const android::StringPiece& product) {
@@ -94,13 +74,19 @@
   return nullptr;
 }
 
-template <typename T>
+template <>
+Value* GetValueForConfigAndProduct<Value>(ResourceTable* table,
+                                          const android::StringPiece& res_name,
+                                          const ConfigDescription& config,
+                                          const android::StringPiece& product);
+
+template <typename T = Value>
 T* GetValueForConfig(ResourceTable* table, const android::StringPiece& res_name,
                      const ConfigDescription& config) {
   return GetValueForConfigAndProduct<T>(table, res_name, config, {});
 }
 
-template <typename T>
+template <typename T = Value>
 T* GetValue(ResourceTable* table, const android::StringPiece& res_name) {
   return GetValueForConfig<T>(table, res_name, {});
 }
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index b133a44..a4b3bf2a 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -1,7 +1,10 @@
 package android.net.wifi;
 
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
@@ -20,6 +23,7 @@
 
 /** @hide */
 @SystemApi
+@SystemService(Context.WIFI_RTT_SERVICE)
 public class RttManager {
 
     private static final boolean DBG = false;
@@ -167,6 +171,7 @@
 
     /** @deprecated Use the new {@link android.net.wifi.RttManager#getRttCapabilities()} API.*/
     @Deprecated
+    @SuppressLint("Doclava125")
     public Capabilities getCapabilities() {
         return new Capabilities();
     }
@@ -990,7 +995,7 @@
      * @exception throw IllegalArgumentException when params are illegal
      *            throw IllegalStateException when RttCapabilities do not exist
      */
-
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startRanging(RttParams[] params, RttListener listener) {
         int index  = 0;
         for(RttParams rttParam : params) {
@@ -1006,6 +1011,7 @@
                 0, putListener(listener), parcelableParams);
     }
 
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void stopRanging(RttListener listener) {
         validateChannel();
         mAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
@@ -1039,6 +1045,7 @@
      * @param callback Callback for responder enabling/disabling result.
      * @throws IllegalArgumentException If {@code callback} is null.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void enableResponder(ResponderCallback callback) {
         if (callback == null) {
             throw new IllegalArgumentException("callback cannot be null");
@@ -1058,6 +1065,7 @@
      * @param callback The same callback used for enabling responder.
      * @throws IllegalArgumentException If {@code callback} is null.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void disableResponder(ResponderCallback callback) {
         if (callback == null) {
             throw new IllegalArgumentException("callback cannot be null");
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f7333e2..91fc2f7 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -67,6 +67,8 @@
     public static final String updateIdentiferVarName = "update_identifier";
     /** {@hide} */
     public static final int INVALID_NETWORK_ID = -1;
+    /** {@hide} */
+    public static final int LOCAL_ONLY_NETWORK_ID = -2;
 
     /** {@hide} */
     private String mPasspointManagementObjectTree;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 58df4ee..c89a9a4 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -17,9 +17,12 @@
 package android.net.wifi;
 
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.net.ConnectivityManager;
@@ -56,27 +59,30 @@
 
 /**
  * This class provides the primary API for managing all aspects of Wi-Fi
- * connectivity. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}.
- * On releases before NYC, it should only be obtained from an application context, and not from
- * any other derived context to avoid memory leaks within the calling process.
-
+ * connectivity.
+ * <p>
+ * On releases before {@link android.os.Build.VERSION_CODES#N}, this object
+ * should only be obtained from an {@linkplain Context#getApplicationContext()
+ * application context}, and not from any other derived context to avoid memory
+ * leaks within the calling process.
+ * <p>
  * It deals with several categories of items:
  * <ul>
- * <li>The list of configured networks. The list can be viewed and updated,
- * and attributes of individual entries can be modified.</li>
+ * <li>The list of configured networks. The list can be viewed and updated, and
+ * attributes of individual entries can be modified.</li>
  * <li>The currently active Wi-Fi network, if any. Connectivity can be
- * established or torn down, and dynamic information about the state of
- * the network can be queried.</li>
- * <li>Results of access point scans, containing enough information to
- * make decisions about what access point to connect to.</li>
- * <li>It defines the names of various Intent actions that are broadcast
- * upon any sort of change in Wi-Fi state.
+ * established or torn down, and dynamic information about the state of the
+ * network can be queried.</li>
+ * <li>Results of access point scans, containing enough information to make
+ * decisions about what access point to connect to.</li>
+ * <li>It defines the names of various Intent actions that are broadcast upon
+ * any sort of change in Wi-Fi state.
  * </ul>
- * This is the API to use when performing Wi-Fi specific operations. To
- * perform operations that pertain to network connectivity at an abstract
- * level, use {@link android.net.ConnectivityManager}.
+ * This is the API to use when performing Wi-Fi specific operations. To perform
+ * operations that pertain to network connectivity at an abstract level, use
+ * {@link android.net.ConnectivityManager}.
  */
+@SystemService(Context.WIFI_SERVICE)
 public class WifiManager {
 
     private static final String TAG = "WifiManager";
@@ -966,6 +972,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL)
     public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
         try {
             ParceledListSlice<WifiConfiguration> parceledList =
@@ -981,6 +988,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL)
     public WifiConnectionStatistics getConnectionStatistics() {
         try {
             return mService.getConnectionStatistics();
@@ -1522,6 +1530,7 @@
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public boolean startScan(WorkSource workSource) {
         try {
             String packageName = mContext.getOpPackageName();
@@ -1542,6 +1551,7 @@
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public boolean startLocationRestrictedScan(WorkSource workSource) {
         return false;
     }
@@ -1556,6 +1566,7 @@
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public boolean isBatchedScanSupported() {
         return false;
     }
@@ -1569,6 +1580,7 @@
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public List<BatchedScanResult> getBatchedScanResults() {
         return null;
     }
@@ -1808,6 +1820,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
         String packageName = mContext.getOpPackageName();
 
@@ -2053,6 +2066,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
     public int getWifiApState() {
         try {
             return mService.getWifiApEnabledState();
@@ -2069,6 +2083,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
     public boolean isWifiApEnabled() {
         return getWifiApState() == WIFI_AP_STATE_ENABLED;
     }
@@ -2080,6 +2095,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
     public WifiConfiguration getWifiApConfiguration() {
         try {
             return mService.getWifiApConfiguration();
@@ -2095,6 +2111,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
     public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
         try {
             mService.setWifiApConfiguration(wifiConfig);
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index c02ceef..f47d5ca 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -16,7 +16,10 @@
 
 package android.net.wifi;
 
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
@@ -40,12 +43,10 @@
 
 /**
  * This class provides a way to scan the Wifi universe around the device
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context
- * .WIFI_SCANNING_SERVICE)}.
  * @hide
  */
 @SystemApi
+@SystemService(Context.WIFI_SCANNING_SERVICE)
 public class WifiScanner {
 
     /** no band specified; use channel list instead */
@@ -732,6 +733,7 @@
      *                 key for this scan, and must also be specified to cancel the scan. Multiple
      *                 scans should also not share this object.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startBackgroundScan(ScanSettings settings, ScanListener listener) {
         startBackgroundScan(settings, listener, null);
     }
@@ -744,6 +746,7 @@
      *                 key for this scan, and must also be specified to cancel the scan. Multiple
      *                 scans should also not share this object.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startBackgroundScan(ScanSettings settings, ScanListener listener,
             WorkSource workSource) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
@@ -761,6 +764,7 @@
      * @param listener specifies which scan to cancel; must be same object as passed in {@link
      *  #startBackgroundScan}
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void stopBackgroundScan(ScanListener listener) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
         int key = removeListener(listener);
@@ -772,6 +776,7 @@
      * reports currently available scan results on appropriate listeners
      * @return true if all scan results were reported correctly
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public boolean getScanResults() {
         validateChannel();
         Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
@@ -786,6 +791,7 @@
      *                 key for this scan, and must also be specified to cancel the scan. Multiple
      *                 scans should also not share this object.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startScan(ScanSettings settings, ScanListener listener) {
         startScan(settings, listener, null);
     }
@@ -799,6 +805,7 @@
      *                 key for this scan, and must also be specified to cancel the scan. Multiple
      *                 scans should also not share this object.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startScan(ScanSettings settings, ScanListener listener, WorkSource workSource) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
         int key = addListener(listener);
@@ -815,6 +822,7 @@
      * hasn't been called on the listener, ignored otherwise
      * @param listener
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void stopScan(ScanListener listener) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
         int key = removeListener(listener);
@@ -962,6 +970,7 @@
      * @param bssidInfos access points to watch
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void configureWifiChange(
             int rssiSampleSize,                             /* sample size for RSSI averaging */
             int lostApSampleSize,                           /* samples to confirm AP's loss */
@@ -995,6 +1004,7 @@
      *                 provided on {@link #stopTrackingWifiChange}
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void startTrackingWifiChange(WifiChangeListener listener) {
         throw new UnsupportedOperationException();
     }
@@ -1005,6 +1015,7 @@
      * #stopTrackingWifiChange}
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void stopTrackingWifiChange(WifiChangeListener listener) {
         throw new UnsupportedOperationException();
     }
@@ -1012,6 +1023,7 @@
     /** @hide */
     @SystemApi
     @Deprecated
+    @SuppressLint("Doclava125")
     public void configureWifiChange(WifiChangeSettings settings) {
         throw new UnsupportedOperationException();
     }
@@ -1067,6 +1079,7 @@
      *                 also be provided on {@link #stopTrackingBssids}
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void startTrackingBssids(BssidInfo[] bssidInfos,
                                     int apLostThreshold, BssidListener listener) {
         throw new UnsupportedOperationException();
@@ -1077,6 +1090,7 @@
      * @param listener same object provided in {@link #startTrackingBssids}
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void stopTrackingBssids(BssidListener listener) {
         throw new UnsupportedOperationException();
     }
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index d3ed792..c22daaf 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -48,9 +49,7 @@
 
 /**
  * This class provides the primary API for managing Wi-Fi Aware operations:
- * discovery and peer-to-peer data connections. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.WIFI_AWARE_SERVICE)}.
+ * discovery and peer-to-peer data connections.
  * <p>
  * The class provides access to:
  * <ul>
@@ -120,6 +119,7 @@
  *        {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}.
  *    </ul>
  */
+@SystemService(Context.WIFI_AWARE_SERVICE)
 public class WifiAwareManager {
     private static final String TAG = "WifiAwareManager";
     private static final boolean DBG = false;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index c93ac7b..95d0a79 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -17,6 +17,7 @@
 package android.net.wifi.p2p;
 
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.net.wifi.WpsInfo;
@@ -119,9 +120,6 @@
  * {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer
  * operations.
  *
- * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.WIFI_P2P_SERVICE)}.
- *
  * {@see WifiP2pConfig}
  * {@see WifiP2pInfo}
  * {@see WifiP2pGroup}
@@ -129,6 +127,7 @@
  * {@see WifiP2pDeviceList}
  * {@see android.net.wifi.WpsInfo}
  */
+@SystemService(Context.WIFI_P2P_SERVICE)
 public class WifiP2pManager {
     private static final String TAG = "WifiP2pManager";
     /**