Merge "Revert "DO NOT MERGE - Add AUTOMOTIVE_USER_SETUP_IN_PROGRESS to Settings"" into qt-qpr1-dev
diff --git a/Android.bp b/Android.bp
index aba5ee8..7e043fc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -321,7 +321,6 @@
         "core/java/android/service/vr/IVrManager.aidl",
         "core/java/android/service/vr/IVrStateCallbacks.aidl",
         "core/java/android/service/watchdog/IExplicitHealthCheckService.aidl",
-        "core/java/android/service/watchdog/PackageConfig.aidl",
         "core/java/android/print/ILayoutResultCallback.aidl",
         "core/java/android/print/IPrinterDiscoveryObserver.aidl",
         "core/java/android/print/IPrintDocumentAdapter.aidl",
@@ -440,7 +439,6 @@
         "core/java/com/android/internal/os/IShellCallback.aidl",
         "core/java/com/android/internal/statusbar/IStatusBar.aidl",
         "core/java/com/android/internal/statusbar/IStatusBarService.aidl",
-        "core/java/com/android/internal/statusbar/RegisterStatusBarResult.aidl",
         "core/java/com/android/internal/textservice/ISpellCheckerService.aidl",
         "core/java/com/android/internal/textservice/ISpellCheckerServiceCallback.aidl",
         "core/java/com/android/internal/textservice/ISpellCheckerSession.aidl",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index d7aedab..993db51 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -325,7 +325,7 @@
     }
 
     // Pulled events will start at field 10000.
-    // Next: 10062
+    // Next: 10067
     oneof pulled {
         WifiBytesTransfer wifi_bytes_transfer = 10000;
         WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -390,6 +390,7 @@
         AppOps app_ops = 10060;
         ProcessSystemIonHeapSize process_system_ion_heap_size = 10061;
         VmsClientStats vms_client_stats = 10065;
+        NotificationRemoteViews notification_remote_views = 10066;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -4751,6 +4752,24 @@
     optional ProcessStatsSectionProto proc_stats_section = 1;
 }
 
+// Next Tag: 2
+message PackageRemoteViewInfoProto {
+    optional string package_name = 1;
+    // add per-package additional info here (like channels)
+}
+
+// Next Tag: 2
+message NotificationRemoteViewsProto {
+    repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
+}
+
+/**
+ * Pulled from NotificationManagerService.java
+ */
+message NotificationRemoteViews {
+    optional NotificationRemoteViewsProto notification_remote_views = 1;
+}
+
 message PowerProfileProto {
     optional double cpu_suspend = 1;
 
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index f430250..893378c 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -271,6 +271,9 @@
         {android::util::VMS_CLIENT_STATS,
          {.additiveFields = {5, 6, 7, 8, 9, 10},
           .puller = new CarStatsPuller(android::util::VMS_CLIENT_STATS)}},
+        // NotiifcationRemoteViews.
+        {android::util::NOTIFICATION_REMOTE_VIEWS,
+         {.puller = new StatsCompanionServicePuller(android::util::NOTIFICATION_REMOTE_VIEWS)}},
 };
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 9f51db8..3266898 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -202,4 +202,6 @@
 
     void setPrivateNotificationsAllowed(boolean allow);
     boolean getPrivateNotificationsAllowed();
+
+    long pullStats(long startNs, int report, boolean doAgg, out List<ParcelFileDescriptor> stats);
 }
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index efa0432..8f2aea3 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2562,6 +2562,12 @@
         }
     }
 
+    @Override
+    protected boolean shouldAddFooterView() {
+        // To accommodate for window insets
+        return true;
+    }
+
     public class ChooserListAdapter extends ResolveListAdapter {
         public static final int TARGET_BAD = -1;
         public static final int TARGET_CALLER = 0;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index f82c28e..3a9d4d5 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -382,14 +382,30 @@
         finish();
     }
 
+    /**
+     * Numerous layouts are supported, each with optional ViewGroups.
+     * Make sure the inset gets added to the correct View, using
+     * a footer for Lists so it can properly scroll under the navbar.
+     */
+    protected boolean shouldAddFooterView() {
+        if (useLayoutWithDefault()) return true;
+
+        View buttonBar = findViewById(R.id.button_bar);
+        if (buttonBar == null || buttonBar.getVisibility() == View.GONE) return true;
+
+        return false;
+    }
+
     protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
         mSystemWindowInsets = insets.getSystemWindowInsets();
 
         mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top,
                 mSystemWindowInsets.right, 0);
 
+        resetButtonBar();
+
         // Need extra padding so the list can fully scroll up
-        if (useLayoutWithDefault()) {
+        if (shouldAddFooterView()) {
             if (mFooterSpacer == null) {
                 mFooterSpacer = new Space(getApplicationContext());
             } else {
@@ -407,8 +423,6 @@
             }
         }
 
-        resetButtonBar();
-
         return insets.consumeSystemWindowInsets();
     }
 
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index 1ec05fb..ecb4193 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -264,3 +264,14 @@
     optional Sender priority_calls = 16;
     optional Sender priority_messages = 17;
 }
+
+// Next Tag: 2
+message PackageRemoteViewInfoProto {
+    optional string package_name = 1;
+    // add per-package additional info here (like channels)
+}
+
+// Next Tag: 2
+message NotificationRemoteViewsProto {
+    repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
+}
\ No newline at end of file
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 704151e..b414164 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -2019,7 +2019,7 @@
     <string name="mime_type_audio" msgid="4933450584432509875">"ઑડિયો"</string>
     <string name="mime_type_audio_ext" msgid="2615491023840514797">"<xliff:g id="EXTENSION">%1$s</xliff:g> ઑડિયો"</string>
     <string name="mime_type_video" msgid="7071965726609428150">"વીડિયો"</string>
-    <string name="mime_type_video_ext" msgid="185438149044230136">"<xliff:g id="EXTENSION">%1$s</xliff:g> વીડિઓ"</string>
+    <string name="mime_type_video_ext" msgid="185438149044230136">"<xliff:g id="EXTENSION">%1$s</xliff:g> વીડિયો"</string>
     <string name="mime_type_image" msgid="2134307276151645257">"છબી"</string>
     <string name="mime_type_image_ext" msgid="5743552697560999471">"<xliff:g id="EXTENSION">%1$s</xliff:g> છબી"</string>
     <string name="mime_type_compressed" msgid="8737300936080662063">"આર્કાઇવ"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index fd1ef77..1606652 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1586,8 +1586,8 @@
     <string name="launchBrowserDefault" msgid="6328349989932924119">"Luncurkan Browser?"</string>
     <string name="SetupCallDefault" msgid="5581740063237175247">"Terima panggilan?"</string>
     <string name="activity_resolver_use_always" msgid="5575222334666843269">"Selalu"</string>
-    <string name="activity_resolver_set_always" msgid="4142825808921411476">"Setel untuk selalu membuka"</string>
-    <string name="activity_resolver_use_once" msgid="948462794469672658">"Hanya sekali"</string>
+    <string name="activity_resolver_set_always" msgid="4142825808921411476">"Selalu gunakan"</string>
+    <string name="activity_resolver_use_once" msgid="948462794469672658">"Sekali ini saja"</string>
     <string name="activity_resolver_app_settings" msgid="6758823206817748026">"Setelan"</string>
     <string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s tidak mendukung profil kerja"</string>
     <string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"Tablet"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 6a499dd..095615d 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -142,7 +142,7 @@
     <string name="wfcSpnFormat_wifi" msgid="1376356951297043426">"Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="7178561009225028264">"Chiamate Wi-Fi"</string>
     <string name="wfcSpnFormat_vowifi" msgid="8371335230890725606">"VoWifi"</string>
-    <string name="wifi_calling_off_summary" msgid="5626710010766902560">"Off"</string>
+    <string name="wifi_calling_off_summary" msgid="5626710010766902560">"OFF"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Chiamata tramite Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Chiamata su rete mobile"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Solo Wi-Fi"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a77e7d6..43b2eea 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -550,7 +550,7 @@
     <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"פעולת טביעת האצבע בוטלה בידי המשתמש."</string>
     <string name="fingerprint_error_lockout" msgid="7853461265604738671">"יותר מדי ניסיונות. נסה שוב מאוחר יותר."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"יותר מדי ניסיונות. חיישן טביעות האצבע הושבת."</string>
-    <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"נסה שוב."</string>
+    <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"כדאי לנסות שוב."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"לא נרשמו טביעות אצבע."</string>
     <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"במכשיר זה אין חיישן טביעות אצבע."</string>
     <string name="fingerprint_name_template" msgid="8941662088160289778">"אצבע <xliff:g id="FINGERID">%d</xliff:g>"</string>
@@ -821,8 +821,8 @@
     <string name="lockscreen_emergency_call" msgid="7500692654885445299">"חירום"</string>
     <string name="lockscreen_return_to_call" msgid="3156883574692006382">"חזרה לשיחה"</string>
     <string name="lockscreen_pattern_correct" msgid="8050630103651508582">"נכון!"</string>
-    <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"נסה שוב"</string>
-    <string name="lockscreen_password_wrong" msgid="8605355913868947490">"נסה שוב"</string>
+    <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"כדאי לנסות שוב"</string>
+    <string name="lockscreen_password_wrong" msgid="8605355913868947490">"כדאי לנסות שוב"</string>
     <string name="lockscreen_storage_locked" msgid="634993789186443380">"בטל את הנעילה לכל התכונות והנתונים"</string>
     <string name="faceunlock_multiple_failures" msgid="681991538434031708">"חרגת ממספר הניסיונות המרבי של זיהוי פנים"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="1248431165144893792">"‏אין כרטיס SIM"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 699ea2e..f028ea8 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1297,7 +1297,7 @@
     <string name="wifi_p2p_failed_message" msgid="6296397512378755690">"ವೈ-ಫೈ ಡೈರೆಕ್ಟ್ ಪ್ರಾರಂಭಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
     <string name="wifi_p2p_enabled_notification_title" msgid="9128862563403191596">"ವೈ-ಫೈ ಡೈರೆಕ್ಟ್ ಆನ್ ಆಗಿದೆ"</string>
     <string name="wifi_p2p_enabled_notification_message" msgid="5571179544720861510">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
-    <string name="accept" msgid="5447154347815825107">"ಸ್ವೀಕರಿಸು"</string>
+    <string name="accept" msgid="5447154347815825107">"ಸ್ವೀಕರಿಸಿ"</string>
     <string name="decline" msgid="6490507610282145874">"ನಿರಾಕರಿಸಿ"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="355410493918793111">"ಆಹ್ವಾನವನ್ನು ಕಳುಹಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_p2p_invitation_to_connect_title" msgid="8082524320754820762">"ಸಂಪರ್ಕಗೊಳ್ಳಲು ಆಹ್ವಾನ"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 96d0163..cc7fa89 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -612,8 +612,8 @@
     <string name="permdesc_register_call_provider" msgid="4201429251459068613">"Колдонмого жаңы телеком туташууларын каттоо мүмкүнчүлүгүн берет."</string>
     <string name="permlab_connection_manager" msgid="3179365584691166915">"телеком туташууларын башкаруу"</string>
     <string name="permdesc_connection_manager" msgid="1426093604238937733">"Колдонмого телеком туташууларын башкаруу мүмкүнчүлүгүн берет."</string>
-    <string name="permlab_bind_incall_service" msgid="5990625112603493016">"чалуу экраны менен байланыштыруу"</string>
-    <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"Колдонмого чалуу экраны качан жана кандай көрүнө тургандыгын башкаруу мүмкүнчүлүгүн берет."</string>
+    <string name="permlab_bind_incall_service" msgid="5990625112603493016">"сүйлөшүп жатканда экранды башкара аласыз"</string>
+    <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"Сүйлөшүп жатканда экранды башкара аласыз."</string>
     <string name="permlab_bind_connection_service" msgid="5409268245525024736">"телефония кызматтары"</string>
     <string name="permdesc_bind_connection_service" msgid="6261796725253264518">"Колдонмого чалууларды жасоо/кабыл алуу үчүн телефония кызматтары менен байланышууга уруксат берет."</string>
     <string name="permlab_control_incall_experience" msgid="6436863486094352987">"чалуу ичиндеги колдонуучу тажрыйбасын камсыз кылуу"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 56702dd..bfa9541 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -853,7 +853,7 @@
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="2373955520011165432">"Du har gjort feil <xliff:g id="NUMBER">%d</xliff:g> ganger i forsøk på å låse opp TV-en. TV-en blir nå tilbakestilt til fabrikkstandard."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"Du har foretatt <xliff:g id="NUMBER">%d</xliff:g> mislykkede opplåsinger av telefonen. Telefonen blir nå tilbakestilt til fabrikkinnstillingene."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"Prøv igjen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
-    <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Glemt mønsteret?"</string>
+    <string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Har du glemt mønsteret?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Opplåsing av konto"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"For mange forsøk på tegning av mønster"</string>
     <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Logg på med Google-kontoen din for å låse opp."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 86f80b7..4a5d00a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -435,7 +435,7 @@
     <string name="permdesc_camera" msgid="1354600178048761499">"यस अनुप्रयोगले जुनसुकै समय क्यामेराको प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ।"</string>
     <string name="permlab_vibrate" msgid="8596800035791962017">"कम्पन नियन्त्रण गर्नुहोस्"</string>
     <string name="permdesc_vibrate" msgid="8733343234582083721">"अनुप्रयोगलाई भाइब्रेटर नियन्त्रण गर्न अनुमति दिन्छ।"</string>
-    <string name="permlab_callPhone" msgid="1798582257194643320">"फोन नम्बरहरूमा सिधै कल गर्नुहोस्"</string>
+    <string name="permlab_callPhone" msgid="1798582257194643320">"फोन नम्बरहरूमा सीधै कल गर्नुहोस्"</string>
     <string name="permdesc_callPhone" msgid="5439809516131609109">"तपाईँको हस्तक्षेप बेगरै फोन नम्बर कल गर्न अनुप्रयोगलाई अनुमति दिन्छ। यसले अनपेक्षित शुल्क वा कलहरू गराउन सक्छ। यसले अनुप्रयोगलाई आपतकालीन नम्बरहरू कल गर्न अनुमति दिँदैन विचार गर्नुहोस्। खराब अनुप्रयोगहरूले तपाईँको स्वीकार बिना कलहरू गरेर तपाईँलाई बढी पैसा तिराउन सक्छ।"</string>
     <string name="permlab_accessImsCallService" msgid="442192920714863782">"IMS कल सेवा पहुँच गर्नुहोस्"</string>
     <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"तपाईँको हस्तक्षेप बिना नै कल गर्न IMS सेवा प्रयोग गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 045f4bb..ab954555 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3361,6 +3361,26 @@
     <!-- If there is ever a ringtone set for some setting, but that ringtone can no longer be resolved, t his is shown instead.  For example, if the ringtone was on a SD card and it had been removed, this woudl be shown for ringtones on that SD card. -->
     <string name="ringtone_unknown">Unknown</string>
 
+    <!-- Start of string constants used to inform the user that the current network may be failing to connect due to not supporting randomized MAC-->
+    <!-- Notification title [CHAR_LIMIT=NONE]-->
+    <string name="wifi_cannot_connect_with_randomized_mac_title">Can\u2019t connect to <xliff:g id="ssid" example="SSID_1">%1$s</xliff:g></string>
+    <!-- Notification text [CHAR_LIMIT=NONE]-->
+    <string name="wifi_cannot_connect_with_randomized_mac_message">Tap to change privacy settings and retry</string>
+    <!-- Title of the dialog which pops up when the notification is tapped. [CHAR_LIMIT=NONE]-->
+    <string name="wifi_disable_mac_randomization_dialog_title">Change privacy setting?</string>
+    <!-- Dialog text [CHAR_LIMIT=NONE]-->
+    <string name="wifi_disable_mac_randomization_dialog_message"><xliff:g id="ssid" example="SSID_1">%1$s</xliff:g> may want to connect using your device MAC address, a unique identifier. This may allow your device\u2019s location to be tracked by nearby devices.
+        \n\nIf you continue, <xliff:g id="ssid" example="SSID_1">%1$s</xliff:g> will change your privacy setting and try to connect again.</string>
+    <!-- Text of the button that will disable MAC randomization for the network when tapped. [CHAR_LIMIT=NONE]-->
+    <string name="wifi_disable_mac_randomization_dialog_confirm_text">Change setting</string>
+    <!-- Toast message which shows up after MAC randomization for the network is disabled. [CHAR_LIMIT=NONE]-->
+    <string name="wifi_disable_mac_randomization_dialog_success">Setting updated. Try Connecting again.</string>
+    <!-- Toast message which shows up if the operation failed. [CHAR_LIMIT=NONE]-->
+    <string name="wifi_disable_mac_randomization_dialog_failure">Can\u2019t change privacy setting</string>
+    <!-- Toast message which shows up if the network no longer exists on the device. [CHAR_LIMIT=NONE]-->
+    <string name="wifi_disable_mac_randomization_dialog_network_not_found">Network not found</string>
+    <!-- End of string constants used to inform the user that the current network may be failing to connect due to not supporting randomized MAC-->
+
     <!-- A notification is shown when there are open wireless networks nearby.  This is the notification's title. -->
     <plurals name="wifi_available">
         <item quantity="one">Wi-Fi network available</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4c13076..aff7f61 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2059,6 +2059,14 @@
   <java-symbol type="layout" name="safe_mode" />
   <java-symbol type="layout" name="simple_list_item_2_single_choice" />
   <java-symbol type="layout" name="app_error_dialog" />
+  <java-symbol type="string" name="wifi_cannot_connect_with_randomized_mac_title" />
+  <java-symbol type="string" name="wifi_cannot_connect_with_randomized_mac_message" />
+  <java-symbol type="string" name="wifi_disable_mac_randomization_dialog_title" />
+  <java-symbol type="string" name="wifi_disable_mac_randomization_dialog_message" />
+  <java-symbol type="string" name="wifi_disable_mac_randomization_dialog_confirm_text" />
+  <java-symbol type="string" name="wifi_disable_mac_randomization_dialog_success" />
+  <java-symbol type="string" name="wifi_disable_mac_randomization_dialog_failure" />
+  <java-symbol type="string" name="wifi_disable_mac_randomization_dialog_network_not_found" />
   <java-symbol type="plurals" name="wifi_available" />
   <java-symbol type="plurals" name="wifi_available_detailed" />
   <java-symbol type="string" name="wifi_available_title" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 6289262..2b37a0c 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1733,6 +1733,7 @@
         <item name="colorBackground">@color/background_device_default_light</item>
         <item name="colorBackgroundFloating">@color/background_device_default_light</item>
         <item name="layout_gravity">center</item>
+        <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
     </style>
 
     <style name="Theme.DeviceDefault.Notification" parent="@style/Theme.Material.Notification">
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index a371a1d8..fd9ce43 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -110,24 +110,34 @@
                 mComponentNames = componentNameString.split(FACET_FILTER_DELIMITER);
             }
 
-            setOnClickListener(v -> {
-                intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, mSelected);
-                mContext.startActivityAsUser(intent, UserHandle.CURRENT);
-            });
+            setOnClickListener(getButtonClickListener(intent));
 
             if (longPressIntentString != null) {
                 final Intent longPressIntent = Intent.parseUri(longPressIntentString,
                         Intent.URI_INTENT_SCHEME);
-                setOnLongClickListener(v -> {
-                    mContext.startActivityAsUser(longPressIntent, UserHandle.CURRENT);
-                    return true;
-                });
+                setOnLongClickListener(getButtonLongClickListener(longPressIntent));
             }
         } catch (Exception e) {
             throw new RuntimeException("Failed to attach intent", e);
         }
     }
 
+    /** Defines the behavior of a button click. */
+    protected OnClickListener getButtonClickListener(Intent toSend) {
+        return v -> {
+            toSend.putExtra(EXTRA_FACET_LAUNCH_PICKER, mSelected);
+            mContext.startActivityAsUser(toSend, UserHandle.CURRENT);
+        };
+    }
+
+    /** Defines the behavior of a long click. */
+    protected OnLongClickListener getButtonLongClickListener(Intent toSend) {
+        return v -> {
+            mContext.startActivityAsUser(toSend, UserHandle.CURRENT);
+            return true;
+        };
+    }
+
     private void setupIcons(TypedArray styledAttributes) {
         mSelectedAlpha = styledAttributes.getFloat(
                 R.styleable.CarFacetButton_selectedAlpha, mSelectedAlpha);
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
index 8879742..bdf23c5 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -90,17 +90,7 @@
         try {
             if (mIntent != null) {
                 final Intent intent = Intent.parseUri(mIntent, Intent.URI_INTENT_SCHEME);
-                setOnClickListener(v -> {
-                    try {
-                        if (mBroadcastIntent) {
-                            mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
-                            return;
-                        }
-                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Failed to launch intent", e);
-                    }
-                });
+                setOnClickListener(getButtonClickListener(intent));
             }
         } catch (URISyntaxException e) {
             throw new RuntimeException("Failed to attach intent", e);
@@ -109,21 +99,41 @@
         try {
             if (mLongIntent != null) {
                 final Intent intent = Intent.parseUri(mLongIntent, Intent.URI_INTENT_SCHEME);
-                setOnLongClickListener(v -> {
-                    try {
-                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Failed to launch intent", e);
-                    }
-                    // consume event either way
-                    return true;
-                });
+                setOnLongClickListener(getButtonLongClickListener(intent));
             }
         } catch (URISyntaxException e) {
             throw new RuntimeException("Failed to attach long press intent", e);
         }
     }
 
+    /** Defines the behavior of a button click. */
+    protected OnClickListener getButtonClickListener(Intent toSend) {
+        return v -> {
+            try {
+                if (mBroadcastIntent) {
+                    mContext.sendBroadcastAsUser(toSend, UserHandle.CURRENT);
+                    return;
+                }
+                mContext.startActivityAsUser(toSend, UserHandle.CURRENT);
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to launch intent", e);
+            }
+        };
+    }
+
+    /** Defines the behavior of a long click. */
+    protected OnLongClickListener getButtonLongClickListener(Intent toSend) {
+        return v -> {
+            try {
+                mContext.startActivityAsUser(toSend, UserHandle.CURRENT);
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to launch intent", e);
+            }
+            // consume event either way
+            return true;
+        };
+    }
+
     /**
      * @param selected true if should indicate if this is a selected state, false otherwise
      */
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index c05c4cd..33085a1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -64,6 +64,8 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -716,6 +718,23 @@
                 }
             } catch (Throwable t) {
                 Slog.wtf(LOG_TAG, "Failed to write settings, restoring backup", t);
+                if (t instanceof IOException) {
+                    // we failed to create a directory, so log the permissions and existence
+                    // state for the settings file and directory
+                    logSettingsDirectoryInformation(destination.getBaseFile());
+                    if (t.getMessage().contains("Couldn't create directory")) {
+                        // attempt to create the directory with Files.createDirectories, which
+                        // throws more informative errors than File.mkdirs.
+                        Path parentPath = destination.getBaseFile().getParentFile().toPath();
+                        try {
+                            Files.createDirectories(parentPath);
+                            Slog.i(LOG_TAG, "Successfully created " + parentPath);
+                        } catch (Throwable t2) {
+                            Slog.e(LOG_TAG, "Failed to write " + parentPath
+                                    + " with Files.writeDirectories", t2);
+                        }
+                    }
+                }
                 destination.failWrite(out);
             } finally {
                 IoUtils.closeQuietly(out);
@@ -729,6 +748,33 @@
         }
     }
 
+    private static void logSettingsDirectoryInformation(File settingsFile) {
+        File parent = settingsFile.getParentFile();
+        Slog.i(LOG_TAG, "directory info for directory/file " + settingsFile
+                + " with stacktrace ", new Exception());
+        File ancestorDir = parent;
+        while (ancestorDir != null) {
+            if (!ancestorDir.exists()) {
+                Slog.i(LOG_TAG, "ancestor directory " + ancestorDir
+                        + " does not exist");
+                ancestorDir = ancestorDir.getParentFile();
+            } else {
+                Slog.i(LOG_TAG, "ancestor directory " + ancestorDir
+                        + " exists");
+                Slog.i(LOG_TAG, "ancestor directory " + ancestorDir
+                        + " permissions: r: " + ancestorDir.canRead() + " w: "
+                        + ancestorDir.canWrite() + " x: " + ancestorDir.canExecute());
+                File ancestorParent = ancestorDir.getParentFile();
+                if (ancestorParent != null) {
+                    Slog.i(LOG_TAG, "ancestor's parent directory " + ancestorParent
+                            + " permissions: r: " + ancestorParent.canRead() + " w: "
+                            + ancestorParent.canWrite() + " x: " + ancestorParent.canExecute());
+                }
+                break;
+            }
+        }
+    }
+
     static void writeSingleSetting(int version, XmlSerializer serializer, String id,
             String name, String value, String defaultValue, String packageName,
             String tag, boolean defaultSysSet) throws IOException {
@@ -803,6 +849,7 @@
             in = new AtomicFile(mStatePersistFile).openRead();
         } catch (FileNotFoundException fnfe) {
             Slog.i(LOG_TAG, "No settings state " + mStatePersistFile);
+            logSettingsDirectoryInformation(mStatePersistFile);
             addHistoricalOperationLocked(HISTORICAL_OPERATION_INITIALIZE, null);
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
index 39c9632..6474b39 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
@@ -81,12 +81,6 @@
         });
     }
 
-    private void animate() {
-        mAnimator.cancel();
-        mAnimator.setFloatValues(mReveal, mAwake ? MAX_REVEAL : MIN_REVEAL);
-        mAnimator.start();
-    }
-
     public float getReveal() {
         return mReveal;
     }
@@ -95,8 +89,8 @@
         if (DEBUG) {
             Log.d(TAG, "updateAwake: awake=" + awake + ", duration=" + duration);
         }
+        mAnimator.cancel();
         mAwake = awake;
-        mAnimator.setDuration(duration);
         if (duration == 0) {
             // We are transiting from home to aod or aod to home directly,
             // we don't need to do transition in these cases.
@@ -105,7 +99,9 @@
             mRevealListener.onRevealStateChanged();
             mRevealListener.onRevealEnd();
         } else {
-            animate();
+            mAnimator.setDuration(duration);
+            mAnimator.setFloatValues(mReveal, mAwake ? MAX_REVEAL : MIN_REVEAL);
+            mAnimator.start();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index da2692e..9b30a77 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -475,9 +475,9 @@
                     SystemUiDeviceConfigFlags
                             .SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS,
                     1000);
-            List<Notification.Action> smartActions = buildSmartActions(
-                    GlobalScreenshot.getSmartActions(mScreenshotId, smartActionsFuture,
-                            timeoutMs, mSmartActionsProvider), context);
+            List<Notification.Action> smartActions = GlobalScreenshot.getSmartActions(mScreenshotId,
+                    smartActionsFuture, timeoutMs, mSmartActionsProvider);
+            smartActions = buildSmartActions(smartActions, context);
             for (Notification.Action action : smartActions) {
                 notificationBuilder.addAction(action);
             }
@@ -1082,8 +1082,8 @@
             List<Notification.Action> actions = smartActionsFuture.get(timeoutMs,
                     TimeUnit.MILLISECONDS);
             long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
-            Slog.d(TAG, String.format("Wait time for smart actions: %d ms",
-                    waitTimeMs));
+            Slog.d(TAG, String.format("Got %d smart actions. Wait time: %d ms",
+                    actions.size(), waitTimeMs));
             notifyScreenshotOp(screenshotId, smartActionsProvider,
                     ScreenshotNotificationSmartActionsProvider.ScreenshotOp.WAIT_FOR_SMART_ACTIONS,
                     ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.SUCCESS,
@@ -1091,7 +1091,8 @@
             return actions;
         } catch (Throwable e) {
             long waitTimeMs = SystemClock.uptimeMillis() - startTimeMs;
-            Slog.d(TAG, "Failed to obtain screenshot notification smart actions.", e);
+            Slog.e(TAG, String.format("Error getting smart actions. Wait time: %d ms", waitTimeMs),
+                    e);
             ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus status =
                     (e instanceof TimeoutException)
                             ? ScreenshotNotificationSmartActionsProvider.ScreenshotOpStatus.TIMEOUT
@@ -1209,14 +1210,16 @@
     public static class SmartActionsReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
-            PendingIntent actionIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
+            PendingIntent pendingIntent = intent.getParcelableExtra(EXTRA_ACTION_INTENT);
+            Intent actionIntent = pendingIntent.getIntent();
+            String actionType = intent.getStringExtra(EXTRA_ACTION_TYPE);
+            Slog.d(TAG, "Executing smart action [" + actionType + "]:" + actionIntent);
             ActivityOptions opts = ActivityOptions.makeBasic();
-            context.startActivityAsUser(actionIntent.getIntent(), opts.toBundle(),
+            context.startActivityAsUser(actionIntent, opts.toBundle(),
                     UserHandle.CURRENT);
 
-            Slog.d(TAG, "Screenshot notification smart action is invoked.");
             notifyScreenshotAction(context, intent.getStringExtra(EXTRA_ID),
-                    intent.getStringExtra(EXTRA_ACTION_TYPE),
+                    actionType,
                     true);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index aa7fce7..91cf89c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -344,6 +344,7 @@
     private boolean mBrightnessMirrorVisible;
     protected BiometricUnlockController mBiometricUnlockController;
     protected LightBarController mLightBarController;
+    @Nullable
     protected LockscreenWallpaper mLockscreenWallpaper;
     @VisibleForTesting
     protected AutoHideController mAutoHideController;
@@ -891,7 +892,7 @@
 
         createNavigationBar(result);
 
-        if (ENABLE_LOCKSCREEN_WALLPAPER) {
+        if (ENABLE_LOCKSCREEN_WALLPAPER && mWallpaperSupported) {
             mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
         }
 
@@ -2638,7 +2639,7 @@
                 if (mRemoteInputManager.getController() != null) {
                     mRemoteInputManager.getController().closeRemoteInputs();
                 }
-                if (mBubbleController.isStackExpanded()) {
+                if (mBubbleController != null && mBubbleController.isStackExpanded()) {
                     mBubbleController.collapseStack();
                 }
                 if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) {
@@ -2654,7 +2655,7 @@
                 if (mStatusBarWindowController != null) {
                     mStatusBarWindowController.setNotTouchable(false);
                 }
-                if (mBubbleController.isStackExpanded()) {
+                if (mBubbleController != null && mBubbleController.isStackExpanded()) {
                     mBubbleController.collapseStack();
                 }
                 finishBarAnimations();
@@ -2748,7 +2749,9 @@
 
     @Override
     public void setLockscreenUser(int newUserId) {
-        mLockscreenWallpaper.setCurrentUser(newUserId);
+        if (mLockscreenWallpaper != null) {
+            mLockscreenWallpaper.setCurrentUser(newUserId);
+        }
         mScrimController.setCurrentUser(newUserId);
         if (mWallpaperSupported) {
             mWallpaperChangedReceiver.onReceive(mContext, null);
@@ -3386,7 +3389,9 @@
             if (mNotificationPanel.canPanelBeCollapsed()) {
                 animateCollapsePanels();
             } else {
-                mBubbleController.performBackPressIfNeeded();
+                if (mBubbleController != null) {
+                    mBubbleController.performBackPressIfNeeded();
+                }
             }
             return true;
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 05b937a..9bad734c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -217,6 +217,8 @@
 
     private final AppOpsManager mAppOpsManager;
 
+    private final ActivityTaskManagerInternal mActivityTaskManagerService;
+
     private final MainHandler mMainHandler;
 
     private final GlobalActionPerformer mGlobalActionPerformer;
@@ -308,6 +310,7 @@
         mMainHandler = new MainHandler(mContext.getMainLooper());
         mGlobalActionPerformer = new GlobalActionPerformer(mContext, mWindowManagerService);
         mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
+        mActivityTaskManagerService = LocalServices.getService(ActivityTaskManagerInternal.class);
 
         registerBroadcastReceivers();
         new AccessibilityContentObserver(mMainHandler).register(
@@ -1635,7 +1638,8 @@
                 if (service == null) {
                     service = new AccessibilityServiceConnection(userState, mContext, componentName,
                             installedService, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
-                            this, mWindowManagerService, mGlobalActionPerformer);
+                            this, mWindowManagerService, mGlobalActionPerformer,
+                            mActivityTaskManagerService);
                 } else if (userState.mBoundServices.contains(service)) {
                     continue;
                 }
@@ -3028,7 +3032,7 @@
                     userState, mContext,
                     COMPONENT_NAME, info, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
                     AccessibilityManagerService.this, mWindowManagerService,
-                    mGlobalActionPerformer) {
+                    mGlobalActionPerformer, mActivityTaskManagerService) {
                 @Override
                 public boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) {
                     return true;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index b66caa5..91031e6 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -34,6 +34,7 @@
 
 import com.android.server.accessibility.AccessibilityManagerService.SecurityPolicy;
 import com.android.server.accessibility.AccessibilityManagerService.UserState;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
 import java.lang.ref.WeakReference;
@@ -58,6 +59,7 @@
     */
     final WeakReference<UserState> mUserStateWeakReference;
     final Intent mIntent;
+    final ActivityTaskManagerInternal mActivityTaskManagerService;
 
     private final Handler mMainHandler;
 
@@ -69,7 +71,8 @@
             AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
             Object lock, SecurityPolicy securityPolicy, SystemSupport systemSupport,
             WindowManagerInternal windowManagerInternal,
-            GlobalActionPerformer globalActionPerfomer) {
+            GlobalActionPerformer globalActionPerfomer,
+            ActivityTaskManagerInternal activityTaskManagerService) {
         super(context, componentName, accessibilityServiceInfo, id, mainHandler, lock,
                 securityPolicy, systemSupport, windowManagerInternal, globalActionPerfomer);
         mUserStateWeakReference = new WeakReference<UserState>(userState);
@@ -77,6 +80,7 @@
         mMainHandler = mainHandler;
         mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                 com.android.internal.R.string.accessibility_binding_label);
+        mActivityTaskManagerService = activityTaskManagerService;
         final long identity = Binder.clearCallingIdentity();
         try {
             mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, mSystemSupport.getPendingIntentActivity(
@@ -103,6 +107,9 @@
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
+        mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(),
+                mAccessibilityServiceInfo.getResolveInfo().serviceInfo.applicationInfo.uid,
+                userState.mUserId);
     }
 
     public void unbindLocked() {
@@ -111,6 +118,9 @@
         if (userState == null) return;
         userState.removeServiceLocked(this);
         mSystemSupport.getMagnificationController().resetAllIfNeeded(mId);
+        // Set uid to -1 to clear allowing app switches.
+        mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(),
+                /* uid= */ -1, userState.mUserId);
         resetLocked();
     }
 
@@ -208,6 +218,12 @@
     @Override
     public void onServiceDisconnected(ComponentName componentName) {
         binderDied();
+        UserState userState = mUserStateWeakReference.get();
+        if (userState != null) {
+            // Set uid to -1 to clear allowing app switches.
+            mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(),
+                    /* uid= */ -1, userState.mUserId);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 1432f57..0d28822 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1289,6 +1289,33 @@
     }
 
     protected UserAccounts getUserAccounts(int userId) {
+        try {
+            return getUserAccountsNotChecked(userId);
+        } catch (RuntimeException e) {
+            if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+                // Let it go...
+                throw e;
+            }
+            // User accounts database is corrupted, we must wipe out the whole user, otherwise the
+            // system will crash indefinitely
+            Slog.wtf(TAG, "Removing user " + userId + " due to exception (" + e + ") reading its "
+                    + "account database");
+            if (userId == ActivityManager.getCurrentUser() && userId != UserHandle.USER_SYSTEM) {
+                Slog.i(TAG, "Switching to system user first");
+                try {
+                    ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM);
+                } catch (RemoteException re) {
+                    Slog.e(TAG, "Could not switch to " + UserHandle.USER_SYSTEM + ": " + re);
+                }
+            }
+            if (!getUserManager().removeUserEvenWhenDisallowed(userId)) {
+                Slog.e(TAG, "could not remove user " + userId);
+            }
+            throw e;
+        }
+    }
+
+    private UserAccounts getUserAccountsNotChecked(int userId) {
         synchronized (mUsers) {
             UserAccounts accounts = mUsers.get(userId);
             boolean validateAccounts = false;
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index 183e059..ebfc2a0 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -66,9 +66,7 @@
         setCancelable(false);
         Resources res = getContext().getResources();
         // Custom view due to alignment and font size requirements
-        // TODO (b/145021634): disabled because it's delaying user switch by 3 seconds
-        // getContext()
-        // .setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
+        getContext().setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert_UserSwitchingDialog);
         View view = LayoutInflater.from(getContext()).inflate(
                 R.layout.car_user_switching_dialog,
                 null);
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 877bef7..bd17e84 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -31,3 +31,5 @@
 narayan@google.com
 
 per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
+
+per-file CarUserSwitchingDialog.java = keunyoung@google.com, felipeal@google.com, gurunagarajan@google.com
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index 98f5557..0ec4454 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -24,6 +24,7 @@
 import android.os.Message;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewTreeObserver;
@@ -46,6 +47,9 @@
     // Time to wait for the onWindowShown() callback before continuing the user switch
     private static final int WINDOW_SHOWN_TIMEOUT_MS = 3000;
 
+    // User switching doesn't happen that frequently, so it doesn't hurt to have it always on
+    protected static final boolean DEBUG = true;
+
     private final ActivityManagerService mService;
     private final int mUserId;
     private static final int MSG_START_USER = 1;
@@ -118,7 +122,7 @@
 
     @Override
     public void show() {
-        // Slog.v(TAG, "show called");
+        if (DEBUG) Slog.d(TAG, "show called");
         super.show();
         final View decorView = getWindow().getDecorView();
         if (decorView != null) {
@@ -132,13 +136,14 @@
 
     @Override
     public void onWindowShown() {
-        // Slog.v(TAG, "onWindowShown called");
+        if (DEBUG) Slog.d(TAG, "onWindowShown called");
         startUser();
     }
 
     void startUser() {
         synchronized (this) {
             if (!mStartedUser) {
+                Slog.i(TAG, "starting user " + mUserId);
                 mService.mUserController.startUserInForeground(mUserId);
                 dismiss();
                 mStartedUser = true;
@@ -147,6 +152,8 @@
                     decorView.getViewTreeObserver().removeOnWindowShownListener(this);
                 }
                 mHandler.removeMessages(MSG_START_USER);
+            } else {
+                Slog.i(TAG, "user " + mUserId + " already started");
             }
         }
     }
@@ -156,6 +163,8 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_START_USER:
+                    Slog.w(TAG, "user switch window not shown in "
+                            + WINDOW_SHOWN_TIMEOUT_MS + " ms");
                     startUser();
                     break;
             }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f20957a..4a46910 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -163,6 +163,7 @@
 import android.os.IInterface;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -281,6 +282,9 @@
     public static final boolean ENABLE_CHILD_NOTIFICATIONS
             = SystemProperties.getBoolean("debug.child_notifs", true);
 
+    // pullStats report request: undecorated remote view stats
+    public static final int REPORT_REMOTE_VIEWS = 0x01;
+
     static final boolean DEBUG_INTERRUPTIVENESS = SystemProperties.getBoolean(
             "debug.notification.interruptiveness", false);
 
@@ -3734,6 +3738,8 @@
             try {
                 if (filter.stats) {
                     dumpJson(pw, filter);
+                } else if (filter.rvStats) {
+                    dumpRemoteViewStats(pw, filter);
                 } else if (filter.proto) {
                     dumpProto(fd, filter);
                 } else if (filter.criticalPriority) {
@@ -4210,6 +4216,49 @@
             new NotificationShellCmd(NotificationManagerService.this)
                     .exec(this, in, out, err, args, callback, resultReceiver);
         }
+
+        /**
+         * Get stats committed after startNs
+         *
+         * @param startNs Report stats committed after this time in nanoseconds.
+         * @param report  Indicatess which section to include in the stats.
+         * @param doAgg   Whether to aggregate the stats or keep them separated.
+         * @param out   List of protos of individual commits or one representing the
+         *                aggregate.
+         * @return the report time in nanoseconds, or 0 on error.
+         */
+        @Override
+        public long pullStats(long startNs, int report, boolean doAgg,
+                List<ParcelFileDescriptor> out) {
+            checkCallerIsSystemOrShell();
+            long startMs = TimeUnit.MILLISECONDS.convert(startNs, TimeUnit.NANOSECONDS);
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                switch (report) {
+                    case REPORT_REMOTE_VIEWS:
+                        Slog.e(TAG, "pullStats REPORT_REMOTE_VIEWS from: "
+                                + startMs + "  wtih " + doAgg);
+                        PulledStats stats = mUsageStats.remoteViewStats(startMs, doAgg);
+                        if (stats != null) {
+                            out.add(stats.toParcelFileDescriptor(report));
+                            Slog.e(TAG, "exiting pullStats with: " + out.size());
+                            long endNs = TimeUnit.NANOSECONDS
+                                    .convert(stats.endTimeMs(), TimeUnit.MILLISECONDS);
+                            return endNs;
+                        }
+                        Slog.e(TAG, "null stats for: " + report);
+                }
+            } catch (IOException e) {
+
+                Slog.e(TAG, "exiting pullStats: on error", e);
+                return 0;
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            Slog.e(TAG, "exiting pullStats: bad request");
+            return 0;
+        }
     };
 
     @VisibleForTesting
@@ -4425,6 +4474,15 @@
         pw.println(dump);
     }
 
+    private void dumpRemoteViewStats(PrintWriter pw, @NonNull DumpFilter filter) {
+        PulledStats stats = mUsageStats.remoteViewStats(filter.since, true);
+        if (stats == null) {
+            pw.println("no remote view stats reported.");
+            return;
+        }
+        stats.dump(REPORT_REMOTE_VIEWS, pw, filter);
+    }
+
     private void dumpProto(FileDescriptor fd, @NonNull DumpFilter filter) {
         final ProtoOutputStream proto = new ProtoOutputStream(fd);
         synchronized (mNotificationLock) {
@@ -8559,6 +8617,7 @@
         public boolean zen;
         public long since;
         public boolean stats;
+        public boolean rvStats;
         public boolean redact = true;
         public boolean proto = false;
         public boolean criticalPriority = false;
@@ -8594,6 +8653,14 @@
                     } else {
                         filter.since = 0;
                     }
+                } else if ("--remote-view-stats".equals(a)) {
+                    filter.rvStats = true;
+                    if (ai < args.length-1) {
+                        ai++;
+                        filter.since = Long.parseLong(args[ai]);
+                    } else {
+                        filter.since = 0;
+                    }
                 } else if (PRIORITY_ARG.equals(a)) {
                     // Bugreport will call the service twice with priority arguments, first to dump
                     // critical sections and then non critical ones. Set approriate filters
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index d630b9a..0c2b683 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -149,6 +149,7 @@
             stats.numPostedByApp++;
             stats.updateInterarrivalEstimate(now);
             stats.countApiUse(notification);
+            stats.numUndecoratedRemoteViews += (isUndecoratedRemoteView(notification) ? 1 : 0);
         }
         releaseAggregatedStatsLocked(aggregatedStatsArray);
         if (ENABLE_SQLITE_LOG) {
@@ -157,6 +158,13 @@
     }
 
     /**
+     * Does this notification use RemoveViews without a platform decoration?
+     */
+    protected static boolean isUndecoratedRemoteView(NotificationRecord notification) {
+        return (notification.getNotification().getNotificationStyle() == null);
+    }
+
+    /**
      * Called when a notification has been updated.
      */
     public synchronized void registerUpdatedByApp(NotificationRecord notification,
@@ -326,6 +334,15 @@
         return dump;
     }
 
+    public PulledStats remoteViewStats(long startMs, boolean aggregate) {
+        if (ENABLE_SQLITE_LOG) {
+            if (aggregate) {
+                return mSQLiteLog.remoteViewAggStats(startMs);
+            }
+        }
+        return null;
+    }
+
     public synchronized void dump(PrintWriter pw, String indent, DumpFilter filter) {
         if (ENABLE_AGGREGATED_IN_MEMORY_STATS) {
             for (AggregatedStats as : mStats.values()) {
@@ -403,6 +420,7 @@
         public int numRateViolations;
         public int numAlertViolations;
         public int numQuotaViolations;
+        public int numUndecoratedRemoteViews;
         public long mLastAccessTime;
 
         public AggregatedStats(Context context, String key) {
@@ -669,6 +687,8 @@
             output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n");
             output.append(indentPlusTwo).append(quietImportance.toString()).append("\n");
             output.append(indentPlusTwo).append(finalImportance.toString()).append("\n");
+            output.append(indentPlusTwo);
+            output.append("numUndecorateRVs=").append(numUndecoratedRemoteViews).append("\n");
             output.append(indent).append("}");
             return output.toString();
         }
@@ -1027,7 +1047,7 @@
         private static final int MSG_DISMISS = 4;
 
         private static final String DB_NAME = "notification_log.db";
-        private static final int DB_VERSION = 5;
+        private static final int DB_VERSION = 7;
 
         /** Age in ms after which events are pruned from the DB. */
         private static final long HORIZON_MS = 7 * 24 * 60 * 60 * 1000L;  // 1 week
@@ -1060,6 +1080,7 @@
         private static final String COL_FIRST_EXPANSIONTIME_MS = "first_expansion_time_ms";
         private static final String COL_AIRTIME_EXPANDED_MS = "expansion_airtime_ms";
         private static final String COL_EXPAND_COUNT = "expansion_count";
+        private static final String COL_UNDECORATED = "undecorated";
 
 
         private static final int EVENT_TYPE_POST = 1;
@@ -1085,12 +1106,20 @@
                 "COUNT(*) AS cnt, " +
                 "SUM(" + COL_MUTED + ") as muted, " +
                 "SUM(" + COL_NOISY + ") as noisy, " +
-                "SUM(" + COL_DEMOTED + ") as demoted " +
+                "SUM(" + COL_DEMOTED + ") as demoted, " +
+                "SUM(" + COL_UNDECORATED + ") as undecorated " +
                 "FROM " + TAB_LOG + " " +
                 "WHERE " +
                 COL_EVENT_TYPE + "=" + EVENT_TYPE_POST +
                 " AND " + COL_EVENT_TIME + " > %d " +
                 " GROUP BY " + COL_EVENT_USER_ID + ", day, " + COL_PKG;
+        private static final String UNDECORATED_QUERY = "SELECT " +
+                COL_PKG + ", " +
+                "MAX(" + COL_EVENT_TIME + ") as max_time " +
+                "FROM " + TAB_LOG + " " +
+                "WHERE " + COL_UNDECORATED + "> 0 " +
+                " AND " + COL_EVENT_TIME + " > %d " +
+                "GROUP BY " + COL_PKG;
 
         public SQLiteLog(Context context) {
             HandlerThread backgroundThread = new HandlerThread("notification-sqlite-log",
@@ -1146,7 +1175,8 @@
                             COL_AIRTIME_MS + " INT," +
                             COL_FIRST_EXPANSIONTIME_MS + " INT," +
                             COL_AIRTIME_EXPANDED_MS + " INT," +
-                            COL_EXPAND_COUNT + " INT" +
+                            COL_EXPAND_COUNT + " INT," +
+                            COL_UNDECORATED + " INT" +
                             ")");
                 }
 
@@ -1256,6 +1286,7 @@
             } else {
                 putPosttimeVisibility(r, cv);
             }
+            cv.put(COL_UNDECORATED, (isUndecoratedRemoteView(r) ? 1 : 0));
             SQLiteDatabase db = mHelper.getWritableDatabase();
             if (db.insert(TAB_LOG, null, cv) < 0) {
                 Log.wtf(TAG, "Error while trying to insert values: " + cv);
@@ -1332,5 +1363,22 @@
             }
             return dump;
         }
+
+        public PulledStats remoteViewAggStats(long startMs) {
+            PulledStats stats = new PulledStats(startMs);
+            SQLiteDatabase db = mHelper.getReadableDatabase();
+            String q = String.format(UNDECORATED_QUERY, startMs);
+            Cursor cursor = db.rawQuery(q, null);
+            try {
+                for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
+                    String pkg = cursor.getString(0);
+                    long maxTimeMs = cursor.getLong(1);
+                    stats.addUndecoratedPackage(pkg, maxTimeMs);
+                }
+            } finally {
+                cursor.close();
+            }
+            return stats;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/notification/PulledStats.java b/services/core/java/com/android/server/notification/PulledStats.java
new file mode 100644
index 0000000..ada890a
--- /dev/null
+++ b/services/core/java/com/android/server/notification/PulledStats.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.notification;
+
+import static com.android.server.notification.NotificationManagerService.REPORT_REMOTE_VIEWS;
+
+import android.os.ParcelFileDescriptor;
+import android.service.notification.NotificationRemoteViewsProto;
+import android.service.notification.PackageRemoteViewInfoProto;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PulledStats {
+    static final String TAG = "PulledStats";
+
+    private final long mTimePeriodStartMs;
+    private long mTimePeriodEndMs;
+    private List<String> mUndecoratedPackageNames;
+
+    public PulledStats(long startMs) {
+        mTimePeriodEndMs = mTimePeriodStartMs = startMs;
+        mUndecoratedPackageNames = new ArrayList<>();
+    }
+
+    ParcelFileDescriptor toParcelFileDescriptor(int report)
+            throws IOException {
+        final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
+        switch(report) {
+            case REPORT_REMOTE_VIEWS:
+                Thread thr = new Thread("NotificationManager pulled metric output") {
+                    public void run() {
+                        try {
+                            FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(
+                                    fds[1]);
+                            final ProtoOutputStream proto = new ProtoOutputStream(fout);
+                            writeToProto(report, proto);
+                            proto.flush();
+                            fout.close();
+                        } catch (IOException e) {
+                            Slog.w(TAG, "Failure writing pipe", e);
+                        }
+                    }
+                };
+                thr.start();
+                break;
+
+            default:
+                Slog.w(TAG, "Unknown pulled stats request: " + report);
+                break;
+        }
+        return fds[0];
+    }
+
+    /*
+     * @return the most recent timestamp in the report, as nanoseconds.
+     */
+    public long endTimeMs() {
+        return mTimePeriodEndMs;
+    }
+
+    public void dump(int report, PrintWriter pw, NotificationManagerService.DumpFilter filter) {
+        switch(report) {
+            case REPORT_REMOTE_VIEWS:
+                pw.print("  Packages with undecordated notifications (");
+                pw.print(mTimePeriodStartMs);
+                pw.print(" - ");
+                pw.print(mTimePeriodEndMs);
+                pw.println("):");
+                if (mUndecoratedPackageNames.size() == 0) {
+                    pw.println("    none");
+                } else {
+                    for (String pkg : mUndecoratedPackageNames) {
+                        if (!filter.filtered || pkg.equals(filter.pkgFilter)) {
+                            pw.println("    " + pkg);
+                        }
+                    }
+                }
+                break;
+
+            default:
+                pw.println("Unknown pulled stats request: " + report);
+                break;
+        }
+    }
+
+    @VisibleForTesting
+    void writeToProto(int report, ProtoOutputStream proto) {
+        switch(report) {
+            case REPORT_REMOTE_VIEWS:
+                for (String pkg: mUndecoratedPackageNames) {
+                    long token = proto.start(NotificationRemoteViewsProto.PACKAGE_REMOTE_VIEW_INFO);
+                    proto.write(PackageRemoteViewInfoProto.PACKAGE_NAME, pkg);
+                    proto.end(token);
+                }
+                break;
+
+            default:
+                Slog.w(TAG, "Unknown pulled stats request: " + report);
+                break;
+        }
+    }
+
+    public void addUndecoratedPackage(String packageName, long timestampMs) {
+        mUndecoratedPackageNames.add(packageName);
+        mTimePeriodEndMs = Math.max(mTimePeriodEndMs, timestampMs);
+    }
+}
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 4c33bec..b844362 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -48,6 +48,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.PermissionWhitelistFlags;
 import android.content.pm.PackageManagerInternal;
@@ -2601,7 +2602,7 @@
 
         // Make sure all dynamic permissions have been assigned to a package,
         // and make sure there are no dangling permissions.
-        flags = updatePermissions(changingPkgName, changingPkg, flags);
+        flags = updatePermissions(changingPkgName, changingPkg, flags, callback);
 
         synchronized (mLock) {
             if (mBackgroundPermissions == null) {
@@ -2651,7 +2652,8 @@
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
     }
 
-    private int updatePermissions(String packageName, PackageParser.Package pkg, int flags) {
+    private int updatePermissions(String packageName, PackageParser.Package pkg, int flags,
+            @Nullable PermissionCallback callback) {
         Set<BasePermission> needsUpdate = null;
         synchronized (mLock) {
             final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
@@ -2665,6 +2667,44 @@
                         && (pkg == null || !hasPermission(pkg, bp.getName()))) {
                         Slog.i(TAG, "Removing old permission tree: " + bp.getName()
                                 + " from package " + bp.getSourcePackageName());
+                        if (bp.isRuntime()) {
+                            final int[] userIds = mUserManagerInt.getUserIds();
+                            final int numUserIds = userIds.length;
+                            for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
+                                final int userId = userIds[userIdNum];
+
+                                mPackageManagerInt.forEachPackage((Package p) -> {
+                                    final String pName = p.packageName;
+                                    final ApplicationInfo appInfo =
+                                            mPackageManagerInt.getApplicationInfo(pName, 0,
+                                                    Process.SYSTEM_UID, UserHandle.USER_SYSTEM);
+                                    if (appInfo != null
+                                            && appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+                                        return;
+                                    }
+
+                                    final String permissionName = bp.getName();
+                                    if (checkPermission(permissionName, pName, Process.SYSTEM_UID,
+                                            userId) == PackageManager.PERMISSION_GRANTED) {
+                                        try {
+                                            revokeRuntimePermission(
+                                                    permissionName,
+                                                    pName,
+                                                    false,
+                                                    userId,
+                                                    callback);
+                                        } catch (IllegalArgumentException e) {
+                                            Slog.e(TAG,
+                                                    "Failed to revoke "
+                                                            + permissionName
+                                                            + " from "
+                                                            + pName,
+                                                    e);
+                                        }
+                                    }
+                                });
+                            }
+                        }
                         flags |= UPDATE_PERMISSIONS_ALL;
                         it.remove();
                     }
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index c76bbb0..d70b628 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -41,6 +41,7 @@
 import android.app.AppOpsManager.HistoricalOpsRequest;
 import android.app.AppOpsManager.HistoricalPackageOps;
 import android.app.AppOpsManager.HistoricalUidOps;
+import android.app.INotificationManager;
 import android.app.ProcessMemoryState;
 import android.app.StatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -140,6 +141,7 @@
 import com.android.server.SystemServiceManager;
 import com.android.server.am.MemoryStatUtil.IonAllocations;
 import com.android.server.am.MemoryStatUtil.MemoryStat;
+import com.android.server.notification.NotificationManagerService;
 import com.android.server.role.RoleManagerInternal;
 import com.android.server.storage.DiskStatsFileLogger;
 import com.android.server.storage.DiskStatsLoggingService;
@@ -1625,14 +1627,7 @@
                 if (statsFiles.size() != 1) {
                     return;
                 }
-                InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
-                        statsFiles.get(0));
-                int[] len = new int[1];
-                byte[] stats = readFully(stream, len);
-                StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
-                        wallClockNanos);
-                e.writeStorage(Arrays.copyOf(stats, len[0]));
-                pulledData.add(e);
+                unpackStreamedData(tagId, elapsedNanos, wallClockNanos, pulledData, statsFiles);
                 new File(mBaseDir.getAbsolutePath() + "/" + section + "_"
                         + lastHighWaterMark).delete();
                 new File(
@@ -1648,6 +1643,52 @@
         }
     }
 
+    private INotificationManager mNotificationManager =
+            INotificationManager.Stub.asInterface(
+                    ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+
+    private void pullNotificationStats(int reportId, int tagId, long elapsedNanos,
+            long wallClockNanos,
+            List<StatsLogEventWrapper> pulledData) {
+        final long callingToken = Binder.clearCallingIdentity();
+        try {
+            // determine last pull tine. Copy file trick from pullProcessStats?
+            long lastNotificationStatsNs = wallClockNanos -
+                    TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS);
+
+            List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
+            long notificationStatsNs = mNotificationManager.pullStats(
+                    lastNotificationStatsNs, reportId, true, statsFiles);
+            if (statsFiles.size() != 1) {
+                return;
+            }
+            unpackStreamedData(tagId, elapsedNanos, wallClockNanos, pulledData, statsFiles);
+        } catch (IOException e) {
+            Log.e(TAG, "Getting notistats failed: ", e);
+
+        } catch (RemoteException e) {
+            Log.e(TAG, "Getting notistats failed: ", e);
+        } catch (SecurityException e) {
+            Log.e(TAG, "Getting notistats failed: ", e);
+        } finally {
+            Binder.restoreCallingIdentity(callingToken);
+        }
+
+    }
+
+    static void unpackStreamedData(int tagId, long elapsedNanos, long wallClockNanos,
+            List<StatsLogEventWrapper> pulledData, List<ParcelFileDescriptor> statsFiles)
+            throws IOException {
+        InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
+                statsFiles.get(0));
+        int[] len = new int[1];
+        byte[] stats = readFully(stream, len);
+        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
+                wallClockNanos);
+        e.writeStorage(Arrays.copyOf(stats, len[0]));
+        pulledData.add(e);
+    }
+
     static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
         int pos = 0;
         final int initialAvail = stream.available();
@@ -2477,6 +2518,11 @@
                 pullAppOps(elapsedNanos, wallClockNanos, ret);
                 break;
             }
+            case StatsLog.NOTIFICATION_REMOTE_VIEWS: {
+                pullNotificationStats(NotificationManagerService.REPORT_REMOTE_VIEWS,
+                        tagId, elapsedNanos, wallClockNanos, ret);
+                break;
+            }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index f336497..ab23b29 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -39,6 +39,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
 import org.junit.After;
@@ -67,6 +68,7 @@
     @Mock AccessibilityServiceInfo mMockServiceInfo;
     @Mock ResolveInfo mMockResolveInfo;
     @Mock AccessibilityManagerService.SecurityPolicy mMockSecurityPolicy;
+    @Mock ActivityTaskManagerInternal mMockActivityTaskManagerInternal;
     @Mock AbstractAccessibilityServiceConnection.SystemSupport mMockSystemSupport;
     @Mock WindowManagerInternal mMockWindowManagerInternal;
     @Mock GlobalActionPerformer mMockGlobalActionPerformer;
@@ -89,7 +91,8 @@
         mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext,
                 COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, mHandler, new Object(),
                 mMockSecurityPolicy, mMockSystemSupport, mMockWindowManagerInternal,
-                mMockGlobalActionPerformer);
+                mMockGlobalActionPerformer, mMockActivityTaskManagerInternal);
+        when(mMockSecurityPolicy.canPerformGestures(mConnection)).thenReturn(true);
     }
 
     @After
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 4a9cef1..367962b 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -20,6 +20,7 @@
         "androidx.test.rules", "hamcrest-library",
         "mockito-target-inline-minus-junit4",
         "platform-test-annotations",
+        "platformprotosnano",
         "hamcrest-library",
         "testables",
         "truth-prebuilt",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java
new file mode 100644
index 0000000..f685c68
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.server.notification;
+
+import static com.android.server.notification.NotificationManagerService.REPORT_REMOTE_VIEWS;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotSame;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.service.notification.nano.NotificationRemoteViewsProto;
+import android.test.MoreAsserts;
+import android.util.proto.ProtoOutputStream;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.UiServiceTestCase;
+
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
+
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+public class PulledStatsTest extends UiServiceTestCase {
+
+    @Test
+    public void testPulledStats_Empty() {
+        PulledStats stats = new PulledStats(0L);
+        assertEquals(0L, stats.endTimeMs());
+    }
+
+    @Test
+    public void testPulledStats_UnknownReport() {
+        PulledStats stats = new PulledStats(0L);
+        stats.addUndecoratedPackage("foo", 456);
+        stats.addUndecoratedPackage("bar", 123);
+
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        final ProtoOutputStream proto = new ProtoOutputStream(bytes);
+        stats.writeToProto(1023123, proto); // a very large number
+        proto.flush();
+
+        // expect empty output in response to an unrecognized request
+        assertEquals(0L, bytes.size());
+    }
+
+    @Test
+    public void testPulledStats_RemoteViewReportPackages() {
+        List<String> expectedPkgs = new ArrayList<>(2);
+        expectedPkgs.add("foo");
+        expectedPkgs.add("bar");
+
+        PulledStats stats = new PulledStats(0L);
+        for(String pkg: expectedPkgs) {
+            stats.addUndecoratedPackage(pkg, 111);
+        }
+
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        final ProtoOutputStream protoStream = new ProtoOutputStream(bytes);
+        stats.writeToProto(REPORT_REMOTE_VIEWS, protoStream);
+        protoStream.flush();
+
+        try {
+            NotificationRemoteViewsProto proto =
+                    NotificationRemoteViewsProto.parseFrom(bytes.toByteArray());
+            List<String> actualPkgs = new ArrayList<>(2);
+            for(int i = 0 ; i < proto.packageRemoteViewInfo.length; i++) {
+                actualPkgs.add(proto.packageRemoteViewInfo[i].packageName);
+            }
+            assertEquals(2, actualPkgs.size());
+            assertTrue("missing packages", actualPkgs.containsAll(expectedPkgs));
+            assertTrue("unexpected packages", expectedPkgs.containsAll(actualPkgs));
+        } catch (InvalidProtocolBufferNanoException e) {
+            e.printStackTrace();
+            fail("writeToProto generated unparsable output");
+        }
+
+    }
+    @Test
+    public void testPulledStats_RemoteViewReportEndTime() {
+        List<String> expectedPkgs = new ArrayList<>(2);
+        expectedPkgs.add("foo");
+        expectedPkgs.add("bar");
+
+        PulledStats stats = new PulledStats(0L);
+        long t = 111;
+        for(String pkg: expectedPkgs) {
+            t += 1000;
+            stats.addUndecoratedPackage(pkg, t);
+        }
+        assertEquals(t, stats.endTimeMs());
+    }
+
+}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 163be51..628dc93 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -89,8 +89,8 @@
     private int mCarrierId;
 
     /**
-     * The source of the name, NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SOURCE or
-     * NAME_SOURCE_USER_INPUT.
+     * The source of the name, NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN,
+     * NAME_SOURCE_SIM_PNN, or NAME_SOURCE_USER_INPUT.
      */
     private int mNameSource;
 
@@ -334,7 +334,7 @@
     }
 
     /**
-     * @return the source of the name, eg NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SOURCE or
+     * @return the source of the name, eg NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN or
      * NAME_SOURCE_USER_INPUT.
      * @hide
      */
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c3a7985..e2ac1f2 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -393,19 +393,19 @@
     public static final String NAME_SOURCE = "name_source";
 
     /**
-     * The name_source is the default
+     * The name_source is the default, which is from the carrier id.
      * @hide
      */
     public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
 
     /**
-     * The name_source is from the SIM
+     * The name_source is from SIM EF_SPN.
      * @hide
      */
-    public static final int NAME_SOURCE_SIM_SOURCE = 1;
+    public static final int NAME_SOURCE_SIM_SPN = 1;
 
     /**
-     * The name_source is from the user
+     * The name_source is from user input
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -418,6 +418,24 @@
     public static final int NAME_SOURCE_CARRIER = 3;
 
     /**
+     * The name_source is from SIM EF_PNN.
+     * @hide
+     */
+    public static final int NAME_SOURCE_SIM_PNN = 4;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"NAME_SOURCE_"},
+            value = {
+                    NAME_SOURCE_DEFAULT_SOURCE,
+                    NAME_SOURCE_SIM_SPN,
+                    NAME_SOURCE_USER_INPUT,
+                    NAME_SOURCE_CARRIER,
+                    NAME_SOURCE_SIM_PNN
+            })
+    public @interface SimDisplayNameSource {}
+
+    /**
      * TelephonyProvider column name for the color of a SIM.
      * <P>Type: INTEGER (int)</P>
      */
@@ -1669,13 +1687,12 @@
      * Set display name by simInfo index with name source
      * @param displayName the display name of SIM card
      * @param subId the unique SubscriptionInfo index in database
-     * @param nameSource 0: NAME_SOURCE_DEFAULT_SOURCE, 1: NAME_SOURCE_SIM_SOURCE,
-     *                   2: NAME_SOURCE_USER_INPUT
+     * @param nameSource SIM display name source
      * @return the number of records updated or < 0 if invalid subId
      * @hide
      */
     @UnsupportedAppUsage
-    public int setDisplayName(String displayName, int subId, int nameSource) {
+    public int setDisplayName(String displayName, int subId, @SimDisplayNameSource int nameSource) {
         if (VDBG) {
             logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId
                     + " nameSource:" + nameSource);