Merge "Using correct slop for checking quickstep gesture" into qt-dev
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index fa73758..7bfed91 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -380,7 +380,7 @@
         // don't want the navigation bar background be moving around when resizing in docked mode.
         // However, we need it for the transitions into/out of docked mode.
         if (mNavigationBarColor != null && fullscreen) {
-            DecorView.getNavigationBarRect(width, height, stableInsets, systemInsets, mTmpRect);
+            DecorView.getNavigationBarRect(width, height, stableInsets, systemInsets, mTmpRect, 1f);
             mNavigationBarColor.setBounds(mTmpRect);
             mNavigationBarColor.draw(canvas);
         }
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 723f161..afe7954 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1080,10 +1080,13 @@
     }
 
     public static void getNavigationBarRect(int canvasWidth, int canvasHeight, Rect stableInsets,
-            Rect contentInsets, Rect outRect) {
-        final int bottomInset = getColorViewBottomInset(stableInsets.bottom, contentInsets.bottom);
-        final int leftInset = getColorViewLeftInset(stableInsets.left, contentInsets.left);
-        final int rightInset = getColorViewLeftInset(stableInsets.right, contentInsets.right);
+            Rect contentInsets, Rect outRect, float scale) {
+        final int bottomInset =
+                (int) (getColorViewBottomInset(stableInsets.bottom, contentInsets.bottom) * scale);
+        final int leftInset =
+                (int) (getColorViewLeftInset(stableInsets.left, contentInsets.left) * scale);
+        final int rightInset =
+                (int) (getColorViewLeftInset(stableInsets.right, contentInsets.right) * scale);
         final int size = getNavBarSize(bottomInset, rightInset, leftInset);
         if (isNavBarToRightEdge(bottomInset, rightInset)) {
             outRect.set(canvasWidth - size, 0, canvasWidth, canvasHeight);
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 14abb77..dd75c56 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2787,6 +2787,9 @@
          screen. -->
     <bool name="config_lowRamTaskSnapshotsAndRecents">false</bool>
 
+    <!-- The amount to scale fullscreen snapshots for Overview and snapshot starting windows. -->
+    <item name="config_fullTaskSnapshotScale" format="float" type="dimen">1.0</item>
+
     <!-- Determines whether recent tasks are provided to the user. Default device has recents
          property. If this is false, then the following recents config flags are ignored. -->
     <bool name="config_hasRecents">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9d75654..50814c5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -355,6 +355,7 @@
   <java-symbol type="bool" name="config_enableMultiUserUI"/>
   <java-symbol type="bool" name="config_enableNewAutoSelectNetworkUI"/>
   <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
+  <java-symbol type="dimen" name="config_fullTaskSnapshotScale" />
   <java-symbol type="bool" name="config_lowRamTaskSnapshotsAndRecents" />
   <java-symbol type="bool" name="config_hasRecents" />
   <java-symbol type="string" name="config_recentsComponentName" />
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 150b6f9..8d420e2 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -211,21 +211,22 @@
 }
 
 void JMediaCodec::release() {
-    if (mCodec != NULL) {
-        mCodec->release();
-        mCodec.clear();
-        mInitStatus = NO_INIT;
-    }
+    std::call_once(mReleaseFlag, [this] {
+        if (mCodec != NULL) {
+            mCodec->release();
+            mInitStatus = NO_INIT;
+        }
 
-    if (mLooper != NULL) {
-        mLooper->unregisterHandler(id());
-        mLooper->stop();
-        mLooper.clear();
-    }
+        if (mLooper != NULL) {
+            mLooper->unregisterHandler(id());
+            mLooper->stop();
+            mLooper.clear();
+        }
+    });
 }
 
 JMediaCodec::~JMediaCodec() {
-    if (mCodec != NULL || mLooper != NULL) {
+    if (mLooper != NULL) {
         /* MediaCodec and looper should have been released explicitly already
          * in setMediaCodec() (see comments in setMediaCodec()).
          *
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index de08550..dfe30a3 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -17,6 +17,8 @@
 #ifndef _ANDROID_MEDIA_MEDIACODEC_H_
 #define _ANDROID_MEDIA_MEDIACODEC_H_
 
+#include <mutex>
+
 #include "jni.h"
 
 #include <media/MediaAnalyticsItem.h>
@@ -156,6 +158,7 @@
     sp<ALooper> mLooper;
     sp<MediaCodec> mCodec;
     AString mNameAtCreation;
+    std::once_flag mReleaseFlag;
 
     sp<AMessage> mCallbackNotification;
     sp<AMessage> mOnFrameRenderedNotification;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index ab174f4..f16fb1c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -712,11 +712,25 @@
     public boolean matches(WifiConfiguration config) {
         if (config.isPasspoint()) {
             return (isPasspoint() && config.FQDN.equals(mConfig.FQDN));
-        } else {
-            // Normal non-Passpoint network
-            return ssid.equals(removeDoubleQuotes(config.SSID))
-                    && security == getSecurity(config)
-                    && (mConfig == null || mConfig.shared == config.shared);
+        }
+
+        if (!ssid.equals(removeDoubleQuotes(config.SSID))
+                || (mConfig != null && mConfig.shared != config.shared)) {
+            return false;
+        }
+
+        final int configSecurity = getSecurity(config);
+        final WifiManager wifiManager = getWifiManager();
+        switch (security) {
+            case SECURITY_PSK_SAE_TRANSITION:
+                return configSecurity == SECURITY_PSK
+                        || (wifiManager.isWpa3SaeSupported() && configSecurity == SECURITY_SAE);
+            case SECURITY_OWE_TRANSITION:
+                return configSecurity == SECURITY_NONE
+                        || (wifiManager.isEnhancedOpenSupported()
+                                && configSecurity == SECURITY_OWE);
+            default:
+                return security == configSecurity;
         }
     }
 
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index da625fa..4200b43 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -451,8 +451,8 @@
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"S\'ha activat l\'estalvi de bateria"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"Redueix el rendiment i l\'ús de les dades en segon pla."</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"Desactiva l\'estalvi de bateria"</string>
-    <string name="media_projection_dialog_text" msgid="8585357687598538511">"Quan graves o emets contingut, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> pot capturar la informació sensible que es mostri a la pantalla o que reprodueixi el dispositiu, com ara àudio, contrasenyes, informació de pagament, fotos i missatges."</string>
-    <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"Quan graves o emets contingut, el servei que ofereix aquesta funció pot capturar informació sensible que es mostri a la pantalla o que reprodueixi el dispositiu, com ara àudio, contrasenyes, informació de pagament, fotos i missatges."</string>
+    <string name="media_projection_dialog_text" msgid="8585357687598538511">"Quan graves o emets contingut, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> pot capturar la informació sensible que es mostri a la pantalla o que es reprodueixi al dispositiu, com ara àudio, contrasenyes, informació de pagament, fotos i missatges."</string>
+    <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"Quan graves o emets contingut, el servei que ofereix aquesta funció pot capturar informació sensible que es mostri a la pantalla o que es reprodueixi al dispositiu, com ara àudio, contrasenyes, informació de pagament, fotos i missatges."</string>
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"Es mostra informació sensible durant l\'emissió o la gravació"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"No ho tornis a mostrar"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Esborra-ho tot"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a6bd968..981e0cf 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -451,9 +451,9 @@
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"Ahorro de batería activado"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"Reduce el rendimiento y los datos en segundo plano"</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"Desactivar Ahorro de batería"</string>
-    <string name="media_projection_dialog_text" msgid="8585357687598538511">"Mientras graba o envía contenido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede obtener información sensible que se muestre en la pantalla o que se reproduzca en el dispositivo, como audio, contraseñas, información de pagos, fotos y mensajes."</string>
-    <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"Mientras graba o envía contenido, el servicio que ofrece esta función puede obtener información sensible que se muestre en la pantalla o que se reproduzca en el dispositivo, como audio, contraseñas, información de pagos, fotos y mensajes."</string>
-    <string name="media_projection_dialog_title" msgid="8124184308671641248">"Se muestra información sensible durante el envío y la grabación"</string>
+    <string name="media_projection_dialog_text" msgid="8585357687598538511">"Mientras grabas o envías contenido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede capturar información sensible que se muestre en la pantalla o que se reproduzca en el dispositivo, como audio, contraseñas, información de pagos, fotos y mensajes."</string>
+    <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"Mientras grabas o envías contenido, el servicio que ofrece esta función puede capturar información sensible que se muestre en la pantalla o que se reproduzca en el dispositivo, como audio, contraseñas, información de pagos, fotos y mensajes."</string>
+    <string name="media_projection_dialog_title" msgid="8124184308671641248">"Sobre información sensible durante el envío y la grabación"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"No volver a mostrar"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Borrar todo"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"Gestionar"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 0477057..5c4d71e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -451,9 +451,9 @@
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"Économiseur de batterie activé"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"Limite les performances et les données en arrière-plan."</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"Désactiver l\'économiseur de batterie"</string>
-    <string name="media_projection_dialog_text" msgid="8585357687598538511">"Pendant que vous enregistrez ou diffusez du contenu, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> peut capturer des informations sensibles affichées à l\'écran ou lues par votre appareil, y compris des contenus audio, des mots de passe, des informations de paiement, des photos et des messages."</string>
+    <string name="media_projection_dialog_text" msgid="8585357687598538511">"Pendant que vous enregistrez ou diffusez du contenu, l\'appli <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> peut capturer des informations sensibles affichées à l\'écran ou lues par votre appareil, y compris des contenus audio, des mots de passe, des informations de paiement, des photos et des messages."</string>
     <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"Pendant que vous enregistrez ou diffusez du contenu, le service concerné peut capturer des informations sensibles affichées à l\'écran ou lues par votre appareil, y compris des contenus audio, des mots de passe, des informations de paiement, des photos et des messages."</string>
-    <string name="media_projection_dialog_title" msgid="8124184308671641248">"Exposition d\'informations sensibles lors de l\'enregistrement ou de la diffusion de contenu"</string>
+    <string name="media_projection_dialog_title" msgid="8124184308671641248">"Présence d\'informations sensibles lors de l\'enregistrement ou de la diffusion de contenu"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne plus afficher"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Tout effacer"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"Gérer"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 13a0f1f..5b0a1ea 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -451,9 +451,9 @@
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"កម្មវិធីសន្សំថ្មបានបើក"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"ការ​បន្ថយ​ការ​ប្រតិបត្តិ និង​ទិន្នន័យ​ផ្ទៃ​ខាងក្រោយ"</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"បិទ​កម្មវិធី​សន្សំ​ថ្ម"</string>
-    <string name="media_projection_dialog_text" msgid="8585357687598538511">"នៅពេល​កំពុងថត ឬបញ្ជូន <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> អាច​ថតព័ត៌មាន​រសើប​ទាំងឡាយ​ដែលបង្ហាញ​នៅលើ​អេក្រង់​របស់អ្នក ឬដែលចាក់ពី​ឧបករណ៍​របស់អ្នក រួមទាំង​ព័ត៌មាន​រសើប​ដូចជា សំឡេង ពាក្យ​សម្ងាត់ ព័ត៌មាន​បង់ប្រាក់ រូបថត និងសារ​ជាដើម។"</string>
+    <string name="media_projection_dialog_text" msgid="8585357687598538511">"នៅពេល​កំពុងថត ឬភ្ជាប់ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> អាច​ថតព័ត៌មាន​រសើប​ទាំងឡាយ​ដែលបង្ហាញ​នៅលើ​អេក្រង់​របស់អ្នក ឬដែលចាក់ពី​ឧបករណ៍​របស់អ្នក រួមទាំង​ព័ត៌មាន​រសើប​ដូចជា សំឡេង ពាក្យ​សម្ងាត់ ព័ត៌មាន​បង់ប្រាក់ រូបថត និងសារ​ជាដើម។"</string>
     <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"នៅពេល​កំពុងថត ឬបញ្ជូន សេវាកម្មដែល​ផ្ដល់មុខងារនេះ​អាចថតព័ត៌មាន​រសើប​ទាំងឡាយ​ដែលបង្ហាញ​នៅលើ​អេក្រង់​របស់អ្នក ឬដែលចាក់​ពីឧបករណ៍​របស់អ្នក រួមទាំង​ព័ត៌មាន​រសើប​ដូចជា សំឡេង ពាក្យ​សម្ងាត់ ព័ត៌មាន​បង់ប្រាក់​ រូបថត និងសារ​ជាដើម។"</string>
-    <string name="media_projection_dialog_title" msgid="8124184308671641248">"បង្ហាញព័ត៌មានរសើប​ អំឡុងពេលបញ្ជូន/ថត"</string>
+    <string name="media_projection_dialog_title" msgid="8124184308671641248">"ការបង្ហាញព័ត៌មានរសើប​ អំឡុងពេលភ្ជាប់/ថត"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"កុំ​បង្ហាញ​ម្ដងទៀត"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"សម្អាត​ទាំងអស់"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"គ្រប់គ្រង"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 7367fa5..caa07faf9 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -451,7 +451,7 @@
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"ബാറ്ററി ലാഭിക്കൽ ഓണാണ്"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"പ്രവർത്തനവും പശ്ചാത്തല ഡാറ്റയും കുറയ്‌ക്കുന്നു"</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"ബാറ്ററി ലാഭിക്കൽ ഓഫാക്കുക"</string>
-    <string name="media_projection_dialog_text" msgid="8585357687598538511">"റെക്കോർഡ് അല്ലെങ്കിൽ കാസ്‌റ്റ് ചെയ്യുന്നതിനിടെ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്‌തതോ ആയ ഓഡിയോ, പാസ്‌വേഡുകൾ, പേയ്മെന്റ് വിവരം, ഫോട്ടോകൾ, സന്ദേശങ്ങൾ എന്നിവ ഉൾപ്പെടെയുള്ള തന്ത്രപ്രധാന വിവരങ്ങൾ ക്യാപ്‌ചർ ചെയ്യാനാവും."</string>
+    <string name="media_projection_dialog_text" msgid="8585357687598538511">"റെക്കോർഡ് അല്ലെങ്കിൽ കാസ്‌റ്റ് ചെയ്യുന്നതിനിടെ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്‌തതോ ആയ ഓഡിയോ, പാസ്‌വേഡുകൾ, പേയ്മെന്റ് വിവരം, ഫോട്ടോകൾ, സന്ദേശങ്ങൾ എന്നിവ ഉൾപ്പെടെയുള്ള തന്ത്രപ്രധാന വിവരങ്ങൾ ക്യാപ്‌ചർ ചെയ്യാനാവും."</string>
     <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"റെക്കോർഡ് അല്ലെങ്കിൽ കാസ്‌റ്റ് ചെയ്യുന്നതിനിടെ, ഈ പ്രവർത്തനത്തിനാവശ്യമായ സേവനത്തിന്, നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്‌തതോ ആയ ഓഡിയോ, പാസ്‌വേഡുകൾ, പേയ്മെന്റ് വിവരം, ഫോട്ടോകൾ, സന്ദേശങ്ങൾ എന്നിവ ഉൾപ്പെടെയുള്ള തന്ത്രപ്രധാന വിവരങ്ങൾ ക്യാപ്‌ചർ ചെയ്യാനാവും."</string>
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"കാസ്‌റ്റ്/റെക്കോർഡ് ചെയ്യുമ്പോൾ സൂക്ഷ്‌മമായി കൈകാര്യം ചെയ്യേണ്ട വിവരം വെളിപ്പെടുത്തുന്നു"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"വീണ്ടും കാണിക്കരുത്"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 650f35e..adbbb64 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -451,7 +451,7 @@
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"ဘက်ထရီ အားထိန်းကို ဖွင့်ထားခြင်း"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"လုပ်ကိုင်မှုကို လျှော့ချလျက် နောက်ခံ ဒေတာကို ကန့်သတ်သည်"</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"ဘက်ထရီ အားထိန်းကို ပိတ်ရန်"</string>
-    <string name="media_projection_dialog_text" msgid="8585357687598538511">"အသံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် အသံ၊ စကားဝှက်၊ ငွေပေးချေမှုဆိုင်ရာ အချက်အလက်၊ ဓာတ်ပုံနှင့် မက်ဆေ့ဂျ်များကဲ့သို့ အရေးကြီးသည့် အချက်အလက်များအပါအဝင် သင့်မျက်နှာပြင်တွင် ပြသထားသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အရေးကြီးသည့် အချက်အလက်မှန်သမျှကို ဖမ်းယူနိုင်ပါသည်။"</string>
+    <string name="media_projection_dialog_text" msgid="8585357687598538511">"အသံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> သည် အသံ၊ စကားဝှက်၊ ငွေပေးချေမှုဆိုင်ရာ အချက်အလက်၊ ဓာတ်ပုံနှင့် မက်ဆေ့ဂျ်များကဲ့သို့ အရေးကြီးသည့် အချက်အလက်များအပါအဝင် ဖန်သားပြင်တွင် ပြသထားသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အရေးကြီးသည့် အချက်အလက်မှန်သမျှကို ဖမ်းယူနိုင်ပါသည်။"</string>
     <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"အသံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် ဤလုပ်ဆောင်ချက်ကို ပေးအပ်သည့် ဝန်ဆောင်မှုသည် အသံ၊ စကားဝှက်၊ ငွေပေးချေမှုဆိုင်ရာ အချက်အလက်၊ ဓာတ်ပုံနှင့် မက်ဆေ့ဂျ်များကဲ့သို့ အရေးကြီးသည့် အချက်အလက်များအပါအဝင် သင့်မျက်နှာပြင်တွင် ပြသထားသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အရေးကြီးသည့် အချက်အလက်မှန်သမျှကို ဖမ်းယူနိုင်ပါသည်။"</string>
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"ကာစ်လုပ်နေစဉ်/အသံဖမ်းနေစဉ် အရေးကြီးသောအချက်အလက်များ ထုတ်ဖော်မိခြင်း"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"နောက်ထပ် မပြပါနှင့်"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 29c423a..df437b3 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -459,7 +459,7 @@
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"Oszczędzanie baterii jest włączone"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"Zmniejsza wydajność i ogranicza dane w tle"</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"Wyłącz Oszczędzanie baterii"</string>
-    <string name="media_projection_dialog_text" msgid="8585357687598538511">"Podczas nagrywania lub przesyłania aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu takie jak dźwięki czy podawane hasła, informacje o płatnościach, zdjęcia i wiadomości."</string>
+    <string name="media_projection_dialog_text" msgid="8585357687598538511">"Podczas nagrywania lub przesyłania aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu, takie jak dźwięki czy podawane hasła, informacje o płatnościach, zdjęcia i wiadomości."</string>
     <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"Podczas nagrywania lub przesyłania usługa udostępniająca tę funkcję może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu takie jak dźwięki czy podawane hasła, informacje o płatnościach, zdjęcia i wiadomości."</string>
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"Ujawnianie poufnych informacji podczas przesyłania/nagrywania"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Nie pokazuj ponownie"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index c03c108..f5ed50f 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -197,7 +197,7 @@
     <string name="carrier_network_change_mode" msgid="8149202439957837762">"Сменить сеть"</string>
     <string name="accessibility_battery_details" msgid="7645516654955025422">"Сведения о расходе заряда батареи"</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"Заряд батареи в процентах: <xliff:g id="NUMBER">%d</xliff:g>."</string>
-    <string name="accessibility_battery_level_with_estimate" msgid="9033100930684311630">"Заряд батареи – <xliff:g id="PERCENTAGE">%1$s</xliff:g> %. При текущем уровне расхода его хватит примерно на такое время: <xliff:g id="TIME">%2$s</xliff:g>."</string>
+    <string name="accessibility_battery_level_with_estimate" msgid="9033100930684311630">"Заряд батареи в процентах: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Оценка оставшегося времени работы: <xliff:g id="TIME">%2$s</xliff:g>."</string>
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Зарядка батареи. Текущий заряд: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> %%."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Настройки"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Уведомления"</string>
@@ -457,7 +457,7 @@
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"Режим энергосбережения включен"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"Откл. фоновой передачи данных"</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"Отключить режим энергосбережения"</string>
-    <string name="media_projection_dialog_text" msgid="8585357687598538511">"При записи сообщений или трансляции экрана приложение \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" может получить доступ к конфиденциальной информации, которая отображается на экране или воспроизводится на устройстве, например к аудиозаписям, паролям, фото, сообщениям и платежным данным."</string>
+    <string name="media_projection_dialog_text" msgid="8585357687598538511">"При записи сообщений или трансляции экрана приложение <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> может получить доступ к конфиденциальной информации, которая отображается на экране или воспроизводится на устройстве, например к аудиозаписям, паролям, фото, сообщениям и платежным данным."</string>
     <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"При записи сообщений или трансляции экрана сервис может получить доступ к конфиденциальной информации, которая отображается на экране или воспроизводится на устройстве, например к аудиозаписям, паролям, фото, сообщениям и платежным данным."</string>
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"Раскрытие личной информации при записи или трансляции"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Больше не показывать"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6a9d3d3..0366303 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -453,7 +453,7 @@
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"Inaktivera batterisparläget"</string>
     <string name="media_projection_dialog_text" msgid="8585357687598538511">"När du spelar in eller castar kan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> registrera vilka känsliga uppgifter som helst som visas på skärmen eller spelas upp på enheten, inklusive ljud, lösenord, betalningsuppgifter, foton och meddelanden."</string>
     <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"När du spelar in eller castar kan tjänsten som tillhandahåller funktionen registrera vilka känsliga uppgifter som helst som visas på skärmen eller spelas upp på enheten, inklusive ljud, lösenord, betalningsuppgifter, foton och meddelanden."</string>
-    <string name="media_projection_dialog_title" msgid="8124184308671641248">"Avslöja känsliga uppgifter under inspelning och vid castning"</string>
+    <string name="media_projection_dialog_title" msgid="8124184308671641248">"Känsliga uppgifters synlighet under inspelning och vid castning"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Visa inte igen"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Rensa alla"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"Hantera"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index 909b68b..0af333e 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -57,8 +57,8 @@
     private static final String LEARNING_EVENT_COUNT_KEY = "reminder_exp_learning_event_count";
     private static final String LEARNED_HINT_LAST_SHOWN_KEY =
             "reminder_exp_learned_hint_last_shown";
-    private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(200);
-    private static final int DEFAULT_LEARNING_COUNT = 30000;
+    private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(10);
+    private static final int DEFAULT_LEARNING_COUNT = 10;
     private static final long DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS = 150;
     private static final long DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS =
             TimeUnit.SECONDS.toMillis(1);
@@ -66,7 +66,7 @@
             TimeUnit.SECONDS.toMillis(3);
     private static final boolean DEFAULT_SUPPRESS_ON_LOCKSCREEN = false;
     private static final boolean DEFAULT_SUPPRESS_ON_LAUNCHER = false;
-    private static final boolean DEFAULT_SUPPRESS_ON_APPS = false;
+    private static final boolean DEFAULT_SUPPRESS_ON_APPS = true;
 
     private static final String[] DEFAULT_HOME_CHANGE_ACTIONS = new String[] {
             PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
index 6bbeffa..deb314b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
@@ -115,7 +115,6 @@
             return false;
         }
         mWindowManager.removeViewImmediate(mKeyButtonView);
-        mRotationButtonController.cleanUp();
         mIsShowing = false;
         return true;
     }
@@ -141,10 +140,7 @@
 
     @Override
     public void setOnClickListener(View.OnClickListener onClickListener) {
-        mKeyButtonView.setOnClickListener(view -> {
-            hide();
-            onClickListener.onClick(view);
-        });
+        mKeyButtonView.setOnClickListener(onClickListener);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 5708c1b..b56abcd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -871,9 +871,6 @@
         boolean[] feedbackEnabled = new boolean[1];
         int a11yFlags = getA11yButtonState(feedbackEnabled);
 
-        mNavigationBarView.getRotationButtonController().setAccessibilityFeedbackEnabled(
-                feedbackEnabled[0]);
-
         boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
         boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
         mNavigationBarView.setAccessibilityButtonState(clickable, longClickable);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index ed486cd..9919abd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -1040,6 +1040,9 @@
         reorient();
         onNavigationModeChanged(mNavBarMode);
         setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
+        if (mRotationButtonController != null) {
+            mRotationButtonController.registerListeners();
+        }
 
         mEdgeBackGestureHandler.onNavBarAttached();
         getViewTreeObserver().addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
@@ -1053,6 +1056,10 @@
         for (int i = 0; i < mButtonDispatchers.size(); ++i) {
             mButtonDispatchers.valueAt(i).onDestroy();
         }
+        if (mRotationButtonController != null) {
+            mRotationButtonController.unregisterListeners();
+        }
+
         mEdgeBackGestureHandler.onNavBarDetached();
         getViewTreeObserver().removeOnComputeInternalInsetsListener(
                 mOnComputeInternalInsetsListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
index 1e5406f..0147e7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
@@ -26,7 +26,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Handler;
-import android.os.Message;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.view.IRotationWatcher.Stub;
@@ -34,6 +34,7 @@
 import android.view.Surface;
 import android.view.View;
 import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -42,6 +43,7 @@
 import com.android.systemui.R;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 import com.android.systemui.statusbar.policy.RotationLockController;
 
@@ -64,8 +66,10 @@
     private boolean mPendingRotationSuggestion;
     private boolean mHoveringRotationSuggestion;
     private RotationLockController mRotationLockController;
+    private AccessibilityManagerWrapper mAccessibilityManagerWrapper;
     private TaskStackListenerImpl mTaskStackListener;
     private Consumer<Integer> mRotWatcherListener;
+    private boolean mListenersRegistered = false;
     private boolean mIsNavigationBarShowing;
 
     private final Runnable mRemoveRotationProposal =
@@ -73,22 +77,17 @@
     private final Runnable mCancelPendingRotationProposal =
             () -> mPendingRotationSuggestion = false;
     private Animator mRotateHideAnimator;
-    private boolean mAccessibilityFeedbackEnabled;
 
     private final Context mContext;
     private final RotationButton mRotationButton;
+    private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
 
     private final Stub mRotationWatcher = new Stub() {
         @Override
         public void onRotationChanged(final int rotation) throws RemoteException {
-            if (mRotationButton.getCurrentView() == null) {
-                return;
-            }
-
             // We need this to be scheduled as early as possible to beat the redrawing of
             // window in response to the orientation change.
-            Handler h = mRotationButton.getCurrentView().getHandler();
-            Message msg = Message.obtain(h, () -> {
+            mMainThreadHandler.postAtFrontOfQueue(() -> {
                 // If the screen rotation changes while locked, potentially update lock to flow with
                 // new screen rotation and hide any showing suggestions.
                 if (mRotationLockController.isRotationLocked()) {
@@ -102,8 +101,6 @@
                     mRotWatcherListener.accept(rotation);
                 }
             });
-            msg.setAsynchronous(true);
-            h.sendMessageAtFrontOfQueue(msg);
         }
     };
 
@@ -124,40 +121,49 @@
         mStyleRes = style;
         mIsNavigationBarShowing = true;
         mRotationLockController = Dependency.get(RotationLockController.class);
+        mAccessibilityManagerWrapper = Dependency.get(AccessibilityManagerWrapper.class);
 
         // Register the task stack listener
         mTaskStackListener = new TaskStackListenerImpl();
-        ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
         mRotationButton.setOnClickListener(this::onRotateSuggestionClick);
         mRotationButton.setOnHoverListener(this::onRotateSuggestionHover);
+    }
 
+    void registerListeners() {
+        if (mListenersRegistered) {
+            return;
+        }
+
+        mListenersRegistered = true;
         try {
             WindowManagerGlobal.getWindowManagerService()
                     .watchRotation(mRotationWatcher, mContext.getDisplay().getDisplayId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
+
+        ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
     }
 
-    void cleanUp() {
-        // Unregister the task stack listener
-        ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
+    void unregisterListeners() {
+        if (!mListenersRegistered) {
+            return;
+        }
 
+        mListenersRegistered = false;
         try {
             WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
+
+        ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
     }
 
     void addRotationCallback(Consumer<Integer> watcher) {
         mRotWatcherListener = watcher;
     }
 
-    void setAccessibilityFeedbackEnabled(boolean flag) {
-        mAccessibilityFeedbackEnabled = flag;
-    }
-
     void setRotationLockedAtAngle(int rotationSuggestion) {
         mRotationLockController.setRotationLockedAtAngle(true /* locked */, rotationSuggestion);
     }
@@ -185,7 +191,7 @@
 
         // Clear any pending suggestion flag as it has either been nullified or is being shown
         mPendingRotationSuggestion = false;
-        view.removeCallbacks(mCancelPendingRotationProposal);
+        mMainThreadHandler.removeCallbacks(mCancelPendingRotationProposal);
 
         // Handle the visibility change and animation
         if (visible) { // Appear and change (cannot force)
@@ -255,13 +261,9 @@
             return;
         }
 
-        final View currentView = mRotationButton.getCurrentView();
-
         // If window rotation matches suggested rotation, remove any current suggestions
         if (rotation == windowRotation) {
-            if (currentView != null) {
-                currentView.removeCallbacks(mRemoveRotationProposal);
-            }
+            mMainThreadHandler.removeCallbacks(mRemoveRotationProposal);
             setRotateSuggestionButtonState(false /* visible */);
             return;
         }
@@ -285,11 +287,9 @@
             // If the navbar isn't shown, flag the rotate icon to be shown should the navbar become
             // visible given some time limit.
             mPendingRotationSuggestion = true;
-            if (currentView != null) {
-                currentView.removeCallbacks(mCancelPendingRotationProposal);
-                currentView.postDelayed(mCancelPendingRotationProposal,
-                        NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS);
-            }
+            mMainThreadHandler.removeCallbacks(mCancelPendingRotationProposal);
+            mMainThreadHandler.postDelayed(mCancelPendingRotationProposal,
+                    NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS);
         }
     }
 
@@ -334,9 +334,7 @@
     private void onRotationSuggestionsDisabled() {
         // Immediately hide the rotate button and clear any planned removal
         setRotateSuggestionButtonState(false /* visible */, true /* force */);
-        if (mRotationButton.getCurrentView() != null) {
-            mRotationButton.getCurrentView().removeCallbacks(mRemoveRotationProposal);
-        }
+        mMainThreadHandler.removeCallbacks(mRemoveRotationProposal);
     }
 
     private void showAndLogRotationSuggestion() {
@@ -369,10 +367,6 @@
     }
 
     private void rescheduleRotationTimeout(final boolean reasonHover) {
-        if (mRotationButton.getCurrentView() == null) {
-            return;
-        }
-
         // May be called due to a new rotation proposal or a change in hover state
         if (reasonHover) {
             // Don't reschedule if a hide animator is running
@@ -382,16 +376,16 @@
         }
 
         // Stop any pending removal
-        mRotationButton.getCurrentView().removeCallbacks(mRemoveRotationProposal);
+        mMainThreadHandler.removeCallbacks(mRemoveRotationProposal);
         // Schedule timeout
-        mRotationButton.getCurrentView().postDelayed(mRemoveRotationProposal,
+        mMainThreadHandler.postDelayed(mRemoveRotationProposal,
                 computeRotationProposalTimeout());
     }
 
     private int computeRotationProposalTimeout() {
-        if (mAccessibilityFeedbackEnabled) return 10000;
-        if (mHoveringRotationSuggestion) return 8000;
-        return 5000;
+        return mAccessibilityManagerWrapper.getRecommendedTimeoutMillis(
+                mHoveringRotationSuggestion ? 16000 : 5000,
+                AccessibilityManager.FLAG_CONTENT_CONTROLS);
     }
 
     private boolean isRotateSuggestionIntroduced() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index 24e7336..bd96752 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -64,13 +64,6 @@
     }
 
     @Override
-    public void onDestroy() {
-        if (mRotationButtonController != null) {
-            mRotationButtonController.cleanUp();
-        }
-    }
-
-    @Override
     public void onNavigationModeChanged(int mode) {
         mNavBarMode = mode;
     }
diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto
index a1bbe52..381d983 100644
--- a/proto/src/task_snapshot.proto
+++ b/proto/src/task_snapshot.proto
@@ -32,4 +32,5 @@
      int32 system_ui_visibility = 8;
      bool is_translucent = 9;
      string top_activity_component = 10;
+     float scale = 11;
  }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5f4d113..d2031b6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -111,9 +111,6 @@
 import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime;
 import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
 import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
-import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
-import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS;
-import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
 
 import android.Manifest;
 import android.annotation.IntDef;
@@ -294,6 +291,7 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.IntPair;
 import com.android.internal.util.Preconditions;
 import com.android.server.AttributeCache;
 import com.android.server.DeviceIdleController;
@@ -19801,6 +19799,8 @@
             return;
         }
 
+        final String packageName = ps.pkg.packageName;
+
         // These are flags that can change base on user actions.
         final int userSettableMask = FLAG_PERMISSION_USER_SET
                 | FLAG_PERMISSION_USER_FIXED
@@ -19810,8 +19810,59 @@
         final int policyOrSystemFlags = FLAG_PERMISSION_SYSTEM_FIXED
                 | FLAG_PERMISSION_POLICY_FIXED;
 
-        boolean writeInstallPermissions = false;
-        boolean writeRuntimePermissions = false;
+        // Delay and combine non-async permission callbacks
+        final boolean[] permissionRemoved = new boolean[1];
+        final ArraySet<Long> revokedPermissions = new ArraySet<>();
+        final SparseBooleanArray updatedUsers = new SparseBooleanArray();
+
+        PermissionCallback delayingPermCallback = new PermissionCallback() {
+            public void onGidsChanged(int appId, int userId) {
+                mPermissionCallback.onGidsChanged(appId, userId);
+            }
+
+            public void onPermissionChanged() {
+                mPermissionCallback.onPermissionChanged();
+            }
+
+            public void onPermissionGranted(int uid, int userId) {
+                mPermissionCallback.onPermissionGranted(uid, userId);
+            }
+
+            public void onInstallPermissionGranted() {
+                mPermissionCallback.onInstallPermissionGranted();
+            }
+
+            public void onPermissionRevoked(int uid, int userId) {
+                revokedPermissions.add(IntPair.of(uid, userId));
+
+                updatedUsers.put(userId, true);
+            }
+
+            public void onInstallPermissionRevoked() {
+                mPermissionCallback.onInstallPermissionRevoked();
+            }
+
+            public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
+                for (int userId : updatedUserIds) {
+                    if (sync) {
+                        updatedUsers.put(userId, true);
+                    } else {
+                        // Don't override sync=true by sync=false
+                        if (!updatedUsers.get(userId)) {
+                            updatedUsers.put(userId, false);
+                        }
+                    }
+                }
+            }
+
+            public void onPermissionRemoved() {
+                permissionRemoved[0] = true;
+            }
+
+            public void onInstallPermissionUpdated() {
+                mPermissionCallback.onInstallPermissionUpdated();
+            }
+        };
 
         final int permissionCount = ps.pkg.requestedPermissions.size();
         for (int i = 0; i < permissionCount; i++) {
@@ -19843,26 +19894,20 @@
                 }
             }
 
-            final PermissionsState permissionsState = ps.getPermissionsState();
-
-            final int oldFlags = permissionsState.getPermissionFlags(permName, userId);
+            final int oldFlags = mPermissionManager.getPermissionFlags(permName, packageName,
+                    Process.SYSTEM_UID, userId);
 
             // Always clear the user settable flags.
-            final boolean hasInstallState =
-                    permissionsState.getInstallPermissionState(permName) != null;
             // If permission review is enabled and this is a legacy app, mark the
             // permission as requiring a review as this is the initial state.
             int flags = 0;
             if (ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M && bp.isRuntime()) {
                 flags |= FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKE_ON_UPGRADE;
             }
-            if (permissionsState.updatePermissionFlags(bp, userId, userSettableMask, flags)) {
-                if (hasInstallState) {
-                    writeInstallPermissions = true;
-                } else {
-                    writeRuntimePermissions = true;
-                }
-            }
+
+            mPermissionManager.updatePermissionFlags(permName, packageName,
+                    userSettableMask, flags, Process.SYSTEM_UID, userId, false,
+                    delayingPermCallback);
 
             // Below is only runtime permission handling.
             if (!bp.isRuntime()) {
@@ -19876,35 +19921,42 @@
 
             // If this permission was granted by default, make sure it is.
             if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0) {
-                if (permissionsState.grantRuntimePermission(bp, userId)
-                        != PERMISSION_OPERATION_FAILURE) {
-                    writeRuntimePermissions = true;
-                }
+                mPermissionManager.grantRuntimePermission(permName, packageName, false,
+                        Process.SYSTEM_UID, userId, delayingPermCallback);
             // If permission review is enabled the permissions for a legacy apps
             // are represented as constantly granted runtime ones, so don't revoke.
             } else if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
                 // Otherwise, reset the permission.
-                final int revokeResult = permissionsState.revokeRuntimePermission(bp, userId);
-                switch (revokeResult) {
-                    case PERMISSION_OPERATION_SUCCESS:
-                    case PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
-                        writeRuntimePermissions = true;
-                        final int appId = ps.appId;
-                        mHandler.post(
-                                () -> killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED));
-                    } break;
-                }
+                mPermissionManager.revokeRuntimePermission(permName, packageName, false, userId,
+                        delayingPermCallback);
             }
         }
 
-        // Synchronously write as we are taking permissions away.
-        if (writeRuntimePermissions) {
-            mSettings.writeRuntimePermissionsForUserLPr(userId, true);
+        // Execute delayed callbacks
+        if (permissionRemoved[0]) {
+            mPermissionCallback.onPermissionRemoved();
         }
 
-        // Synchronously write as we are taking permissions away.
-        if (writeInstallPermissions) {
-            mSettings.writeLPr();
+        // Slight variation on the code in mPermissionCallback.onPermissionRevoked() as we cannot
+        // kill uid while holding mPackages-lock
+        if (!revokedPermissions.isEmpty()) {
+            int numRevokedPermissions = revokedPermissions.size();
+            for (int i = 0; i < numRevokedPermissions; i++) {
+                int revocationUID = IntPair.first(revokedPermissions.valueAt(i));
+                int revocationUserId = IntPair.second(revokedPermissions.valueAt(i));
+
+                mOnPermissionChangeListeners.onPermissionsChanged(revocationUID);
+
+                // Kill app later as we are holding mPackages
+                mHandler.post(() -> killUid(UserHandle.getAppId(revocationUID), revocationUserId,
+                        KILL_APP_REASON_PERMISSIONS_REVOKED));
+            }
+        }
+
+        int numUpdatedUsers = updatedUsers.size();
+        for (int i = 0; i < numUpdatedUsers; i++) {
+            mSettings.writeRuntimePermissionsForUserLPr(updatedUsers.keyAt(i),
+                    updatedUsers.valueAt(i));
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index e5f914d..a7da3ec 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -3127,6 +3127,27 @@
         }
 
         @Override
+        public @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtectionLevel(
+                @PermissionInfo.Protection int protectionLevel) {
+            ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
+
+            synchronized (PermissionManagerService.this.mLock) {
+                int numTotalPermissions = mSettings.mPermissions.size();
+
+                for (int i = 0; i < numTotalPermissions; i++) {
+                    BasePermission bp = mSettings.mPermissions.valueAt(i);
+
+                    if (bp.perm != null && bp.perm.info != null
+                            && bp.protectionLevel == protectionLevel) {
+                        matchingPermissions.add(bp.perm.info);
+                    }
+                }
+            }
+
+            return matchingPermissions;
+        }
+
+        @Override
         public @Nullable byte[] backupRuntimePermissions(@NonNull UserHandle user) {
             return PermissionManagerService.this.backupRuntimePermissions(user);
         }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 313de3d..e5e9598 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -195,4 +195,8 @@
 
     /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
     public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
+
+    /** Get all permission that have a certain protection level */
+    public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtectionLevel(
+            @PermissionInfo.Protection int protectionLevel);
 }
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 93b11bef..68feb4a 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -23,6 +23,7 @@
 import static android.app.AppOpsManager.MODE_IGNORED;
 import static android.app.AppOpsManager.OP_NONE;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
 import static android.content.pm.PackageManager.GET_PERMISSIONS;
 
 import android.annotation.NonNull;
@@ -41,20 +42,27 @@
 import android.content.pm.PermissionInfo;
 import android.os.Build;
 import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.permission.PermissionControllerManager;
-import android.permission.PermissionManagerInternal;
 import android.provider.Telephony;
 import android.telecom.TelecomManager;
+import android.util.ArraySet;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
 import java.util.ArrayList;
 import java.util.concurrent.CountDownLatch;
@@ -76,6 +84,13 @@
     @GuardedBy("mLock")
     private final SparseBooleanArray mIsStarted = new SparseBooleanArray();
 
+    /**
+     * Whether an async {@link #synchronizePackagePermissionsAndAppOpsForUser} is currently
+     * scheduled for a package/user.
+     */
+    @GuardedBy("mLock")
+    private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>();
+
     public PermissionPolicyService(@NonNull Context context) {
         super(context);
 
@@ -86,8 +101,10 @@
     public void onStart() {
         final PackageManagerInternal packageManagerInternal = LocalServices.getService(
                 PackageManagerInternal.class);
-        final PermissionManagerInternal permManagerInternal = LocalServices.getService(
-                PermissionManagerInternal.class);
+        final PermissionManagerServiceInternal permManagerInternal = LocalServices.getService(
+                PermissionManagerServiceInternal.class);
+        final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
+                ServiceManager.getService(Context.APP_OPS_SERVICE));
 
         packageManagerInternal.getPackageList(new PackageListObserver() {
             @Override
@@ -111,11 +128,62 @@
         });
 
         permManagerInternal.addOnRuntimePermissionStateChangedListener(
-                (packageName, changedUserId) -> {
-                    if (isStarted(changedUserId)) {
-                        synchronizePackagePermissionsAndAppOpsForUser(packageName, changedUserId);
+                this::synchronizePackagePermissionsAndAppOpsAsyncForUser);
+
+        IAppOpsCallback appOpsListener = new IAppOpsCallback.Stub() {
+            public void opChanged(int op, int uid, String packageName) {
+                synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
+                        UserHandle.getUserId(uid));
+            }
+        };
+
+        final ArrayList<PermissionInfo> dangerousPerms =
+                permManagerInternal.getAllPermissionWithProtectionLevel(
+                        PermissionInfo.PROTECTION_DANGEROUS);
+
+        try {
+            int numDangerousPerms = dangerousPerms.size();
+            for (int i = 0; i < numDangerousPerms; i++) {
+                PermissionInfo perm = dangerousPerms.get(i);
+
+                if (perm.isHardRestricted() || perm.backgroundPermission != null) {
+                    appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
+                            null, appOpsListener);
+                } else if (perm.isSoftRestricted()) {
+                    appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
+                            null, appOpsListener);
+
+                    SoftRestrictedPermissionPolicy policy =
+                            SoftRestrictedPermissionPolicy.forPermission(null, null, null,
+                                    perm.name);
+                    if (policy.resolveAppOp() != OP_NONE) {
+                        appOpsService.startWatchingMode(policy.resolveAppOp(), null,
+                                appOpsListener);
                     }
-                });
+                }
+            }
+        } catch (RemoteException doesNotHappen) {
+            Slog.wtf(LOG_TAG, "Cannot set up app-ops listener");
+        }
+    }
+
+    private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
+            @UserIdInt int changedUserId) {
+        if (isStarted(changedUserId)) {
+            synchronized (mLock) {
+                if (mIsPackageSyncsScheduled.add(new Pair<>(packageName, changedUserId))) {
+                    FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
+                            PermissionPolicyService
+                                    ::synchronizePackagePermissionsAndAppOpsForUser,
+                            this, packageName, changedUserId));
+                } else {
+                    if (DEBUG) {
+                        Slog.v(LOG_TAG, "sync for " + packageName + "/" + changedUserId
+                                + " already scheduled");
+                    }
+                }
+            }
+        }
     }
 
     @Override
@@ -230,10 +298,14 @@
      */
     private void synchronizePackagePermissionsAndAppOpsForUser(@NonNull String packageName,
             @UserIdInt int userId) {
+        synchronized (mLock) {
+            mIsPackageSyncsScheduled.remove(new Pair<>(packageName, userId));
+        }
+
         if (DEBUG) {
             Slog.v(LOG_TAG,
-                    "synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", " + userId
-                            + ")");
+                    "synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", "
+                            + userId + ")");
         }
 
         final PackageManagerInternal packageManagerInternal = LocalServices.getService(
@@ -336,6 +408,16 @@
          */
         private final @NonNull ArrayList<OpToUnrestrict> mOpsToForeground = new ArrayList<>();
 
+        /**
+         * All ops that need to be flipped to foreground if allow.
+         *
+         * Currently, only used by the foreground/background permissions logic.
+         *
+         * @see #syncPackages
+         */
+        private final @NonNull ArrayList<OpToUnrestrict> mOpsToForegroundIfAllow =
+                new ArrayList<>();
+
         PermissionToOpSynchroniser(@NonNull Context context) {
             mContext = context;
             mPackageManager = context.getPackageManager();
@@ -351,22 +433,27 @@
             final int allowCount = mOpsToAllow.size();
             for (int i = 0; i < allowCount; i++) {
                 final OpToUnrestrict op = mOpsToAllow.get(i);
-                setUidModeAllowed(op.code, op.uid);
+                setUidModeAllowed(op.code, op.uid, op.packageName);
             }
             final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
             for (int i = 0; i < allowIfDefaultCount; i++) {
                 final OpToUnrestrict op = mOpsToAllowIfDefault.get(i);
                 setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
             }
-            final int foregroundCount = mOpsToForeground.size();
+            final int foregroundCount = mOpsToForegroundIfAllow.size();
             for (int i = 0; i < foregroundCount; i++) {
+                final OpToUnrestrict op = mOpsToForegroundIfAllow.get(i);
+                setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
+            }
+            final int foregroundIfAllowCount = mOpsToForeground.size();
+            for (int i = 0; i < foregroundIfAllowCount; i++) {
                 final OpToUnrestrict op = mOpsToForeground.get(i);
-                setUidModeForeground(op.code, op.uid);
+                setUidModeForeground(op.code, op.uid, op.packageName);
             }
             final int ignoreCount = mOpsToIgnore.size();
             for (int i = 0; i < ignoreCount; i++) {
                 final OpToUnrestrict op = mOpsToIgnore.get(i);
-                setUidModeIgnored(op.code, op.uid);
+                setUidModeIgnored(op.code, op.uid, op.packageName);
             }
             final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
             for (int i = 0; i < ignoreIfDefaultCount; i++) {
@@ -459,6 +546,24 @@
             }
         }
 
+        private boolean isBgPermRestricted(@NonNull String pkg, @NonNull String perm, int uid) {
+            try {
+                final PermissionInfo bgPermInfo = mPackageManager.getPermissionInfo(perm, 0);
+
+                if (bgPermInfo.isSoftRestricted()) {
+                    Slog.wtf(LOG_TAG, "Support for soft restricted background permissions not "
+                            + "implemented");
+                }
+
+                return bgPermInfo.isHardRestricted() && (mPackageManager.getPermissionFlags(
+                                perm, pkg, UserHandle.getUserHandleForUid(uid))
+                                & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
+            } catch (NameNotFoundException e) {
+                Slog.w(LOG_TAG, "Cannot read permission state of " + perm, e);
+                return false;
+            }
+        }
+
         /**
          * Add op that belong to a foreground permission for later processing in
          * {@link #syncPackages()}.
@@ -481,26 +586,27 @@
             final String pkgName = pkg.packageName;
             final int uid = pkg.applicationInfo.uid;
 
-            if (mPackageManager.checkPermission(permission, pkgName)
-                    == PackageManager.PERMISSION_GRANTED) {
-                boolean isBgHardRestricted = false;
-                try {
-                    final PermissionInfo bgPermInfo = mPackageManager.getPermissionInfo(
-                            bgPermissionName, 0);
+            // App does not support runtime permissions. Hence the state is encoded in the app-op.
+            // To not override unrecoverable state don't change app-op unless bg perm is reviewed.
+            if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+                // If the review is required for this permission, the grant state does not
+                // really matter. To have a stable state, don't change the app-op if review is still
+                // pending.
+                int flags = mPackageManager.getPermissionFlags(bgPermissionName,
+                        pkg.packageName, UserHandle.getUserHandleForUid(uid));
 
-                    if (bgPermInfo.isSoftRestricted()) {
-                        Slog.wtf(LOG_TAG, "Support for soft restricted background permissions not "
-                                + "implemented");
-                    }
-
-                    isBgHardRestricted =
-                            bgPermInfo.isHardRestricted() && (mPackageManager.getPermissionFlags(
-                                    bgPermissionName, pkgName, UserHandle.getUserHandleForUid(uid))
-                                    & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
-                } catch (NameNotFoundException e) {
-                    Slog.w(LOG_TAG, "Cannot read permission state of " + bgPermissionName, e);
+                if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0
+                        && isBgPermRestricted(pkgName, bgPermissionName, uid)) {
+                    mOpsToForegroundIfAllow.add(new OpToUnrestrict(uid, pkgName, opCode));
                 }
 
+                return;
+            }
+
+            if (mPackageManager.checkPermission(permission, pkgName)
+                    == PackageManager.PERMISSION_GRANTED) {
+                final boolean isBgHardRestricted = isBgPermRestricted(pkgName, bgPermissionName,
+                        uid);
                 final boolean isBgPermGranted = mPackageManager.checkPermission(bgPermissionName,
                         pkgName) == PackageManager.PERMISSION_GRANTED;
 
@@ -554,45 +660,49 @@
         }
 
         private void setUidModeAllowedIfDefault(int opCode, int uid, @NonNull String packageName) {
-            setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_ALLOWED, packageName);
+            setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
         }
 
-        private void setUidModeAllowed(int opCode, int uid) {
-            mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED);
+        private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
+            setUidMode(opCode, uid, MODE_ALLOWED, packageName);
         }
 
-        private void setUidModeForeground(int opCode, int uid) {
-            mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_FOREGROUND);
+        private void setUidModeForegroundIfAllow(int opCode, int uid, @NonNull String packageName) {
+            setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
+        }
+
+        private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
+            setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
         }
 
         private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
-            setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName);
+            setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
         }
 
-        private void setUidModeIgnored(int opCode, int uid) {
-            mAppOpsManager.setUidMode(opCode, uid, MODE_IGNORED);
+        private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
+            setUidMode(opCode, uid, MODE_IGNORED, packageName);
         }
 
-        private void setUidModeIfDefault(int opCode, int uid, int mode,
+        private void setUidMode(int opCode, int uid, int mode,
                 @NonNull String packageName) {
-            final int currentMode;
-            try {
-                currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
-                        .opToPublicName(opCode), uid, packageName);
-            } catch (SecurityException e) {
-                // This might happen if the app was uninstalled in between the add and sync step.
-                // In this case the package name cannot be resolved inside appops service and hence
-                // the uid does not match.
-                Slog.w(LOG_TAG, "Cannot set mode of uid=" + uid + " op=" + opCode + " to " + mode,
-                        e);
-                return;
-            }
+            final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
+                    .opToPublicName(opCode), uid, packageName);
 
-            if (currentMode == MODE_DEFAULT) {
+            if (currentMode != mode) {
                 mAppOpsManager.setUidMode(opCode, uid, mode);
             }
         }
 
+        private void setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
+                @NonNull String packageName) {
+            final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
+                    .opToPublicName(opCode), uid, packageName);
+
+            if (currentMode == requiredModeBefore) {
+                mAppOpsManager.setUidMode(opCode, uid, newMode);
+            }
+        }
+
         private void setUidModeDefault(int opCode, int uid) {
             mAppOpsManager.setUidMode(opCode, uid, MODE_DEFAULT);
         }
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index 90e0dc4..1658833 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -29,6 +29,7 @@
 import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -75,14 +76,16 @@
      * Get the policy for a soft restricted permission.
      *
      * @param context A context to use
-     * @param appInfo The application the permission belongs to
-     * @param user The user the app belongs to
+     * @param appInfo The application the permission belongs to. Can be {@code null}, but then
+     *                only {@link #resolveAppOp} will work.
+     * @param user The user the app belongs to. Can be {@code null}, but then only
+     *             {@link #resolveAppOp} will work.
      * @param permission The name of the permission
      *
      * @return The policy for this permission
      */
     public static @NonNull SoftRestrictedPermissionPolicy forPermission(@NonNull Context context,
-            @NonNull ApplicationInfo appInfo, @NonNull UserHandle user,
+            @Nullable ApplicationInfo appInfo, @Nullable UserHandle user,
             @NonNull String permission) {
         switch (permission) {
             // Storage uses a special app op to decide the mount state and supports soft restriction
@@ -90,13 +93,26 @@
             // collections.
             case READ_EXTERNAL_STORAGE:
             case WRITE_EXTERNAL_STORAGE: {
-                int flags = context.getPackageManager().getPermissionFlags(
-                        permission, appInfo.packageName, user);
-                boolean applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
-                boolean isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
-                boolean hasRequestedLegacyExternalStorage =
-                        appInfo.hasRequestedLegacyExternalStorage();
-                int targetSDK = appInfo.targetSdkVersion;
+                final int flags;
+                final boolean applyRestriction;
+                final boolean isWhiteListed;
+                final boolean hasRequestedLegacyExternalStorage;
+                final int targetSDK;
+
+                if (appInfo != null) {
+                    flags = context.getPackageManager().getPermissionFlags(permission,
+                            appInfo.packageName, user);
+                    applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
+                    isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
+                    hasRequestedLegacyExternalStorage = appInfo.hasRequestedLegacyExternalStorage();
+                    targetSDK = appInfo.targetSdkVersion;
+                } else {
+                    flags = 0;
+                    applyRestriction = false;
+                    isWhiteListed = false;
+                    hasRequestedLegacyExternalStorage = false;
+                    targetSDK = 0;
+                }
 
                 return new SoftRestrictedPermissionPolicy() {
                     @Override
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 73775b4..5fd2ab8 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -26,10 +26,7 @@
 import static android.os.Process.SYSTEM_UID;
 
 import android.Manifest.permission;
-import android.app.ActivityManager;
 import android.app.AppOpsManager;
-import android.app.ContentProviderHolder;
-import android.app.IActivityManager;
 import android.app.slice.ISliceManager;
 import android.app.slice.SliceSpec;
 import android.app.usage.UsageStatsManagerInternal;
@@ -391,7 +388,7 @@
     }
 
     protected int checkAccess(String pkg, Uri uri, int uid, int pid) {
-        return checkSlicePermission(uri, null, pkg, uid, pid, null);
+        return checkSlicePermission(uri, null, pkg, pid, uid, null);
     }
 
     private String getProviderPkg(Uri uri, int user) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 9189279..be3b924 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -79,6 +79,7 @@
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.logWithStack;
 import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
+import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
 
@@ -540,6 +541,14 @@
                 // If the app was already visible, don't reset the waitingToShow state.
                 if (isHidden()) {
                     waitingToShow = true;
+
+                    // Let's reset the draw state in order to prevent the starting window to be
+                    // immediately dismissed when the app still has the surface.
+                    forAllWindows(w -> {
+                            if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
+                                w.mWinAnimator.resetDrawState();
+                            }
+                        },  true /* traverseTopToBottom */);
                 }
             }
 
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 101c4b8..9fdc045 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -95,6 +95,7 @@
     private final ArraySet<Task> mSkipClosingAppSnapshotTasks = new ArraySet<>();
     private final ArraySet<Task> mTmpTasks = new ArraySet<>();
     private final Handler mHandler = new Handler();
+    private final float mFullSnapshotScale;
 
     private final Rect mTmpRect = new Rect();
 
@@ -124,6 +125,8 @@
                 PackageManager.FEATURE_EMBEDDED);
         mIsRunningOnWear = mService.mContext.getPackageManager().hasSystemFeature(
             PackageManager.FEATURE_WATCH);
+        mFullSnapshotScale = mService.mContext.getResources().getFloat(
+                com.android.internal.R.dimen.config_fullTaskSnapshotScale);
     }
 
     void systemReady() {
@@ -287,7 +290,9 @@
         }
 
         final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
-        final float scaleFraction = isLowRamDevice ? mPersister.getReducedScale() : 1f;
+        final float scaleFraction = isLowRamDevice
+                ? mPersister.getReducedScale()
+                : mFullSnapshotScale;
 
         final WindowState mainWindow = appWindowToken.findMainWindow();
         if (mainWindow == null) {
@@ -379,9 +384,10 @@
                 task.getTaskDescription().getBackgroundColor(), 255);
         final LayoutParams attrs = mainWindow.getAttrs();
         final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
-                attrs.privateFlags, attrs.systemUiVisibility, task.getTaskDescription());
-        final int width = task.getBounds().width();
-        final int height = task.getBounds().height();
+                attrs.privateFlags, attrs.systemUiVisibility, task.getTaskDescription(),
+                mFullSnapshotScale);
+        final int width = (int) (task.getBounds().width() * mFullSnapshotScale);
+        final int height = (int) (task.getBounds().height() * mFullSnapshotScale);
 
         final RenderNode node = RenderNode.create("TaskSnapshotController", null);
         node.setLeftTopRightBottom(0, 0, width, height);
@@ -401,7 +407,7 @@
         return new TaskSnapshot(topChild.mActivityComponent, hwBitmap.createGraphicBufferHandle(),
                 hwBitmap.getColorSpace(), topChild.getTask().getConfiguration().orientation,
                 getInsets(mainWindow), ActivityManager.isLowRamDeviceStatic() /* reduced */,
-                1.0f /* scale */, false /* isRealSnapshot */, task.getWindowingMode(),
+                mFullSnapshotScale, false /* isRealSnapshot */, task.getWindowingMode(),
                 getSystemUiVisibility(task), false);
     }
 
@@ -483,6 +489,7 @@
     }
 
     void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + "mFullSnapshotScale=" + mFullSnapshotScale);
         mCache.dump(pw, prefix);
     }
 }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index f7b8945..fcd97c1 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -87,14 +87,16 @@
                         + bitmapFile.getPath());
                 return null;
             }
-            ComponentName topActivityComponent = ComponentName.unflattenFromString(
+            final ComponentName topActivityComponent = ComponentName.unflattenFromString(
                     proto.topActivityComponent);
+            // For legacy snapshots, restore the scale based on the reduced resolution state
+            final float legacyScale = reducedResolution ? mPersister.getReducedScale() : 1f;
+            final float scale = Float.compare(proto.scale, 0f) != 0 ? proto.scale : legacyScale;
             return new TaskSnapshot(topActivityComponent, buffer, bitmap.getColorSpace(),
                     proto.orientation,
                     new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
-                    reducedResolution, reducedResolution ? mPersister.getReducedScale() : 1f,
-                    proto.isRealSnapshot, proto.windowingMode, proto.systemUiVisibility,
-                    proto.isTranslucent);
+                    reducedResolution, scale, proto.isRealSnapshot, proto.windowingMode,
+                    proto.systemUiVisibility, proto.isTranslucent);
         } catch (IOException e) {
             Slog.w(TAG, "Unable to load task snapshot data for taskId=" + taskId);
             return null;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 0b63f48..72fc189 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -342,6 +342,7 @@
             proto.systemUiVisibility = mSnapshot.getSystemUiVisibility();
             proto.isTranslucent = mSnapshot.isTranslucent();
             proto.topActivityComponent = mSnapshot.getTopActivityComponent().flattenToString();
+            proto.scale = mSnapshot.getScale();
             final byte[] bytes = TaskSnapshotProto.toByteArray(proto);
             final File file = getProtoFile(mTaskId, mUserId);
             final AtomicFile atomicFile = new AtomicFile(file);
@@ -369,12 +370,13 @@
             }
 
             final Bitmap swBitmap = bitmap.copy(Config.ARGB_8888, false /* isMutable */);
-            final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId);
             final Bitmap reduced = mSnapshot.isReducedResolution()
                     ? swBitmap
                     : Bitmap.createScaledBitmap(swBitmap,
                             (int) (bitmap.getWidth() * mReducedScale),
                             (int) (bitmap.getHeight() * mReducedScale), true /* filter */);
+
+            final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId);
             try {
                 FileOutputStream reducedFos = new FileOutputStream(reducedFile);
                 reduced.compress(JPEG, QUALITY, reducedFos);
@@ -383,6 +385,7 @@
                 Slog.e(TAG, "Unable to open " + reducedFile +" for persisting.", e);
                 return false;
             }
+            reduced.recycle();
 
             // For snapshots with reduced resolution, do not create or save full sized bitmaps
             if (mSnapshot.isReducedResolution()) {
@@ -399,7 +402,6 @@
                 Slog.e(TAG, "Unable to open " + file + " for persisting.", e);
                 return false;
             }
-            reduced.recycle();
             swBitmap.recycle();
             return true;
         }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 5d99db5..a7760a86 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -248,7 +248,7 @@
         mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
         mTaskBounds = taskBounds;
         mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
-                windowPrivateFlags, sysUiVis, taskDescription);
+                windowPrivateFlags, sysUiVis, taskDescription, 1f);
         mStatusBarColor = taskDescription.getStatusBarColor();
         mOrientationOnCreation = currentOrientation;
     }
@@ -488,12 +488,14 @@
         private final int mWindowFlags;
         private final int mWindowPrivateFlags;
         private final int mSysUiVis;
+        private final float mScale;
 
-        SystemBarBackgroundPainter( int windowFlags, int windowPrivateFlags, int sysUiVis,
-                TaskDescription taskDescription) {
+        SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int sysUiVis,
+                TaskDescription taskDescription, float scale) {
             mWindowFlags = windowFlags;
             mWindowPrivateFlags = windowPrivateFlags;
             mSysUiVis = sysUiVis;
+            mScale = scale;
             final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
             final int semiTransparent = context.getColor(
                     R.color.system_bar_background_semi_transparent);
@@ -521,7 +523,7 @@
                     (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
             if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
                     mSysUiVis, mStatusBarColor, mWindowFlags, forceBarBackground)) {
-                return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
+                return (int) (getColorViewTopInset(mStableInsets.top, mContentInsets.top) * mScale);
             } else {
                 return 0;
             }
@@ -544,8 +546,8 @@
                 int statusBarHeight) {
             if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0
                     && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
-                final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
-                        mContentInsets.right);
+                final int rightInset = (int) (DecorView.getColorViewRightInset(mStableInsets.right,
+                        mContentInsets.right) * mScale);
                 final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
                 c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
             }
@@ -555,7 +557,7 @@
         void drawNavigationBarBackground(Canvas c) {
             final Rect navigationBarRect = new Rect();
             getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
-                    navigationBarRect);
+                    navigationBarRect, mScale);
             final boolean visible = isNavigationBarColorViewVisible();
             if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
                 c.drawRect(navigationBarRect, mNavigationBarPaint);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ce8720a..57fa2ed 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7626,22 +7626,30 @@
 
     @Override
     public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode) {
-        boolean shouldWaitForAnimToComplete = false;
+        boolean isDown;
+        boolean isUp;
+
         if (ev instanceof KeyEvent) {
             KeyEvent keyEvent = (KeyEvent) ev;
-            shouldWaitForAnimToComplete = keyEvent.getSource() == InputDevice.SOURCE_MOUSE
-                    || keyEvent.getAction() == KeyEvent.ACTION_DOWN;
-        } else if (ev instanceof MotionEvent) {
+            isDown = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
+            isUp = keyEvent.getAction() == KeyEvent.ACTION_UP;
+        } else {
             MotionEvent motionEvent = (MotionEvent) ev;
-            shouldWaitForAnimToComplete = motionEvent.getSource() == InputDevice.SOURCE_MOUSE
-                    || motionEvent.getAction() == MotionEvent.ACTION_DOWN;
+            isDown = motionEvent.getAction() == MotionEvent.ACTION_DOWN;
+            isUp = motionEvent.getAction() == MotionEvent.ACTION_UP;
         }
 
-        if (shouldWaitForAnimToComplete) {
+        // For ACTION_DOWN, syncInputTransactions before injecting input.
+        // For ACTION_UP, sync after injecting.
+        if (isDown) {
             syncInputTransactions();
         }
-
-        return LocalServices.getService(InputManagerInternal.class).injectInputEvent(ev, mode);
+        final boolean result =
+                LocalServices.getService(InputManagerInternal.class).injectInputEvent(ev, mode);
+        if (isUp) {
+            syncInputTransactions();
+        }
+        return result;
     }
 
     @Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ba59cdb..8b61208 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -6443,7 +6443,7 @@
                     .setAdmin(admin)
                     .setStrings(vpnPackage)
                     .setBoolean(lockdown)
-                    .setInt(/* number of vpn packages */ 0)
+                    .setInt(lockdownWhitelist != null ? lockdownWhitelist.size() : 0)
                     .write();
         } finally {
             mInjector.binderRestoreCallingIdentity(token);
diff --git a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
index a1d48cc..14b71ec 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
@@ -49,7 +49,7 @@
     }
 
     @Before
-    public void setup() {
+    public final void setup() {
         MockitoAnnotations.initMocks(this);
 
         // Share classloader to allow package access.
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index 4c2822a..f5002ac 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -68,7 +68,7 @@
     private IBinder mToken = new Binder();
 
     @Before
-    public void setup() {
+    public void setUp() {
         mSliceService = mock(SliceManagerService.class);
         when(mSliceService.getContext()).thenReturn(mContext);
         when(mSliceService.getLock()).thenReturn(new Object());
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceFullAccessListTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceFullAccessListTest.java
index d942c5a..4958daf 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceFullAccessListTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceFullAccessListTest.java
@@ -47,7 +47,7 @@
     private SliceFullAccessList mAccessList;
 
     @Before
-    public void setup() {
+    public void setUp() {
         mAccessList = new SliceFullAccessList(mContext);
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
index 7182f0f..a443695 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -71,7 +71,7 @@
     private TestableContext mContextSpy;
 
     @Before
-    public void setup() {
+    public void setUp() {
         LocalServices.addService(UsageStatsManagerInternal.class,
                 mock(UsageStatsManagerInternal.class));
         mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index b0eafee..f958867 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -145,7 +145,10 @@
 
     @Test
     public void testLowResolutionPersistAndLoadSnapshot() {
-        TaskSnapshot a = createSnapshot(0.5f /* reducedResolution */);
+        TaskSnapshot a = new TaskSnapshotBuilder()
+                .setScale(0.5f)
+                .setReducedResolution(true)
+                .build();
         assertTrue(a.isReducedResolution());
         mPersister.persistSnapshot(1 , mTestUserId, a);
         mPersister.waitForQueueEmpty();
@@ -253,6 +256,27 @@
     }
 
     @Test
+    public void testScalePersistAndLoadSnapshot() {
+        TaskSnapshot a = new TaskSnapshotBuilder()
+                .setScale(0.25f)
+                .build();
+        TaskSnapshot b = new TaskSnapshotBuilder()
+                .setScale(0.75f)
+                .build();
+        assertEquals(0.25f, a.getScale(), 1E-5);
+        assertEquals(0.75f, b.getScale(), 1E-5);
+        mPersister.persistSnapshot(1, mTestUserId, a);
+        mPersister.persistSnapshot(2, mTestUserId, b);
+        mPersister.waitForQueueEmpty();
+        final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId, false /* reduced */);
+        final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId, false /* reduced */);
+        assertNotNull(snapshotA);
+        assertNotNull(snapshotB);
+        assertEquals(0.25f, snapshotA.getScale(), 1E-5);
+        assertEquals(0.75f, snapshotB.getScale(), 1E-5);
+    }
+
+    @Test
     public void testRemoveObsoleteFiles() {
         mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
         mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index c3b0a67..e004cd3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -77,12 +77,7 @@
     }
 
     TaskSnapshot createSnapshot() {
-        return createSnapshot(1f /* scale */);
-    }
-
-    TaskSnapshot createSnapshot(float scale) {
         return new TaskSnapshotBuilder()
-                .setScale(scale)
                 .build();
     }
 
@@ -92,6 +87,7 @@
     static class TaskSnapshotBuilder {
 
         private float mScale = 1f;
+        private boolean mReducedResolution = false;
         private boolean mIsRealSnapshot = true;
         private boolean mIsTranslucent = false;
         private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
@@ -102,6 +98,11 @@
             return this;
         }
 
+        TaskSnapshotBuilder setReducedResolution(boolean reducedResolution) {
+            mReducedResolution = reducedResolution;
+            return this;
+        }
+
         TaskSnapshotBuilder setIsRealSnapshot(boolean isRealSnapshot) {
             mIsRealSnapshot = isRealSnapshot;
             return this;
@@ -130,7 +131,7 @@
             buffer.unlockCanvasAndPost(c);
             return new TaskSnapshot(new ComponentName("", ""), buffer,
                     ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, TEST_INSETS,
-                    mScale < 1f /* reducedResolution */, mScale, mIsRealSnapshot,
+                    mReducedResolution, mScale, mIsRealSnapshot,
                     mWindowingMode, mSystemUiVisibility, mIsTranslucent);
         }
     }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 1ac81db..a10454e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -791,6 +791,14 @@
     public static final int PROFILE_CLASS_DEFAULT = PROFILE_CLASS_UNSET;
 
     /**
+     * IMSI (International Mobile Subscriber Identity).
+     * <P>Type: TEXT </P>
+     * @hide
+     */
+    //TODO: add @SystemApi
+    public static final String IMSI = "imsi";
+
+    /**
      * Broadcast Action: The user has changed one of the default subs related to
      * data, phone calls, or sms</p>
      *