Merge "Disable force-dark"
diff --git a/api/system-current.txt b/api/system-current.txt
index cba137a..8714c0f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1843,7 +1843,9 @@
     field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessChangeEvent> CREATOR;
     field public final float batteryLevel;
     field public final float brightness;
+    field public final long colorSampleDuration;
     field public final int colorTemperature;
+    field @Nullable public final long[] colorValueBuckets;
     field public final boolean isDefaultBrightnessConfig;
     field public final boolean isUserSetBrightness;
     field public final float lastBrightness;
@@ -5520,6 +5522,8 @@
 
   public final class PermissionControllerManager {
     method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
+    field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
+    field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
     field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
     field public static final int REASON_MALWARE = 1; // 0x1
   }
@@ -5533,7 +5537,7 @@
     ctor public PermissionControllerService();
     method public final void attachBaseContext(android.content.Context);
     method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract int onCountPermissionApps(@NonNull java.util.List<java.lang.String>, boolean, boolean);
+    method public abstract int onCountPermissionApps(@NonNull java.util.List<java.lang.String>, int);
     method @NonNull public abstract java.util.List<android.permission.RuntimePermissionPresentationInfo> onGetAppPermissions(@NonNull String);
     method @NonNull public abstract java.util.List<android.permission.RuntimePermissionUsageInfo> onGetPermissionUsages(boolean, long);
     method public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream);
diff --git a/api/test-current.txt b/api/test-current.txt
index 2a7aa17..2a9a149 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -660,7 +660,9 @@
     field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessChangeEvent> CREATOR;
     field public final float batteryLevel;
     field public final float brightness;
+    field public final long colorSampleDuration;
     field public final int colorTemperature;
+    field @Nullable public final long[] colorValueBuckets;
     field public final boolean isDefaultBrightnessConfig;
     field public final boolean isUserSetBrightness;
     field public final float lastBrightness;
@@ -1692,6 +1694,8 @@
 
   public final class PermissionControllerManager {
     method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
+    field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
+    field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
     field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
     field public static final int REASON_MALWARE = 1; // 0x1
   }
diff --git a/core/java/android/hardware/display/BrightnessChangeEvent.java b/core/java/android/hardware/display/BrightnessChangeEvent.java
index 02eb28c..c6186bb 100644
--- a/core/java/android/hardware/display/BrightnessChangeEvent.java
+++ b/core/java/android/hardware/display/BrightnessChangeEvent.java
@@ -16,11 +16,15 @@
 
 package android.hardware.display;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Objects;
+
 /**
  * Data about a brightness settings change.
  *
@@ -72,12 +76,29 @@
     /** Whether brightness curve includes a user brightness point */
     public final boolean isUserSetBrightness;
 
+    /**
+     * Histogram counting how many times a pixel of a given value was displayed onscreen for the
+     * Value component of HSV if the device supports color sampling, if the device does not support
+     * color sampling the value will be null.
+     * The buckets of the histogram are evenly weighted, the number of buckets is device specific.
+     * For example if we had {10, 6, 4, 1} this means that 10 pixels were in the range
+     * [0x00,0x3f], 6 pixels were in the range [0x40,0x7f] etc.
+     */
+    @Nullable
+    public final long[] colorValueBuckets;
+
+    /**
+     * How many milliseconds of data are contained in the colorValueBuckets.
+     */
+    public final long colorSampleDuration;
+
 
     /** @hide */
     private BrightnessChangeEvent(float brightness, long timeStamp, String packageName,
             int userId, float[] luxValues, long[] luxTimestamps, float batteryLevel,
             float powerBrightnessFactor, boolean nightMode, int colorTemperature,
-            float lastBrightness, boolean isDefaultBrightnessConfig, boolean isUserSetBrightness) {
+            float lastBrightness, boolean isDefaultBrightnessConfig, boolean isUserSetBrightness,
+            long[] colorValueBuckets, long colorSampleDuration) {
         this.brightness = brightness;
         this.timeStamp = timeStamp;
         this.packageName = packageName;
@@ -91,6 +112,8 @@
         this.lastBrightness = lastBrightness;
         this.isDefaultBrightnessConfig = isDefaultBrightnessConfig;
         this.isUserSetBrightness = isUserSetBrightness;
+        this.colorValueBuckets = colorValueBuckets;
+        this.colorSampleDuration = colorSampleDuration;
     }
 
     /** @hide */
@@ -108,6 +131,8 @@
         this.lastBrightness = other.lastBrightness;
         this.isDefaultBrightnessConfig = other.isDefaultBrightnessConfig;
         this.isUserSetBrightness = other.isUserSetBrightness;
+        this.colorValueBuckets = other.colorValueBuckets;
+        this.colorSampleDuration = other.colorSampleDuration;
     }
 
     private BrightnessChangeEvent(Parcel source) {
@@ -124,6 +149,8 @@
         lastBrightness = source.readFloat();
         isDefaultBrightnessConfig = source.readBoolean();
         isUserSetBrightness = source.readBoolean();
+        colorValueBuckets = source.createLongArray();
+        colorSampleDuration = source.readLong();
     }
 
     public static final Creator<BrightnessChangeEvent> CREATOR =
@@ -156,6 +183,8 @@
         dest.writeFloat(lastBrightness);
         dest.writeBoolean(isDefaultBrightnessConfig);
         dest.writeBoolean(isUserSetBrightness);
+        dest.writeLongArray(colorValueBuckets);
+        dest.writeLong(colorSampleDuration);
     }
 
     /** @hide */
@@ -173,6 +202,8 @@
         private float mLastBrightness;
         private boolean mIsDefaultBrightnessConfig;
         private boolean mIsUserSetBrightness;
+        private long[] mColorValueBuckets;
+        private long mColorSampleDuration;
 
         /** {@see BrightnessChangeEvent#brightness} */
         public Builder setBrightness(float brightness) {
@@ -252,12 +283,21 @@
             return this;
         }
 
+        /** {@see BrightnessChangeEvent#valueBuckets} */
+        public Builder setColorValues(@NonNull long[] colorValueBuckets, long colorSampleDuration) {
+            Objects.requireNonNull(colorValueBuckets);
+            mColorValueBuckets = colorValueBuckets;
+            mColorSampleDuration = colorSampleDuration;
+            return this;
+        }
+
         /** Builds a BrightnessChangeEvent */
         public BrightnessChangeEvent build() {
             return new BrightnessChangeEvent(mBrightness, mTimeStamp,
                     mPackageName, mUserId, mLuxValues, mLuxTimestamps, mBatteryLevel,
                     mPowerBrightnessFactor, mNightMode, mColorTemperature, mLastBrightness,
-                    mIsDefaultBrightnessConfig, mIsUserSetBrightness);
+                    mIsDefaultBrightnessConfig, mIsUserSetBrightness, mColorValueBuckets,
+                    mColorSampleDuration);
         }
     }
 }
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index 5dd869f..ee6744b 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -32,8 +32,8 @@
     void getRuntimePermissionBackup(in UserHandle user, in ParcelFileDescriptor pipe);
     void getAppPermissions(String packageName, in RemoteCallback callback);
     void revokeRuntimePermission(String packageName, String permissionName);
-    void countPermissionApps(in List<String> permissionNames, boolean countOnlyGranted,
-            boolean countSystem, in RemoteCallback callback);
+    void countPermissionApps(in List<String> permissionNames, int flags,
+            in RemoteCallback callback);
     void getPermissionUsages(boolean countSystem, long numMillis, in RemoteCallback callback);
     void isApplicationQualifiedForRole(String roleName, String packageName,
             in RemoteCallback callback);
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index b59d0c7..850d020 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -20,6 +20,7 @@
 
 import static com.android.internal.util.Preconditions.checkArgumentNonnegative;
 import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
+import static com.android.internal.util.Preconditions.checkFlagsArgument;
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.internal.util.Preconditions.checkStringNotEmpty;
 
@@ -113,6 +114,20 @@
      */
     public static final int REASON_INSTALLER_POLICY_VIOLATION = 2;
 
+    /** @hide */
+    @IntDef(prefix = { "COUNT_" }, value = {
+            COUNT_ONLY_WHEN_GRANTED,
+            COUNT_WHEN_SYSTEM,
+    }, flag = true)
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CountPermissionAppsFlag {}
+
+    /** Count an app only if the permission is granted to the app. */
+    public static final int COUNT_ONLY_WHEN_GRANTED = 1;
+
+    /** Count and app even if it is a system app. */
+    public static final int COUNT_WHEN_SYSTEM = 2;
+
     /**
      * Callback for delivering the result of {@link #revokeRuntimePermissions}.
      */
@@ -162,7 +177,7 @@
      */
     public interface OnCountPermissionAppsResultCallback {
         /**
-         * The result for {@link #countPermissionApps(List, boolean, boolean,
+         * The result for {@link #countPermissionApps(List, int,
          * OnCountPermissionAppsResultCallback, Handler)}.
          *
          * @param numApps The number of apps that have one of the permissions
@@ -302,8 +317,8 @@
      * Count how many apps have one of a set of permissions.
      *
      * @param permissionNames The permissions the app might have
-     * @param countOnlyGranted Count an app only if the permission is granted to the app
-     * @param countSystem Also count system apps
+     * @param flags Modify which apps to count. By default all non-system apps that request a
+     *              permission are counted
      * @param callback Callback to receive the result
      * @param handler Handler on which to invoke the callback
      *
@@ -311,13 +326,14 @@
      */
     @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
     public void countPermissionApps(@NonNull List<String> permissionNames,
-            boolean countOnlyGranted, boolean countSystem,
+            @CountPermissionAppsFlag int flags,
             @NonNull OnCountPermissionAppsResultCallback callback, @Nullable Handler handler) {
         checkCollectionElementsNotNull(permissionNames, "permissionNames");
+        checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED);
         checkNotNull(callback);
 
         sRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(sRemoteService,
-                permissionNames, countOnlyGranted, countSystem, callback,
+                permissionNames, flags, callback,
                 handler == null ? sRemoteService.getHandler() : handler));
     }
 
@@ -731,20 +747,17 @@
             AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
         private final @NonNull List<String> mPermissionNames;
         private final @NonNull OnCountPermissionAppsResultCallback mCallback;
-        private final boolean mCountOnlyGranted;
-        private final boolean mCountSystem;
+        private final @CountPermissionAppsFlag int mFlags;
 
         private final @NonNull RemoteCallback mRemoteCallback;
 
         private PendingCountPermissionAppsRequest(@NonNull RemoteService service,
-                @NonNull List<String> permissionNames, boolean countOnlyGranted,
-                boolean countSystem, @NonNull OnCountPermissionAppsResultCallback callback,
-                @NonNull Handler handler) {
+                @NonNull List<String> permissionNames, @CountPermissionAppsFlag int flags,
+                @NonNull OnCountPermissionAppsResultCallback callback, @NonNull Handler handler) {
             super(service);
 
             mPermissionNames = permissionNames;
-            mCountOnlyGranted = countOnlyGranted;
-            mCountSystem = countSystem;
+            mFlags = flags;
             mCallback = callback;
 
             mRemoteCallback = new RemoteCallback(result -> {
@@ -770,7 +783,7 @@
         public void run() {
             try {
                 getService().getServiceInterface().countPermissionApps(mPermissionNames,
-                        mCountOnlyGranted, mCountSystem, mRemoteCallback);
+                        mFlags, mRemoteCallback);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error counting permission apps", e);
             }
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index 9a58b97..70404c3 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -16,9 +16,13 @@
 
 package android.permission;
 
+import static android.permission.PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED;
+import static android.permission.PermissionControllerManager.COUNT_WHEN_SYSTEM;
+
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkArgumentNonnegative;
 import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
+import static com.android.internal.util.Preconditions.checkFlagsArgument;
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.internal.util.Preconditions.checkStringNotEmpty;
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -37,6 +41,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteCallback;
 import android.os.UserHandle;
+import android.permission.PermissionControllerManager.CountPermissionAppsFlag;
 import android.util.ArrayMap;
 import android.util.Log;
 
@@ -121,13 +126,13 @@
      * Count how many apps have one of a set of permissions.
      *
      * @param permissionNames The permissions the app might have
-     * @param countOnlyGranted Count an app only if the permission is granted to the app
-     * @param countSystem Also count system apps
+     * @param flags Modify which apps to count. By default all non-system apps that request a
+     *              permission are counted
      *
      * @return the number of apps that have one of the permissions
      */
     public abstract int onCountPermissionApps(@NonNull List<String> permissionNames,
-            boolean countOnlyGranted, boolean countSystem);
+            @CountPermissionAppsFlag int flags);
 
     /**
      * Count how many apps have used permissions.
@@ -226,17 +231,18 @@
             }
 
             @Override
-            public void countPermissionApps(List<String> permissionNames, boolean countOnlyGranted,
-                    boolean countSystem, RemoteCallback callback) {
+            public void countPermissionApps(List<String> permissionNames, int flags,
+                    RemoteCallback callback) {
                 checkCollectionElementsNotNull(permissionNames, "permissionNames");
+                checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED);
                 checkNotNull(callback, "callback");
 
                 enforceCallingPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS, null);
 
                 mHandler.sendMessage(
                         obtainMessage(PermissionControllerService::countPermissionApps,
-                                PermissionControllerService.this, permissionNames, countOnlyGranted,
-                                countSystem, callback));
+                                PermissionControllerService.this, permissionNames, flags,
+                                callback));
             }
 
             @Override
@@ -311,8 +317,8 @@
     }
 
     private void countPermissionApps(@NonNull List<String> permissionNames,
-            boolean countOnlyGranted, boolean countSystem, @NonNull RemoteCallback callback) {
-        int numApps = onCountPermissionApps(permissionNames, countOnlyGranted, countSystem);
+            @CountPermissionAppsFlag int flags, @NonNull RemoteCallback callback) {
+        int numApps = onCountPermissionApps(permissionNames, flags);
 
         Bundle result = new Bundle();
         result.putInt(PermissionControllerManager.KEY_RESULT, numApps);
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index e76e096..ea2a25d 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -348,7 +348,7 @@
      */
     public final void setVoiceState(int state) {
         try {
-            mSystemService.setVoiceState(state);
+            mSystemService.setVoiceState(mInterface, state);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -359,7 +359,7 @@
      */
     public final void setTranscription(@NonNull String transcription) {
         try {
-            mSystemService.setTranscription(transcription);
+            mSystemService.setTranscription(mInterface, transcription);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -372,7 +372,7 @@
      */
     public final void clearTranscription(boolean immediate) {
         try {
-            mSystemService.clearTranscription(immediate);
+            mSystemService.clearTranscription(mInterface, immediate);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index e9d72a2..bb9bd52 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -6021,6 +6021,9 @@
                     }
 
                     updateSelection(event);
+                    if (mTextView.hasSelection() && mEndHandle != null) {
+                        mEndHandle.updateMagnifier(event);
+                    }
                     break;
 
                 case MotionEvent.ACTION_UP:
@@ -6028,6 +6031,9 @@
                         break;
                     }
                     updateSelection(event);
+                    if (mEndHandle != null) {
+                        mEndHandle.dismissMagnifier();
+                    }
 
                     // No longer dragging to select text, let the parent intercept events.
                     mTextView.getParent().requestDisallowInterceptTouchEvent(false);
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index b85488f..8dde44e 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -155,15 +155,15 @@
     /**
      * Sets the transcribed voice to the given string.
      */
-    void setTranscription(String transcription);
+    void setTranscription(IVoiceInteractionService service, String transcription);
 
     /**
      * Indicates that the transcription session is finished.
      */
-    void clearTranscription(boolean immediate);
+    void clearTranscription(IVoiceInteractionService service, boolean immediate);
 
     /**
      * Sets the voice state indication based upon the given value.
      */
-    void setVoiceState(int state);
+    void setVoiceState(IVoiceInteractionService service, int state);
 }
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index 96d6eee..dde757b 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -90,6 +90,9 @@
     public static final int RGBA_F16     = 0x16;
     public static final int RGBA_1010102 = 0x2B;
 
+    /** @hide */
+    public static final int HSV_888 = 0x37;
+
     /**
      * @deprecated use {@link android.graphics.ImageFormat#JPEG
      * ImageFormat.JPEG} instead.
@@ -109,6 +112,7 @@
                 info.bytesPerPixel = 4;
                 break;
             case RGB_888:
+            case HSV_888:
                 info.bitsPerPixel = 24;
                 info.bytesPerPixel = 3;
                 break;
@@ -227,6 +231,8 @@
                 return "RGBA_F16";
             case RGBA_1010102:
                 return "RGBA_1010102";
+            case HSV_888:
+                return "HSV_888";
             case JPEG:
                 return "JPEG";
             default:
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
index 1cd3509..fa1426e 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
@@ -52,6 +52,10 @@
     private val MAX_ITEMS = context.resources.getInteger(R.integer.ongoing_appops_dialog_max_apps)
     private val iconFactory = IconDrawableFactory.newInstance(context, true)
     private var dismissDialog: (() -> Unit)? = null
+    private val appsAndTypes = dialogBuilder.appsAndTypes
+            .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
+            { it.second.min() },
+            { it.first }))
 
     init {
         val a = context.theme.obtainStyledAttributes(
@@ -90,10 +94,10 @@
 
         title.setText(dialogBuilder.getDialogTitle())
 
-        val numItems = dialogBuilder.appsAndTypes.size
+        val numItems = appsAndTypes.size
         for (i in 0..(numItems - 1)) {
             if (i >= MAX_ITEMS) break
-            val item = dialogBuilder.appsAndTypes[i]
+            val item = appsAndTypes[i]
             addAppItem(appsList, item.first, item.second, dialogBuilder.types.size > 1)
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
index 2894621..9c1076a 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
@@ -30,8 +30,7 @@
         appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType })
                 .toList()
                 .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
-                        { it.second.min() }, // Sort by "smallest" AppOpp (Location is largest)
-                        { it.first })) // Sort alphabetically bt App Name
+                        { it.second.min() })) // Sort by "smallest" AppOpp (Location is largest)
         types = itemsList.map { it.privacyType }.distinct().sorted()
         val singleApp = appsAndTypes.size == 1
         app = if (singleApp) appsAndTypes[0].first else null
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
index dbe87d1..f7ca51d 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
@@ -44,17 +44,22 @@
         return applicationName.compareTo(other.applicationName)
     }
 
-    var icon: Drawable = context.getDrawable(android.R.drawable.sym_def_app_icon)
-    var applicationName: String
-
-    init {
+    private val applicationInfo: ApplicationInfo? by lazy {
         try {
-            val app: ApplicationInfo = context.packageManager
-                    .getApplicationInfo(packageName, 0)
-            icon = context.packageManager.getApplicationIcon(app)
-            applicationName = context.packageManager.getApplicationLabel(app) as String
-        } catch (e: PackageManager.NameNotFoundException) {
-            applicationName = packageName
+            context.packageManager.getApplicationInfo(packageName, 0)
+        } catch (_: PackageManager.NameNotFoundException) {
+            null
         }
     }
+    val icon: Drawable by lazy {
+        applicationInfo?.let {
+            context.packageManager.getApplicationIcon(it)
+        } ?: context.getDrawable(android.R.drawable.sym_def_app_icon)
+    }
+
+    val applicationName: String by lazy {
+        applicationInfo?.let {
+            context.packageManager.getApplicationLabel(it) as String
+        } ?: packageName
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
index f163b88..b6e0d90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
@@ -37,7 +37,7 @@
                 "Bar", TEST_UID, context))
         val bar3 = PrivacyItem(Privacy.TYPE_LOCATION, PrivacyApplication(
                 "Bar", TEST_UID, context))
-        val foo0 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
+        val foo0 = PrivacyItem(Privacy.TYPE_MICROPHONE, PrivacyApplication(
                 "Foo", TEST_UID, context))
         val baz1 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
                 "Baz", TEST_UID, context))
@@ -50,10 +50,11 @@
         assertEquals(3, list.size)
         val appsList = list.map { it.first }
         val typesList = list.map { it.second }
+        // List is sorted by number of types and then by types
         assertEquals(listOf("Bar", "Baz", "Foo"), appsList.map { it.packageName })
         assertEquals(listOf(Privacy.TYPE_CAMERA, Privacy.TYPE_LOCATION), typesList[0])
         assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[1])
-        assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[2])
+        assertEquals(listOf(Privacy.TYPE_MICROPHONE), typesList[2])
     }
 
     @Test
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 019d726..727cf0e 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -27,12 +27,17 @@
 import android.content.IntentFilter;
 import android.content.pm.ParceledListSlice;
 import android.database.ContentObserver;
+import android.graphics.PixelFormat;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.hardware.display.AmbientBrightnessDayStats;
 import android.hardware.display.BrightnessChangeEvent;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.DisplayedContentSample;
+import android.hardware.display.DisplayedContentSamplingAttributes;
 import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Environment;
@@ -48,6 +53,7 @@
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.Xml;
+import android.view.Display;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -55,6 +61,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.RingBuffer;
+import com.android.server.LocalServices;
 
 import libcore.io.IoUtils;
 
@@ -111,6 +118,8 @@
     private static final String ATTR_DEFAULT_CONFIG = "defaultConfig";
     private static final String ATTR_POWER_SAVE = "powerSaveFactor";
     private static final String ATTR_USER_POINT = "userPoint";
+    private static final String ATTR_COLOR_SAMPLE_DURATION = "colorSampleDuration";
+    private static final String ATTR_COLOR_VALUE_BUCKETS = "colorValueBuckets";
 
     private static final int MSG_BACKGROUND_START = 0;
     private static final int MSG_BRIGHTNESS_CHANGED = 1;
@@ -119,6 +128,10 @@
 
     private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
+    private static final long COLOR_SAMPLE_DURATION = TimeUnit.SECONDS.toSeconds(10);
+    // Sample chanel 2 of HSV which is the Value component.
+    private static final int COLOR_SAMPLE_COMPONENT_MASK = 0x1 << 2;
+
     // Lock held while accessing mEvents, is held while writing events to flash.
     private final Object mEventsLock = new Object();
     @GuardedBy("mEventsLock")
@@ -136,12 +149,16 @@
     private final ContentResolver mContentResolver;
     private final Handler mBgHandler;
 
-    // mBroadcastReceiver,  mSensorListener, mSettingsObserver and mSensorRegistered
-    // should only be used on the mBgHandler thread.
+    // These members should only be accessed on the mBgHandler thread.
     private BroadcastReceiver mBroadcastReceiver;
     private SensorListener mSensorListener;
     private SettingsObserver mSettingsObserver;
+    private DisplayListener mDisplayListener;
     private boolean mSensorRegistered;
+    private boolean mColorSamplingEnabled;
+    private int mNoFramesToSample;
+    private float mFrameRate;
+    // End of block of members that should only be accessed on the mBgHandler thread.
 
     private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL;
 
@@ -208,6 +225,7 @@
             mLastBrightness = initialBrightness;
             mStarted = true;
         }
+        enableColorSampling();
     }
 
     /** Stop listening for events */
@@ -226,6 +244,7 @@
         synchronized (mDataCollectionLock) {
             mStarted = false;
         }
+        disableColorSampling();
     }
 
     public void onSwitchUser(@UserIdInt int newUserId) {
@@ -367,6 +386,17 @@
         builder.setColorTemperature(mInjector.getColorTemperature(mContext,
                 UserHandle.USER_CURRENT));
 
+        if (mColorSamplingEnabled) {
+            DisplayedContentSample sample = mInjector.sampleColor(mNoFramesToSample);
+            if (sample != null && sample.getSampleComponent(
+                    DisplayedContentSample.ColorComponent.CHANNEL2) != null) {
+                float numMillis = (sample.getNumFrames() / mFrameRate) * 1000.0f;
+                builder.setColorValues(
+                        sample.getSampleComponent(DisplayedContentSample.ColorComponent.CHANNEL2),
+                        Math.round(numMillis));
+            }
+        }
+
         BrightnessChangeEvent event = builder.build();
         if (DEBUG) {
             Slog.d(TAG, "Event " + event.brightness + " " + event.packageName);
@@ -541,6 +571,19 @@
                 }
                 out.attribute(null, ATTR_LUX, luxValues.toString());
                 out.attribute(null, ATTR_LUX_TIMESTAMPS, luxTimestamps.toString());
+                if (toWrite[i].colorValueBuckets != null
+                        && toWrite[i].colorValueBuckets.length > 0) {
+                    out.attribute(null, ATTR_COLOR_SAMPLE_DURATION,
+                            Long.toString(toWrite[i].colorSampleDuration));
+                    StringBuilder buckets = new StringBuilder();
+                    for (int j = 0; j < toWrite[i].colorValueBuckets.length; ++j) {
+                        if (j > 0) {
+                            buckets.append(',');
+                        }
+                        buckets.append(Long.toString(toWrite[i].colorValueBuckets[j]));
+                    }
+                    out.attribute(null, ATTR_COLOR_VALUE_BUCKETS, buckets.toString());
+                }
                 out.endTag(null, TAG_EVENT);
             }
         }
@@ -628,6 +671,20 @@
                         builder.setUserBrightnessPoint(Boolean.parseBoolean(userPoint));
                     }
 
+                    String colorSampleDurationString =
+                            parser.getAttributeValue(null, ATTR_COLOR_SAMPLE_DURATION);
+                    String colorValueBucketsString =
+                            parser.getAttributeValue(null, ATTR_COLOR_VALUE_BUCKETS);
+                    if (colorSampleDurationString != null && colorValueBucketsString != null) {
+                        long colorSampleDuration = Long.parseLong(colorSampleDurationString);
+                        String[] buckets = colorValueBucketsString.split(",");
+                        long[] bucketValues = new long[buckets.length];
+                        for (int i = 0; i < bucketValues.length; ++i) {
+                            bucketValues[i] = Long.parseLong(buckets[i]);
+                        }
+                        builder.setColorValues(bucketValues, colorSampleDuration);
+                    }
+
                     BrightnessChangeEvent event = builder.build();
                     if (DEBUG) {
                         Slog.i(TAG, "Read event " + event.brightness
@@ -695,6 +752,73 @@
 
     private void dumpLocal(PrintWriter pw) {
         pw.println("  mSensorRegistered=" + mSensorRegistered);
+        pw.println("  mColorSamplingEnabled=" + mColorSamplingEnabled);
+        pw.println("  mNoFramesToSample=" + mNoFramesToSample);
+        pw.println("  mFrameRate=" + mFrameRate);
+    }
+
+    private void enableColorSampling() {
+        if (!mInjector.isBrightnessModeAutomatic(mContentResolver)
+                || !mInjector.isInteractive(mContext)
+                || mColorSamplingEnabled) {
+            return;
+        }
+
+        mFrameRate = mInjector.getFrameRate(mContext);
+        if (mFrameRate <= 0) {
+            Slog.wtf(TAG, "Default display has a zero or negative framerate.");
+            return;
+        }
+        mNoFramesToSample = (int) (mFrameRate * COLOR_SAMPLE_DURATION);
+
+        DisplayedContentSamplingAttributes attributes = mInjector.getSamplingAttributes();
+        if (DEBUG && attributes != null) {
+            Slog.d(TAG, "Color sampling"
+                    + " mask=0x" + Integer.toHexString(attributes.getComponentMask())
+                    + " dataSpace=0x" + Integer.toHexString(attributes.getDataspace())
+                    + " pixelFormat=0x" + Integer.toHexString(attributes.getPixelFormat()));
+        }
+        // Do we support sampling the Value component of HSV
+        if (attributes != null && attributes.getPixelFormat() == PixelFormat.HSV_888
+                && (attributes.getComponentMask() & COLOR_SAMPLE_COMPONENT_MASK) != 0) {
+
+            mColorSamplingEnabled = mInjector.enableColorSampling(/* enable= */true,
+                    mNoFramesToSample);
+            if (DEBUG) {
+                Slog.i(TAG, "turning on color sampling for "
+                        + mNoFramesToSample + " frames, success=" + mColorSamplingEnabled);
+            }
+        }
+        if (mColorSamplingEnabled && mDisplayListener == null) {
+            mDisplayListener = new DisplayListener();
+            mInjector.registerDisplayListener(mContext, mDisplayListener, mBgHandler);
+        }
+    }
+
+    private void disableColorSampling() {
+        if (!mColorSamplingEnabled) {
+            return;
+        }
+        mInjector.enableColorSampling(/* enable= */ false, /* noFrames= */ 0);
+        mColorSamplingEnabled = false;
+        if (mDisplayListener != null) {
+            mInjector.unRegisterDisplayListener(mContext, mDisplayListener);
+            mDisplayListener = null;
+        }
+        if (DEBUG) {
+            Slog.i(TAG, "turning off color sampling");
+        }
+    }
+
+    private void updateColorSampling() {
+        if (!mColorSamplingEnabled) {
+            return;
+        }
+        float frameRate = mInjector.getFrameRate(mContext);
+        if (frameRate != mFrameRate) {
+            disableColorSampling();
+            enableColorSampling();
+        }
     }
 
     public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(int userId) {
@@ -768,6 +892,26 @@
         }
     }
 
+    private final class DisplayListener implements DisplayManager.DisplayListener {
+
+        @Override
+        public void onDisplayAdded(int displayId) {
+            // Ignore
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            // Ignore
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            if (displayId == Display.DEFAULT_DISPLAY) {
+                updateColorSampling();
+            }
+        }
+    }
+
     private final class SettingsObserver extends ContentObserver {
         public SettingsObserver(Handler handler) {
             super(handler);
@@ -828,9 +972,11 @@
                     break;
                 case MSG_START_SENSOR_LISTENER:
                     startSensorListener();
+                    enableColorSampling();
                     break;
                 case MSG_STOP_SENSOR_LISTENER:
                     stopSensorListener();
+                    disableColorSampling();
                     break;
             }
         }
@@ -957,5 +1103,44 @@
         public boolean isNightModeActive(Context context, int userId) {
             return new ColorDisplayController(context, userId).isActivated();
         }
+
+        public DisplayedContentSample sampleColor(int noFramesToSample) {
+            final DisplayManagerInternal displayManagerInternal =
+                    LocalServices.getService(DisplayManagerInternal.class);
+            return displayManagerInternal.getDisplayedContentSample(
+                   Display.DEFAULT_DISPLAY, noFramesToSample, 0);
+        }
+
+        public float getFrameRate(Context context) {
+            final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
+            Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+            return display.getRefreshRate();
+        }
+
+        public DisplayedContentSamplingAttributes getSamplingAttributes() {
+            final DisplayManagerInternal displayManagerInternal =
+                    LocalServices.getService(DisplayManagerInternal.class);
+            return displayManagerInternal.getDisplayedContentSamplingAttributes(
+                    Display.DEFAULT_DISPLAY);
+        }
+
+        public boolean enableColorSampling(boolean enable, int noFrames) {
+            final DisplayManagerInternal displayManagerInternal =
+                    LocalServices.getService(DisplayManagerInternal.class);
+            return displayManagerInternal.setDisplayedContentSamplingEnabled(
+                    Display.DEFAULT_DISPLAY, enable, COLOR_SAMPLE_COMPONENT_MASK, noFrames);
+        }
+
+        public void registerDisplayListener(Context context,
+                DisplayManager.DisplayListener listener, Handler handler) {
+            final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
+            displayManager.registerDisplayListener(listener, handler);
+        }
+
+        public void unRegisterDisplayListener(Context context,
+                DisplayManager.DisplayListener listener) {
+            final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
+            displayManager.unregisterDisplayListener(listener);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index ebb61f2..29ba166 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -2852,10 +2852,13 @@
         // to check super here.
         final boolean reallyAnimating = super.isSelfAnimating();
         final boolean show = !isHidden() || reallyAnimating;
-        if (show && !mLastSurfaceShowing) {
-            mPendingTransaction.show(mSurfaceControl);
-        } else if (!show && mLastSurfaceShowing) {
-            mPendingTransaction.hide(mSurfaceControl);
+
+        if (mSurfaceControl != null) {
+            if (show && !mLastSurfaceShowing) {
+                mPendingTransaction.show(mSurfaceControl);
+            } else if (!show && mLastSurfaceShowing) {
+                mPendingTransaction.hide(mSurfaceControl);
+            }
         }
         if (mThumbnail != null) {
             mThumbnail.setShowing(mPendingTransaction, show);
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 79a654b..e3b1245 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -37,6 +37,9 @@
 import android.hardware.SensorEventListener;
 import android.hardware.display.AmbientBrightnessDayStats;
 import android.hardware.display.BrightnessChangeEvent;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayedContentSample;
+import android.hardware.display.DisplayedContentSamplingAttributes;
 import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -47,6 +50,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.util.AtomicFile;
+import android.view.Display;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -116,28 +120,81 @@
         assertTrue(mInjector.mIdleScheduled);
         mInjector.sendScreenChange(/*screen on */ true);
         assertNotNull(mInjector.mSensorListener);
+        assertTrue(mInjector.mColorSamplingEnabled);
 
         mInjector.sendScreenChange(/*screen on */ false);
         assertNull(mInjector.mSensorListener);
+        assertFalse(mInjector.mColorSamplingEnabled);
 
         // Turn screen on while brightness mode is manual
         mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ false);
         mInjector.sendScreenChange(/*screen on */ true);
         assertNull(mInjector.mSensorListener);
+        assertFalse(mInjector.mColorSamplingEnabled);
 
         // Set brightness mode to automatic while screen is off.
         mInjector.sendScreenChange(/*screen on */ false);
         mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ true);
         assertNull(mInjector.mSensorListener);
+        assertFalse(mInjector.mColorSamplingEnabled);
 
         // Turn on screen while brightness mode is automatic.
         mInjector.sendScreenChange(/*screen on */ true);
         assertNotNull(mInjector.mSensorListener);
+        assertTrue(mInjector.mColorSamplingEnabled);
 
         mTracker.stop();
         assertNull(mInjector.mSensorListener);
         assertNull(mInjector.mBroadcastReceiver);
         assertFalse(mInjector.mIdleScheduled);
+        assertFalse(mInjector.mColorSamplingEnabled);
+    }
+
+    @Test
+    public void testNoColorSampling_WrongPixelFormat() {
+        mInjector.mDefaultSamplingAttributes =
+                new DisplayedContentSamplingAttributes(
+                        0x23,
+                        mInjector.mDefaultSamplingAttributes.getDataspace(),
+                        mInjector.mDefaultSamplingAttributes.getComponentMask());
+        startTracker(mTracker);
+        assertFalse(mInjector.mColorSamplingEnabled);
+        assertNull(mInjector.mDisplayListener);
+    }
+
+    @Test
+    public void testNoColorSampling_MissingComponent() {
+        mInjector.mDefaultSamplingAttributes =
+                new DisplayedContentSamplingAttributes(
+                        mInjector.mDefaultSamplingAttributes.getPixelFormat(),
+                        mInjector.mDefaultSamplingAttributes.getDataspace(),
+                        0x2);
+        startTracker(mTracker);
+        assertFalse(mInjector.mColorSamplingEnabled);
+        assertNull(mInjector.mDisplayListener);
+    }
+
+    @Test
+    public void testNoColorSampling_NoSupport() {
+        mInjector.mDefaultSamplingAttributes = null;
+        startTracker(mTracker);
+        assertFalse(mInjector.mColorSamplingEnabled);
+        assertNull(mInjector.mDisplayListener);
+    }
+
+    @Test
+    public void testColorSampling_FrameRateChange() {
+        startTracker(mTracker);
+        assertTrue(mInjector.mColorSamplingEnabled);
+        assertNotNull(mInjector.mDisplayListener);
+        int noFramesSampled = mInjector.mNoColorSamplingFrames;
+        mInjector.mFrameRate = 120.0f;
+        // Wrong display
+        mInjector.mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY + 10);
+        assertEquals(noFramesSampled, mInjector.mNoColorSamplingFrames);
+        // Correct display
+        mInjector.mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY);
+        assertEquals(noFramesSampled * 2, mInjector.mNoColorSamplingFrames);
     }
 
     @Test
@@ -149,26 +206,41 @@
         assertNotNull(mInjector.mBroadcastReceiver);
         assertNotNull(mInjector.mContentObserver);
         assertTrue(mInjector.mIdleScheduled);
+        assertFalse(mInjector.mColorSamplingEnabled);
+        assertNull(mInjector.mDisplayListener);
 
         mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
         assertNotNull(mInjector.mSensorListener);
+        assertTrue(mInjector.mColorSamplingEnabled);
+        assertNotNull(mInjector.mDisplayListener);
 
         SensorEventListener listener = mInjector.mSensorListener;
+        DisplayManager.DisplayListener displayListener = mInjector.mDisplayListener;
         mInjector.mSensorListener = null;
+        mInjector.mColorSamplingEnabled = false;
+        mInjector.mDisplayListener = null;
         // Duplicate notification
         mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
         // Sensor shouldn't have been registered as it was already registered.
         assertNull(mInjector.mSensorListener);
+        assertFalse(mInjector.mColorSamplingEnabled);
+        assertNull(mInjector.mDisplayListener);
         mInjector.mSensorListener = listener;
+        mInjector.mDisplayListener = displayListener;
+        mInjector.mColorSamplingEnabled = true;
 
         mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ false);
         assertNull(mInjector.mSensorListener);
+        assertFalse(mInjector.mColorSamplingEnabled);
+        assertNull(mInjector.mDisplayListener);
 
         mTracker.stop();
         assertNull(mInjector.mSensorListener);
         assertNull(mInjector.mBroadcastReceiver);
         assertNull(mInjector.mContentObserver);
         assertFalse(mInjector.mIdleScheduled);
+        assertFalse(mInjector.mColorSamplingEnabled);
+        assertNull(mInjector.mDisplayListener);
     }
 
     @Test
@@ -229,6 +301,8 @@
         assertEquals(3333, event.colorTemperature);
         assertEquals("a.package", event.packageName);
         assertEquals(0, event.userId);
+        assertArrayEquals(new long[] {1, 10, 100, 1000, 300, 30, 10, 1}, event.colorValueBuckets);
+        assertEquals(10000, event.colorSampleDuration);
 
         assertEquals(1, eventsNoPackage.size());
         assertNull(eventsNoPackage.get(0).packageName);
@@ -342,7 +416,8 @@
                 + "lastNits=\"32\" "
                 + "batteryLevel=\"0.5\" nightMode=\"true\" colorTemperature=\"3235\"\n"
                 + "lux=\"132.2,131.1\" luxTimestamps=\""
-                + Long.toString(someTimeAgo) + "," + Long.toString(someTimeAgo) + "\"/>"
+                + Long.toString(someTimeAgo) + "," + Long.toString(someTimeAgo) + "\""
+                + "colorSampleDuration=\"3456\" colorValueBuckets=\"123,598,23,19\"/>"
                 // Event that is too old so shouldn't show up.
                 + "<event nits=\"142\" timestamp=\""
                 + Long.toString(twoMonthsAgo) + "\" packageName=\""
@@ -368,6 +443,7 @@
         assertTrue(event.isDefaultBrightnessConfig);
         assertEquals(0.5f, event.powerBrightnessFactor, FLOAT_DELTA);
         assertTrue(event.isUserSetBrightness);
+        assertNull(event.colorValueBuckets);
 
         events = tracker.getEvents(1, true).getList();
         assertEquals(1, events.size());
@@ -386,6 +462,8 @@
         assertFalse(event.isDefaultBrightnessConfig);
         assertEquals(1.0, event.powerBrightnessFactor, FLOAT_DELTA);
         assertFalse(event.isUserSetBrightness);
+        assertEquals(3456L, event.colorSampleDuration);
+        assertArrayEquals(new long[] {123L, 598L, 23L, 19L}, event.colorValueBuckets);
 
         // Pretend user 1 is a profile of user 0.
         mInjector.mProfiles = new int[]{0, 1};
@@ -481,6 +559,8 @@
         assertEquals(0.5f, event.powerBrightnessFactor, FLOAT_DELTA);
         assertTrue(event.isUserSetBrightness);
         assertFalse(event.isDefaultBrightnessConfig);
+        assertArrayEquals(new long[] {1, 10, 100, 1000, 300, 30, 10, 1}, event.colorValueBuckets);
+        assertEquals(10000, event.colorSampleDuration);
     }
 
     @Test
@@ -546,6 +626,7 @@
         builder.setNightMode(false);
         builder.setColorTemperature(345);
         builder.setLastBrightness(50f);
+        builder.setColorValues(new long[] {23, 34, 45}, 1000L);
         BrightnessChangeEvent event = builder.build();
 
         event.writeToParcel(parcel, 0);
@@ -568,6 +649,8 @@
         assertEquals(event.nightMode, event2.nightMode);
         assertEquals(event.colorTemperature, event2.colorTemperature);
         assertEquals(event.lastBrightness, event2.lastBrightness, FLOAT_DELTA);
+        assertArrayEquals(event.colorValueBuckets, event2.colorValueBuckets);
+        assertEquals(event.colorSampleDuration, event2.colorSampleDuration);
 
         parcel = Parcel.obtain();
         builder.setBatteryLevel(Float.NaN);
@@ -714,6 +797,7 @@
     private class TestInjector extends BrightnessTracker.Injector {
         SensorEventListener mSensorListener;
         BroadcastReceiver mBroadcastReceiver;
+        DisplayManager.DisplayListener mDisplayListener;
         Map<String, Integer> mSecureIntSettings = new HashMap<>();
         long mCurrentTimeMillis = System.currentTimeMillis();
         long mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
@@ -723,6 +807,12 @@
         int[] mProfiles;
         ContentObserver mContentObserver;
         boolean mIsBrightnessModeAutomatic = true;
+        boolean mColorSamplingEnabled = false;
+        DisplayedContentSamplingAttributes mDefaultSamplingAttributes =
+                new DisplayedContentSamplingAttributes(0x37, 0, 0x4);
+        float mFrameRate = 60.0f;
+        int mNoColorSamplingFrames;
+
 
         public TestInjector(Handler handler) {
             mHandler = handler;
@@ -882,5 +972,43 @@
             return mSecureIntSettings.getOrDefault(Settings.Secure.NIGHT_DISPLAY_ACTIVATED,
                     0) == 1;
         }
+
+        @Override
+        public DisplayedContentSample sampleColor(int noFramesToSample) {
+            return new DisplayedContentSample(600L,
+                    null,
+                    null,
+                     new long[] {1, 10, 100, 1000, 300, 30, 10, 1},
+                    null);
+        }
+
+        @Override
+        public float getFrameRate(Context context) {
+            return mFrameRate;
+        }
+
+        @Override
+        public DisplayedContentSamplingAttributes getSamplingAttributes() {
+            return mDefaultSamplingAttributes;
+        }
+
+        @Override
+        public boolean enableColorSampling(boolean enable, int noFrames) {
+            mColorSamplingEnabled = enable;
+            mNoColorSamplingFrames = noFrames;
+            return true;
+        }
+
+        @Override
+        public void registerDisplayListener(Context context,
+                DisplayManager.DisplayListener listener, Handler handler) {
+            mDisplayListener = listener;
+        }
+
+        @Override
+        public void unRegisterDisplayListener(Context context,
+                DisplayManager.DisplayListener listener) {
+            mDisplayListener = null;
+        }
     }
 }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 718f2d3..7cab432 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -613,11 +613,8 @@
         @Override
         public void showSession(IVoiceInteractionService service, Bundle args, int flags) {
             synchronized (this) {
-                if (mImpl == null || mImpl.mService == null
-                        || service.asBinder() != mImpl.mService.asBinder()) {
-                    throw new SecurityException(
-                            "Caller is not the current voice interaction service");
-                }
+                enforceIsCurrentVoiceInteractionService(service);
+
                 final long caller = Binder.clearCallingIdentity();
                 try {
                     mImpl.showSessionLocked(args, flags, null, null);
@@ -896,11 +893,7 @@
         public boolean isEnrolledForKeyphrase(IVoiceInteractionService service, int keyphraseId,
                 String bcp47Locale) {
             synchronized (this) {
-                if (mImpl == null || mImpl.mService == null
-                        || service.asBinder() != mImpl.mService.asBinder()) {
-                    throw new SecurityException(
-                            "Caller is not the current voice interaction service");
-                }
+                enforceIsCurrentVoiceInteractionService(service);
             }
 
             if (bcp47Locale == null) {
@@ -922,11 +915,7 @@
         public ModuleProperties getDspModuleProperties(IVoiceInteractionService service) {
             // Allow the call if this is the current voice interaction service.
             synchronized (this) {
-                if (mImpl == null || mImpl.mService == null
-                        || service == null || service.asBinder() != mImpl.mService.asBinder()) {
-                    throw new SecurityException(
-                            "Caller is not the current voice interaction service");
-                }
+                enforceIsCurrentVoiceInteractionService(service);
 
                 final long caller = Binder.clearCallingIdentity();
                 try {
@@ -943,11 +932,7 @@
                 RecognitionConfig recognitionConfig) {
             // Allow the call if this is the current voice interaction service.
             synchronized (this) {
-                if (mImpl == null || mImpl.mService == null
-                        || service == null || service.asBinder() != mImpl.mService.asBinder()) {
-                    throw new SecurityException(
-                            "Caller is not the current voice interaction service");
-                }
+                enforceIsCurrentVoiceInteractionService(service);
 
                 if (callback == null || recognitionConfig == null || bcp47Locale == null) {
                     throw new IllegalArgumentException("Illegal argument(s) in startRecognition");
@@ -983,11 +968,7 @@
                 IRecognitionStatusCallback callback) {
             // Allow the call if this is the current voice interaction service.
             synchronized (this) {
-                if (mImpl == null || mImpl.mService == null
-                        || service == null || service.asBinder() != mImpl.mService.asBinder()) {
-                    throw new SecurityException(
-                            "Caller is not the current voice interaction service");
-                }
+                enforceIsCurrentVoiceInteractionService(service);
             }
 
             final long caller = Binder.clearCallingIdentity();
@@ -1212,8 +1193,10 @@
         }
 
         @Override
-        public void setTranscription(String transcription) {
+        public void setTranscription(IVoiceInteractionService service, String transcription) {
             synchronized (this) {
+                enforceIsCurrentVoiceInteractionService(service);
+
                 final int size = mVoiceInteractionSessionListeners.beginBroadcast();
                 for (int i = 0; i < size; ++i) {
                     final IVoiceInteractionSessionListener listener =
@@ -1229,8 +1212,10 @@
         }
 
         @Override
-        public void clearTranscription(boolean immediate) {
+        public void clearTranscription(IVoiceInteractionService service, boolean immediate) {
             synchronized (this) {
+                enforceIsCurrentVoiceInteractionService(service);
+
                 final int size = mVoiceInteractionSessionListeners.beginBroadcast();
                 for (int i = 0; i < size; ++i) {
                     final IVoiceInteractionSessionListener listener =
@@ -1246,8 +1231,10 @@
         }
 
         @Override
-        public void setVoiceState(int state) {
+        public void setVoiceState(IVoiceInteractionService service, int state) {
             synchronized (this) {
+                enforceIsCurrentVoiceInteractionService(service);
+
                 final int size = mVoiceInteractionSessionListeners.beginBroadcast();
                 for (int i = 0; i < size; ++i) {
                     final IVoiceInteractionSessionListener listener =
@@ -1269,6 +1256,14 @@
             }
         }
 
+        private void enforceIsCurrentVoiceInteractionService(IVoiceInteractionService service) {
+            if (mImpl == null || mImpl.mService == null
+                    || service.asBinder() != mImpl.mService.asBinder()) {
+                throw new
+                    SecurityException("Caller is not the current voice interaction service");
+            }
+        }
+
         private void setImplLocked(VoiceInteractionManagerServiceImpl impl) {
             mImpl = impl;
             mAtmInternal.notifyActiveVoiceInteractionServiceChanged(
diff --git a/telecomm/java/android/telecom/DefaultDialerManager.java b/telecomm/java/android/telecom/DefaultDialerManager.java
index ef78ea5..57ae5d3 100644
--- a/telecomm/java/android/telecom/DefaultDialerManager.java
+++ b/telecomm/java/android/telecom/DefaultDialerManager.java
@@ -29,11 +29,15 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.Slog;
 
 import com.android.internal.util.CollectionUtils;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Class for managing the default dialer application that will receive incoming calls, and be
@@ -72,19 +76,15 @@
             int user) {
         long identity = Binder.clearCallingIdentity();
         try {
+            RoleManagerCallback.Future cb = new RoleManagerCallback.Future();
             context.getSystemService(RoleManager.class).addRoleHolderAsUser(
                     RoleManager.ROLE_DIALER, packageName, UserHandle.of(user),
-                    AsyncTask.THREAD_POOL_EXECUTOR, new RoleManagerCallback() {
-                        @Override
-                        public void onSuccess() {}
-
-                        @Override
-                        public void onFailure() {
-                            Log.w(TAG, "Failed to set default dialer to %s for user %s",
-                                    packageName, user);
-                        }
-                    });
+                    AsyncTask.THREAD_POOL_EXECUTOR, cb);
+            cb.get(5, TimeUnit.SECONDS);
             return true;
+        } catch (InterruptedException | ExecutionException | TimeoutException e) {
+            Slog.e(TAG, "Failed to set default dialer to " + packageName + " for user " + user, e);
+            return false;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a1fb090..7c3bde4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -354,27 +354,26 @@
      * Returns 3 for Tri standby mode.(Tri SIM functionality)
      */
     public int getPhoneCount() {
-        int phoneCount = 0;
-
-        // check for voice and data support, 0 if not supported
-        if (!isVoiceCapable() && !isSmsCapable()) {
-            ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
-                    Context.CONNECTIVITY_SERVICE);
-            if (cm != null) {
-                if (!cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
-                    return phoneCount;
+        int phoneCount = 1;
+        switch (getMultiSimConfiguration()) {
+            case UNKNOWN:
+                ConnectivityManager cm = mContext == null ? null : (ConnectivityManager) mContext
+                        .getSystemService(Context.CONNECTIVITY_SERVICE);
+                // check for voice and data support, 0 if not supported
+                if (!isVoiceCapable() && !isSmsCapable() && cm != null
+                        && !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
+                    phoneCount = 0;
+                } else {
+                    phoneCount = 1;
                 }
-            }
-        }
-
-        phoneCount = 1;
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                phoneCount = telephony.getNumOfActiveSims();
-            }
-        } catch (RemoteException ex) {
-            Rlog.e(TAG, "getNumOfActiveSims RemoteException", ex);
+                break;
+            case DSDS:
+            case DSDA:
+                phoneCount = PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
+                break;
+            case TSTS:
+                phoneCount = PhoneConstants.MAX_PHONE_COUNT_TRI_SIM;
+                break;
         }
         return phoneCount;
     }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 762d886..bc43fea 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1843,11 +1843,6 @@
      * @hide
      */
     void switchMultiSimConfig(int numOfSims);
-    /**
-     * Get how many modems have been activated on the phone
-     * @hide
-     */
-    int getNumOfActiveSims();
 
     /**
      * Get if reboot is required upon altering modems configurations