Merge "convert HomeHelperTest to presubmit"
diff --git a/Android.bp b/Android.bp
index c1f6860..a587372 100644
--- a/Android.bp
+++ b/Android.bp
@@ -333,6 +333,7 @@
         "android.hardware.radio-V1.2-java",
         "android.hardware.radio-V1.3-java",
         "android.hardware.radio-V1.4-java",
+        "android.hardware.radio-V1.5-java",
         "android.hardware.thermal-V1.0-java-constants",
         "android.hardware.thermal-V1.0-java",
         "android.hardware.thermal-V1.1-java",
@@ -444,6 +445,7 @@
         "services-platform-compat-config",
         "media-provider-platform-compat-config",
         "services-devicepolicy-platform-compat-config",
+        "services-core-platform-compat-config",
     ],
     static_libs: [
         // If MimeMap ever becomes its own APEX, then this dependency would need to be removed
@@ -1634,6 +1636,7 @@
         "core/java/com/android/internal/os/SomeArgs.java",
         "core/java/com/android/internal/util/FastXmlSerializer.java",
         "core/java/com/android/internal/util/HexDump.java",
+        "core/java/com/android/internal/util/IState.java",
         "core/java/com/android/internal/util/IndentingPrintWriter.java",
         "core/java/com/android/internal/util/Preconditions.java",
         "core/java/com/android/internal/util/State.java",
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 62c77ef..f11d4f8 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -1163,12 +1163,12 @@
                 final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
                 StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
                         wallClockNanos);
-                e.writeLong(wifiInfo.getTimeStamp());
+                e.writeLong(wifiInfo.getTimeSinceBootMillis());
                 e.writeInt(wifiInfo.getStackState());
-                e.writeLong(wifiInfo.getControllerTxTimeMillis());
-                e.writeLong(wifiInfo.getControllerRxTimeMillis());
-                e.writeLong(wifiInfo.getControllerIdleTimeMillis());
-                e.writeLong(wifiInfo.getControllerEnergyUsed());
+                e.writeLong(wifiInfo.getControllerTxDurationMillis());
+                e.writeLong(wifiInfo.getControllerRxDurationMillis());
+                e.writeLong(wifiInfo.getControllerIdleDurationMillis());
+                e.writeLong(wifiInfo.getControllerEnergyUsedMicroJoules());
                 pulledData.add(e);
             } catch (RemoteException e) {
                 Slog.e(TAG,
@@ -2183,6 +2183,20 @@
                         e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_ALL_TRUSTED));
                         e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_ALL_TRUSTED));
                         e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_ALL_TRUSTED));
+
+                        String perm = AppOpsManager.opToPermission(op.getOpCode());
+                        if (perm == null) {
+                            e.writeBoolean(false);
+                        } else {
+                            PermissionInfo permInfo;
+                            try {
+                                permInfo = mContext.getPackageManager().getPermissionInfo(perm, 0);
+                                e.writeBoolean(permInfo.getProtection() == PROTECTION_DANGEROUS);
+                            } catch (PackageManager.NameNotFoundException exception) {
+                                e.writeBoolean(false);
+                            }
+                        }
+
                         pulledData.add(e);
                     }
                 }
diff --git a/api/current.txt b/api/current.txt
index b1eac59..09006a5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -44290,6 +44290,7 @@
     field public static final int EUTRAN = 3; // 0x3
     field public static final int GERAN = 1; // 0x1
     field public static final int IWLAN = 5; // 0x5
+    field public static final int NGRAN = 6; // 0x6
     field public static final int UNKNOWN = 0; // 0x0
     field public static final int UTRAN = 2; // 0x2
   }
@@ -44362,6 +44363,45 @@
     field public static final int BAND_T810 = 7; // 0x7
   }
 
+  public static final class AccessNetworkConstants.NgranBands {
+    field public static final int BAND_1 = 1; // 0x1
+    field public static final int BAND_12 = 12; // 0xc
+    field public static final int BAND_2 = 2; // 0x2
+    field public static final int BAND_20 = 20; // 0x14
+    field public static final int BAND_25 = 25; // 0x19
+    field public static final int BAND_257 = 257; // 0x101
+    field public static final int BAND_258 = 258; // 0x102
+    field public static final int BAND_260 = 260; // 0x104
+    field public static final int BAND_261 = 261; // 0x105
+    field public static final int BAND_28 = 28; // 0x1c
+    field public static final int BAND_3 = 3; // 0x3
+    field public static final int BAND_34 = 34; // 0x22
+    field public static final int BAND_38 = 38; // 0x26
+    field public static final int BAND_39 = 39; // 0x27
+    field public static final int BAND_40 = 40; // 0x28
+    field public static final int BAND_41 = 41; // 0x29
+    field public static final int BAND_5 = 5; // 0x5
+    field public static final int BAND_50 = 50; // 0x32
+    field public static final int BAND_51 = 51; // 0x33
+    field public static final int BAND_66 = 66; // 0x42
+    field public static final int BAND_7 = 7; // 0x7
+    field public static final int BAND_70 = 70; // 0x46
+    field public static final int BAND_71 = 71; // 0x47
+    field public static final int BAND_74 = 74; // 0x4a
+    field public static final int BAND_75 = 75; // 0x4b
+    field public static final int BAND_76 = 76; // 0x4c
+    field public static final int BAND_77 = 77; // 0x4d
+    field public static final int BAND_78 = 78; // 0x4e
+    field public static final int BAND_79 = 79; // 0x4f
+    field public static final int BAND_8 = 8; // 0x8
+    field public static final int BAND_80 = 80; // 0x50
+    field public static final int BAND_81 = 81; // 0x51
+    field public static final int BAND_82 = 82; // 0x52
+    field public static final int BAND_83 = 83; // 0x53
+    field public static final int BAND_84 = 84; // 0x54
+    field public static final int BAND_86 = 86; // 0x56
+  }
+
   public static final class AccessNetworkConstants.UtranBand {
     field public static final int BAND_1 = 1; // 0x1
     field public static final int BAND_10 = 10; // 0xa
@@ -44747,6 +44787,7 @@
     method public abstract int getAsuLevel();
     method public abstract int getDbm();
     method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public abstract int getLevel();
+    method public static final int getNumSignalStrengthLevels();
     method public abstract int hashCode();
     field public static final int SIGNAL_STRENGTH_GOOD = 3; // 0x3
     field public static final int SIGNAL_STRENGTH_GREAT = 4; // 0x4
@@ -55161,12 +55202,12 @@
   }
 
   public class WebView extends android.widget.AbsoluteLayout implements android.view.ViewGroup.OnHierarchyChangeListener android.view.ViewTreeObserver.OnGlobalFocusChangeListener {
-    ctor public WebView(android.content.Context);
-    ctor public WebView(android.content.Context, android.util.AttributeSet);
-    ctor public WebView(android.content.Context, android.util.AttributeSet, int);
-    ctor public WebView(android.content.Context, android.util.AttributeSet, int, int);
-    ctor @Deprecated public WebView(android.content.Context, android.util.AttributeSet, int, boolean);
-    method public void addJavascriptInterface(Object, String);
+    ctor public WebView(@NonNull android.content.Context);
+    ctor public WebView(@NonNull android.content.Context, @Nullable android.util.AttributeSet);
+    ctor public WebView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int);
+    ctor public WebView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int, int);
+    ctor @Deprecated public WebView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int, boolean);
+    method public void addJavascriptInterface(@NonNull Object, @NonNull String);
     method public boolean canGoBack();
     method public boolean canGoBackOrForward(int);
     method public boolean canGoForward();
@@ -55180,40 +55221,40 @@
     method public void clearMatches();
     method public void clearSslPreferences();
     method @Deprecated public void clearView();
-    method public android.webkit.WebBackForwardList copyBackForwardList();
+    method @NonNull public android.webkit.WebBackForwardList copyBackForwardList();
     method @Deprecated public android.print.PrintDocumentAdapter createPrintDocumentAdapter();
-    method public android.print.PrintDocumentAdapter createPrintDocumentAdapter(String);
-    method public android.webkit.WebMessagePort[] createWebMessageChannel();
+    method @NonNull public android.print.PrintDocumentAdapter createPrintDocumentAdapter(@NonNull String);
+    method @NonNull public android.webkit.WebMessagePort[] createWebMessageChannel();
     method public void destroy();
     method public static void disableWebView();
-    method public void documentHasImages(android.os.Message);
+    method public void documentHasImages(@NonNull android.os.Message);
     method public static void enableSlowWholeDocumentDraw();
-    method public void evaluateJavascript(String, @Nullable android.webkit.ValueCallback<java.lang.String>);
+    method public void evaluateJavascript(@NonNull String, @Nullable android.webkit.ValueCallback<java.lang.String>);
     method @Deprecated @Nullable public static String findAddress(String);
     method @Deprecated public int findAll(String);
-    method public void findAllAsync(String);
+    method public void findAllAsync(@NonNull String);
     method public void findNext(boolean);
     method public void flingScroll(int, int);
     method @Deprecated public void freeMemory();
     method @Nullable public android.net.http.SslCertificate getCertificate();
     method @android.view.ViewDebug.ExportedProperty(category="webview") public int getContentHeight();
     method @Nullable public static android.content.pm.PackageInfo getCurrentWebViewPackage();
-    method public android.graphics.Bitmap getFavicon();
-    method public android.webkit.WebView.HitTestResult getHitTestResult();
+    method @Nullable public android.graphics.Bitmap getFavicon();
+    method @NonNull public android.webkit.WebView.HitTestResult getHitTestResult();
     method @Deprecated @Nullable public String[] getHttpAuthUsernamePassword(String, String);
-    method @android.view.ViewDebug.ExportedProperty(category="webview") public String getOriginalUrl();
+    method @android.view.ViewDebug.ExportedProperty(category="webview") @Nullable public String getOriginalUrl();
     method public int getProgress();
     method public boolean getRendererPriorityWaivedWhenNotVisible();
     method public int getRendererRequestedPriority();
     method @NonNull public static android.net.Uri getSafeBrowsingPrivacyPolicyUrl();
     method @Deprecated @android.view.ViewDebug.ExportedProperty(category="webview") public float getScale();
-    method public android.webkit.WebSettings getSettings();
+    method @NonNull public android.webkit.WebSettings getSettings();
     method @NonNull public android.view.textclassifier.TextClassifier getTextClassifier();
-    method @android.view.ViewDebug.ExportedProperty(category="webview") public String getTitle();
-    method @android.view.ViewDebug.ExportedProperty(category="webview") public String getUrl();
+    method @android.view.ViewDebug.ExportedProperty(category="webview") @Nullable public String getTitle();
+    method @android.view.ViewDebug.ExportedProperty(category="webview") @Nullable public String getUrl();
     method @Nullable public android.webkit.WebChromeClient getWebChromeClient();
     method @NonNull public static ClassLoader getWebViewClassLoader();
-    method public android.webkit.WebViewClient getWebViewClient();
+    method @NonNull public android.webkit.WebViewClient getWebViewClient();
     method @NonNull public android.os.Looper getWebViewLooper();
     method @Nullable public android.webkit.WebViewRenderProcess getWebViewRenderProcess();
     method @Nullable public android.webkit.WebViewRenderProcessClient getWebViewRenderProcessClient();
@@ -55222,10 +55263,10 @@
     method public void goForward();
     method public void invokeZoomPicker();
     method public boolean isPrivateBrowsingEnabled();
-    method public void loadData(String, @Nullable String, @Nullable String);
-    method public void loadDataWithBaseURL(@Nullable String, String, @Nullable String, @Nullable String, @Nullable String);
-    method public void loadUrl(String, java.util.Map<java.lang.String,java.lang.String>);
-    method public void loadUrl(String);
+    method public void loadData(@NonNull String, @Nullable String, @Nullable String);
+    method public void loadDataWithBaseURL(@Nullable String, @NonNull String, @Nullable String, @Nullable String, @Nullable String);
+    method public void loadUrl(@NonNull String, @NonNull java.util.Map<java.lang.String,java.lang.String>);
+    method public void loadUrl(@NonNull String);
     method @Deprecated public void onChildViewAdded(android.view.View, android.view.View);
     method @Deprecated public void onChildViewRemoved(android.view.View, android.view.View);
     method @Deprecated public void onGlobalFocusChanged(android.view.View, android.view.View);
@@ -55236,23 +55277,23 @@
     method public boolean pageDown(boolean);
     method public boolean pageUp(boolean);
     method public void pauseTimers();
-    method public void postUrl(String, byte[]);
-    method public void postVisualStateCallback(long, android.webkit.WebView.VisualStateCallback);
-    method public void postWebMessage(android.webkit.WebMessage, android.net.Uri);
+    method public void postUrl(@NonNull String, @NonNull byte[]);
+    method public void postVisualStateCallback(long, @NonNull android.webkit.WebView.VisualStateCallback);
+    method public void postWebMessage(@NonNull android.webkit.WebMessage, @NonNull android.net.Uri);
     method public void reload();
     method public void removeJavascriptInterface(@NonNull String);
     method public void requestFocusNodeHref(@Nullable android.os.Message);
-    method public void requestImageRef(android.os.Message);
-    method @Nullable public android.webkit.WebBackForwardList restoreState(android.os.Bundle);
+    method public void requestImageRef(@NonNull android.os.Message);
+    method @Nullable public android.webkit.WebBackForwardList restoreState(@NonNull android.os.Bundle);
     method public void resumeTimers();
     method @Deprecated public void savePassword(String, String, String);
-    method @Nullable public android.webkit.WebBackForwardList saveState(android.os.Bundle);
-    method public void saveWebArchive(String);
-    method public void saveWebArchive(String, boolean, @Nullable android.webkit.ValueCallback<java.lang.String>);
+    method @Nullable public android.webkit.WebBackForwardList saveState(@NonNull android.os.Bundle);
+    method public void saveWebArchive(@NonNull String);
+    method public void saveWebArchive(@NonNull String, boolean, @Nullable android.webkit.ValueCallback<java.lang.String>);
     method @Deprecated public void setCertificate(android.net.http.SslCertificate);
-    method public static void setDataDirectorySuffix(String);
-    method public void setDownloadListener(android.webkit.DownloadListener);
-    method public void setFindListener(android.webkit.WebView.FindListener);
+    method public static void setDataDirectorySuffix(@NonNull String);
+    method public void setDownloadListener(@Nullable android.webkit.DownloadListener);
+    method public void setFindListener(@Nullable android.webkit.WebView.FindListener);
     method @Deprecated public void setHorizontalScrollbarOverlay(boolean);
     method @Deprecated public void setHttpAuthUsernamePassword(String, String, String, String);
     method public void setInitialScale(int);
@@ -55263,9 +55304,9 @@
     method public static void setSafeBrowsingWhitelist(@NonNull java.util.List<java.lang.String>, @Nullable android.webkit.ValueCallback<java.lang.Boolean>);
     method public void setTextClassifier(@Nullable android.view.textclassifier.TextClassifier);
     method @Deprecated public void setVerticalScrollbarOverlay(boolean);
-    method public void setWebChromeClient(android.webkit.WebChromeClient);
+    method public void setWebChromeClient(@Nullable android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
-    method public void setWebViewClient(android.webkit.WebViewClient);
+    method public void setWebViewClient(@NonNull android.webkit.WebViewClient);
     method public void setWebViewRenderProcessClient(@NonNull java.util.concurrent.Executor, @NonNull android.webkit.WebViewRenderProcessClient);
     method public void setWebViewRenderProcessClient(@Nullable android.webkit.WebViewRenderProcessClient);
     method @Deprecated public boolean shouldDelayChildPressedState();
@@ -55313,8 +55354,8 @@
 
   public class WebView.WebViewTransport {
     ctor public WebView.WebViewTransport();
-    method public android.webkit.WebView getWebView();
-    method public void setWebView(android.webkit.WebView);
+    method @Nullable public android.webkit.WebView getWebView();
+    method public void setWebView(@Nullable android.webkit.WebView);
   }
 
   public class WebViewClient {
diff --git a/api/system-current.txt b/api/system-current.txt
index 5ff6778..189585e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5276,18 +5276,30 @@
 
   public final class SoftApConfiguration implements android.os.Parcelable {
     method public int describeContents();
+    method public int getBand();
     method @Nullable public android.net.MacAddress getBssid();
+    method public int getChannel();
+    method public int getSecurityType();
     method @Nullable public String getSsid();
     method @Nullable public String getWpa2Passphrase();
+    method public boolean isHiddenSsid();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int BAND_2GHZ = 0; // 0x0
+    field public static final int BAND_5GHZ = 1; // 0x1
+    field public static final int BAND_ANY = -1; // 0xffffffff
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApConfiguration> CREATOR;
+    field public static final int SECURITY_TYPE_OPEN = 0; // 0x0
+    field public static final int SECURITY_TYPE_WPA2_PSK = 1; // 0x1
   }
 
   public static final class SoftApConfiguration.Builder {
     ctor public SoftApConfiguration.Builder();
     ctor public SoftApConfiguration.Builder(@NonNull android.net.wifi.SoftApConfiguration);
     method @NonNull public android.net.wifi.SoftApConfiguration build();
+    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBand(int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBssid(@Nullable android.net.MacAddress);
+    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannel(int);
+    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setHiddenSsid(boolean);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setSsid(@Nullable String);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setWpa2Passphrase(@Nullable String);
   }
@@ -5307,6 +5319,32 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR;
   }
 
+  public final class WifiActivityEnergyInfo implements android.os.Parcelable {
+    ctor public WifiActivityEnergyInfo(long, int, long, long, long, long, long);
+    method public int describeContents();
+    method public long getControllerEnergyUsedMicroJoules();
+    method public long getControllerIdleDurationMillis();
+    method public long getControllerRxDurationMillis();
+    method public long getControllerScanDurationMillis();
+    method public long getControllerTxDurationMillis();
+    method public int getStackState();
+    method public long getTimeSinceBootMillis();
+    method public boolean isValid();
+    method public void setControllerEnergyUsedMicroJoules(long);
+    method public void setControllerIdleDurationMillis(long);
+    method public void setControllerRxDurationMillis(long);
+    method public void setControllerScanDurationMillis(long);
+    method public void setControllerTxDurationMillis(long);
+    method public void setStackState(int);
+    method public void setTimeSinceBootMillis(long);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiActivityEnergyInfo> CREATOR;
+    field public static final int STACK_STATE_INVALID = 0; // 0x0
+    field public static final int STACK_STATE_STATE_ACTIVE = 1; // 0x1
+    field public static final int STACK_STATE_STATE_IDLE = 3; // 0x3
+    field public static final int STACK_STATE_STATE_SCANNING = 2; // 0x2
+  }
+
   public final class WifiClient implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public android.net.MacAddress getMacAddress();
@@ -5441,8 +5479,9 @@
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(@Nullable java.util.List<android.net.wifi.ScanResult>);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(@NonNull java.util.Set<android.net.wifi.hotspot2.OsuProvider>);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.READ_WIFI_CREDENTIAL}) public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.SoftApConfiguration getSoftApConfiguration();
     method public int getVerboseLoggingLevel();
-    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
+    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState();
     method public boolean isApMacRandomizationSupported();
     method public boolean isConnectedMacRandomizationSupported();
@@ -5460,17 +5499,20 @@
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerTrafficStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.TrafficStateCallback);
     method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreBackupData(@NonNull byte[]);
+    method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreSoftApBackupData(@NonNull byte[]);
     method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreSupplicantBackupData(@NonNull byte[], @NonNull byte[]);
     method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public byte[] retrieveBackupData();
+    method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public byte[] retrieveSoftApBackupData();
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(int);
-    method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
+    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean setSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startLocalOnlyHotspot(@NonNull android.net.wifi.SoftApConfiguration, @Nullable java.util.concurrent.Executor, @Nullable android.net.wifi.WifiManager.LocalOnlyHotspotCallback);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource);
-    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startSoftAp(@Nullable android.net.wifi.WifiConfiguration);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startTetheredHotspot(@Nullable android.net.wifi.SoftApConfiguration);
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession();
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean stopSoftAp();
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterNetworkRequestMatchCallback(@NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2f22b49..b9051da 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -6717,6 +6717,9 @@
     // For long-running operations, total duration of the operation
     // while the app was in the background (only for trusted requests)
     optional int64 trusted_background_duration_millis = 9;
+
+    // Whether AppOps is guarded by Runtime permission
+    optional bool is_runtime_permission = 10;
 }
 
 /**
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 95815e4..9fed269 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -27,7 +27,7 @@
 import android.server.ServerProtoEnums;
 import android.service.batterystats.BatteryStatsServiceDumpHistoryProto;
 import android.service.batterystats.BatteryStatsServiceDumpProto;
-import android.telephony.SignalStrength;
+import android.telephony.CellSignalStrength;
 import android.telephony.TelephonyManager;
 import android.text.format.DateFormat;
 import android.util.ArrayMap;
@@ -2529,7 +2529,7 @@
                 new String[] {"in", "out", "em", "off"}),
         new BitDescription(HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK,
                 HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT, "phone_signal_strength", "Pss",
-                SignalStrength.SIGNAL_STRENGTH_NAMES,
+                new String[] { "none", "poor", "moderate", "good", "great" },
                 new String[] { "0", "1", "2", "3", "4" }),
         new BitDescription(HistoryItem.STATE_BRIGHTNESS_MASK,
                 HistoryItem.STATE_BRIGHTNESS_SHIFT, "brightness", "Sb",
@@ -3891,14 +3891,14 @@
         dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
 
         // Dump signal strength stats
-        args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+        args = new Object[CellSignalStrength.getNumSignalStrengthLevels()];
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
             args[i] = getPhoneSignalStrengthTime(i, rawRealtime, which) / 1000;
         }
         dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
         dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
                 getPhoneSignalScanningTime(rawRealtime, which) / 1000);
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
             args[i] = getPhoneSignalStrengthCount(i, which);
         }
         dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
@@ -4968,7 +4968,7 @@
             "good (-108dBm to -98dBm): ",
             "great (greater than -98dBm): "};
         didOne = false;
-        final int numCellularRxBins = Math.min(SignalStrength.NUM_SIGNAL_STRENGTH_BINS,
+        final int numCellularRxBins = Math.min(CellSignalStrength.getNumSignalStrengthLevels(),
             cellularRxSignalStrengthDescription.length);
         for (int i=0; i<numCellularRxBins; i++) {
             final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
@@ -8216,7 +8216,7 @@
                 which);
 
         // Phone signal strength (SIGNAL_STRENGTH_TIME_DATA and SIGNAL_STRENGTH_COUNT_DATA)
-        for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; ++i) {
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); ++i) {
             final long pssToken = proto.start(SystemProto.PHONE_SIGNAL_STRENGTH);
             proto.write(SystemProto.PhoneSignalStrength.NAME, i);
             dumpTimer(proto, SystemProto.PhoneSignalStrength.TOTAL, getPhoneSignalStrengthTimer(i),
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.java b/core/java/android/os/connectivity/CellularBatteryStats.java
index caa4068..b8c1802 100644
--- a/core/java/android/os/connectivity/CellularBatteryStats.java
+++ b/core/java/android/os/connectivity/CellularBatteryStats.java
@@ -22,8 +22,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Annotation.NetworkType;
+import android.telephony.CellSignalStrength;
 import android.telephony.ModemActivityInfo;
-import android.telephony.SignalStrength;
 
 import java.util.Arrays;
 import java.util.Objects;
@@ -48,7 +48,7 @@
     private long mEnergyConsumedMaMs = 0;
     private long[] mTimeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
     private long[] mTimeInRxSignalStrengthLevelMs =
-            new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+            new long[CellSignalStrength.getNumSignalStrengthLevels()];
     private long[] mTxTimeMs = new long[ModemActivityInfo.TX_POWER_LEVELS];
     private long mMonitoredRailChargeConsumedMaMs = 0;
 
@@ -354,7 +354,7 @@
     /** @hide **/
     public void setTimeInRxSignalStrengthLevelMicros(@NonNull long[] t) {
         mTimeInRxSignalStrengthLevelMs = Arrays.copyOfRange(t, 0,
-            Math.min(t.length, SignalStrength.NUM_SIGNAL_STRENGTH_BINS));
+            Math.min(t.length, CellSignalStrength.getNumSignalStrengthLevels()));
         return;
     }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f627daa..f19ef65 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4952,7 +4952,6 @@
             MOVED_TO_GLOBAL.add(Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED);
             MOVED_TO_GLOBAL.add(Settings.Global.WIFI_P2P_PENDING_FACTORY_RESET);
             MOVED_TO_GLOBAL.add(Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON);
-            MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_ENABLE);
             MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_TIMEOUT);
             MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE);
             MOVED_TO_GLOBAL.add(Settings.Global.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS);
@@ -9283,16 +9282,6 @@
        @SystemApi
        public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
 
-       /**
-        * Whether the package manager should send package verification broadcasts for verifiers to
-        * review apps prior to installation.
-        * 1 = request apps to be verified prior to installation, if a verifier exists.
-        * 0 = do not verify apps before installation
-        * @hide
-        */
-       @UnsupportedAppUsage
-       public static final String PACKAGE_VERIFIER_ENABLE = "package_verifier_enable";
-
        /** Timeout for package verification.
         * @hide */
        public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index add0316..9e454e6 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4155,20 +4155,6 @@
         public static final String CID = "cid";
 
         /**
-         * Message code. <em>OBSOLETE: merged into SERIAL_NUMBER.</em>
-         * <P>Type: INTEGER</P>
-         * @hide
-         */
-        public static final String V1_MESSAGE_CODE = "message_code";
-
-        /**
-         * Message identifier. <em>OBSOLETE: renamed to SERVICE_CATEGORY.</em>
-         * <P>Type: INTEGER</P>
-         * @hide
-         */
-        public static final String V1_MESSAGE_IDENTIFIER = "message_id";
-
-        /**
          * Service category which represents the general topic of the message.
          * <p>
          * For GSM/UMTS: message identifier (see 3GPP TS 23.041 section 9.4.1.2.2)
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2af7ac7..4b47927 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -125,7 +125,7 @@
          *
          * @param webview the WebView to transport
          */
-        public synchronized void setWebView(WebView webview) {
+        public synchronized void setWebView(@Nullable WebView webview) {
             mWebview = webview;
         }
 
@@ -134,6 +134,7 @@
          *
          * @return the transported WebView object
          */
+        @Nullable
         public synchronized WebView getWebView() {
             return mWebview;
         }
@@ -309,7 +310,7 @@
      *
      * @param context an Activity Context to access application assets
      */
-    public WebView(Context context) {
+    public WebView(@NonNull Context context) {
         this(context, null);
     }
 
@@ -319,7 +320,7 @@
      * @param context an Activity Context to access application assets
      * @param attrs an AttributeSet passed to our parent
      */
-    public WebView(Context context, AttributeSet attrs) {
+    public WebView(@NonNull Context context, @Nullable AttributeSet attrs) {
         this(context, attrs, com.android.internal.R.attr.webViewStyle);
     }
 
@@ -332,7 +333,7 @@
      *        reference to a style resource that supplies default values for
      *        the view. Can be 0 to not look for defaults.
      */
-    public WebView(Context context, AttributeSet attrs, int defStyleAttr) {
+    public WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         this(context, attrs, defStyleAttr, 0);
     }
 
@@ -349,7 +350,8 @@
      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
      *        to not look for defaults.
      */
-    public WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+    public WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
         this(context, attrs, defStyleAttr, defStyleRes, null, false);
     }
 
@@ -370,7 +372,7 @@
      * and {@link WebStorage} for fine-grained control of privacy data.
      */
     @Deprecated
-    public WebView(Context context, AttributeSet attrs, int defStyleAttr,
+    public WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
             boolean privateBrowsing) {
         this(context, attrs, defStyleAttr, 0, null, privateBrowsing);
     }
@@ -395,8 +397,8 @@
      *       be added synchronously, before a subsequent loadUrl call takes effect.
      */
     @UnsupportedAppUsage
-    protected WebView(Context context, AttributeSet attrs, int defStyleAttr,
-            Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
+    protected WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            @Nullable Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
         this(context, attrs, defStyleAttr, 0, javaScriptInterfaces, privateBrowsing);
     }
 
@@ -405,8 +407,9 @@
      */
     @SuppressWarnings("deprecation")  // for super() call into deprecated base class constructor.
     @UnsupportedAppUsage
-    protected WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes,
-            Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
+    protected WebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes, @Nullable Map<String, Object> javaScriptInterfaces,
+            boolean privateBrowsing) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
         // WebView is important by default, unless app developer overrode attribute.
@@ -642,7 +645,7 @@
      *         method fails.
      */
     @Nullable
-    public WebBackForwardList saveState(Bundle outState) {
+    public WebBackForwardList saveState(@NonNull Bundle outState) {
         checkThread();
         return mProvider.saveState(outState);
     }
@@ -695,7 +698,7 @@
      * @return the restored back/forward list or {@code null} if restoreState failed
      */
     @Nullable
-    public WebBackForwardList restoreState(Bundle inState) {
+    public WebBackForwardList restoreState(@NonNull Bundle inState) {
         checkThread();
         return mProvider.restoreState(inState);
     }
@@ -713,7 +716,7 @@
      *            controlling caching, accept types or the User-Agent, their
      *            values may be overridden by this WebView's defaults.
      */
-    public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {
+    public void loadUrl(@NonNull String url, @NonNull Map<String, String> additionalHttpHeaders) {
         checkThread();
         mProvider.loadUrl(url, additionalHttpHeaders);
     }
@@ -725,7 +728,7 @@
      *
      * @param url the URL of the resource to load
      */
-    public void loadUrl(String url) {
+    public void loadUrl(@NonNull String url) {
         checkThread();
         mProvider.loadUrl(url);
     }
@@ -739,7 +742,7 @@
      * @param postData the data will be passed to "POST" request, which must be
      *     be "application/x-www-form-urlencoded" encoded.
      */
-    public void postUrl(String url, byte[] postData) {
+    public void postUrl(@NonNull String url, @NonNull byte[] postData) {
         checkThread();
         if (URLUtil.isNetworkUrl(url)) {
             mProvider.postUrl(url, postData);
@@ -803,7 +806,8 @@
      * @param mimeType the MIME type of the data, e.g. 'text/html'.
      * @param encoding the encoding of the data
      */
-    public void loadData(String data, @Nullable String mimeType, @Nullable String encoding) {
+    public void loadData(@NonNull String data, @Nullable String mimeType,
+            @Nullable String encoding) {
         checkThread();
         mProvider.loadData(data, mimeType, encoding);
     }
@@ -850,7 +854,7 @@
      * @param historyUrl the URL to use as the history entry. If {@code null} defaults
      *                   to 'about:blank'. If non-null, this must be a valid URL.
      */
-    public void loadDataWithBaseURL(@Nullable String baseUrl, String data,
+    public void loadDataWithBaseURL(@Nullable String baseUrl, @NonNull String data,
             @Nullable String mimeType, @Nullable String encoding, @Nullable String historyUrl) {
         checkThread();
         mProvider.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
@@ -873,7 +877,8 @@
      *                       completes with the result of the execution (if any).
      *                       May be {@code null} if no notification of the result is required.
      */
-    public void evaluateJavascript(String script, @Nullable ValueCallback<String> resultCallback) {
+    public void evaluateJavascript(@NonNull String script, @Nullable ValueCallback<String>
+            resultCallback) {
         checkThread();
         mProvider.evaluateJavaScript(script, resultCallback);
     }
@@ -883,7 +888,7 @@
      *
      * @param filename the filename where the archive should be placed
      */
-    public void saveWebArchive(String filename) {
+    public void saveWebArchive(@NonNull String filename) {
         checkThread();
         mProvider.saveWebArchive(filename);
     }
@@ -900,8 +905,8 @@
      *                 under which the file was saved, or {@code null} if saving the
      *                 file failed.
      */
-    public void saveWebArchive(String basename, boolean autoname, @Nullable ValueCallback<String>
-            callback) {
+    public void saveWebArchive(@NonNull String basename, boolean autoname,
+            @Nullable ValueCallback<String> callback) {
         checkThread();
         mProvider.saveWebArchive(basename, autoname, callback);
     }
@@ -1064,7 +1069,7 @@
      *                  requests with callbacks.
      * @param callback  The callback to be invoked.
      */
-    public void postVisualStateCallback(long requestId, VisualStateCallback callback) {
+    public void postVisualStateCallback(long requestId, @NonNull VisualStateCallback callback) {
         checkThread();
         mProvider.insertVisualStateCallback(requestId, callback);
     }
@@ -1131,7 +1136,8 @@
      * @param documentName  The user-facing name of the printed document. See
      *                      {@link android.print.PrintDocumentInfo}
      */
-    public PrintDocumentAdapter createPrintDocumentAdapter(String documentName) {
+    @NonNull
+    public PrintDocumentAdapter createPrintDocumentAdapter(@NonNull String documentName) {
         checkThread();
         return mProvider.createPrintDocumentAdapter(documentName);
     }
@@ -1203,6 +1209,7 @@
      * and the email is set in the "extra" field of HitTestResult. Otherwise,
      * HitTestResult type is set to UNKNOWN_TYPE.
      */
+    @NonNull
     public HitTestResult getHitTestResult() {
         checkThread();
         return mProvider.getHitTestResult();
@@ -1233,7 +1240,7 @@
      * @param msg the message to be dispatched with the result of the request
      *            as the data member with "url" as key. The result can be {@code null}.
      */
-    public void requestImageRef(Message msg) {
+    public void requestImageRef(@NonNull Message msg) {
         checkThread();
         mProvider.requestImageRef(msg);
     }
@@ -1243,10 +1250,11 @@
      * passed to WebViewClient.onPageStarted because although the load for
      * that URL has begun, the current page may not have changed.
      *
-     * @return the URL for the current page
+     * @return the URL for the current page or {@code null} if no page has been loaded
      */
     @InspectableProperty(hasAttributeId = false)
     @ViewDebug.ExportedProperty(category = "webview")
+    @Nullable
     public String getUrl() {
         checkThread();
         return mProvider.getUrl();
@@ -1259,10 +1267,12 @@
      * Also, there may have been redirects resulting in a different URL to that
      * originally requested.
      *
-     * @return the URL that was originally requested for the current page
+     * @return the URL that was originally requested for the current page or
+     * {@code null} if no page has been loaded
      */
     @InspectableProperty(hasAttributeId = false)
     @ViewDebug.ExportedProperty(category = "webview")
+    @Nullable
     public String getOriginalUrl() {
         checkThread();
         return mProvider.getOriginalUrl();
@@ -1272,10 +1282,11 @@
      * Gets the title for the current page. This is the title of the current page
      * until WebViewClient.onReceivedTitle is called.
      *
-     * @return the title for the current page
+     * @return the title for the current page or {@code null} if no page has been loaded
      */
     @InspectableProperty(hasAttributeId = false)
     @ViewDebug.ExportedProperty(category = "webview")
+    @Nullable
     public String getTitle() {
         checkThread();
         return mProvider.getTitle();
@@ -1285,9 +1296,11 @@
      * Gets the favicon for the current page. This is the favicon of the current
      * page until WebViewClient.onReceivedIcon is called.
      *
-     * @return the favicon for the current page
+     * @return the favicon for the current page or {@code null} if the page doesn't
+     * have one or if no page has been loaded
      */
     @InspectableProperty(hasAttributeId = false)
+    @Nullable
     public Bitmap getFavicon() {
         checkThread();
         return mProvider.getFavicon();
@@ -1523,6 +1536,7 @@
      * different objects. The object returned from this method will not be
      * updated to reflect any new state.
      */
+    @NonNull
     public WebBackForwardList copyBackForwardList() {
         checkThread();
         return mProvider.copyBackForwardList();
@@ -1535,7 +1549,7 @@
      *
      * @param listener an implementation of {@link FindListener}
      */
-    public void setFindListener(FindListener listener) {
+    public void setFindListener(@Nullable FindListener listener) {
         checkThread();
         setupFindListenerIfNeeded();
         mFindListener.mUserFindListener = listener;
@@ -1580,7 +1594,7 @@
      * @param find the string to find.
      * @see #setFindListener
      */
-    public void findAllAsync(String find) {
+    public void findAllAsync(@NonNull String find) {
         checkThread();
         mProvider.findAllAsync(find);
     }
@@ -1682,7 +1696,7 @@
      *
      * @param response the message that will be dispatched with the result
      */
-    public void documentHasImages(Message response) {
+    public void documentHasImages(@NonNull Message response) {
         checkThread();
         mProvider.documentHasImages(response);
     }
@@ -1694,7 +1708,7 @@
      * @param client an implementation of WebViewClient
      * @see #getWebViewClient
      */
-    public void setWebViewClient(WebViewClient client) {
+    public void setWebViewClient(@NonNull WebViewClient client) {
         checkThread();
         mProvider.setWebViewClient(client);
     }
@@ -1705,6 +1719,7 @@
      * @return the WebViewClient, or a default client if not yet set
      * @see #setWebViewClient
      */
+    @NonNull
     public WebViewClient getWebViewClient() {
         checkThread();
         return mProvider.getWebViewClient();
@@ -1798,7 +1813,7 @@
      *
      * @param listener an implementation of DownloadListener
      */
-    public void setDownloadListener(DownloadListener listener) {
+    public void setDownloadListener(@Nullable DownloadListener listener) {
         checkThread();
         mProvider.setDownloadListener(listener);
     }
@@ -1811,7 +1826,7 @@
      * @param client an implementation of WebChromeClient
      * @see #getWebChromeClient
      */
-    public void setWebChromeClient(WebChromeClient client) {
+    public void setWebChromeClient(@Nullable WebChromeClient client) {
         checkThread();
         mProvider.setWebChromeClient(client);
     }
@@ -1898,7 +1913,7 @@
      *               context. {@code null} values are ignored.
      * @param name the name used to expose the object in JavaScript
      */
-    public void addJavascriptInterface(Object object, String name) {
+    public void addJavascriptInterface(@NonNull Object object, @NonNull String name) {
         checkThread();
         mProvider.addJavascriptInterface(object, name);
     }
@@ -1926,6 +1941,7 @@
      *
      * @return the two message ports that form the message channel.
      */
+    @NonNull
     public WebMessagePort[] createWebMessageChannel() {
         checkThread();
         return mProvider.createWebMessageChannel();
@@ -1950,7 +1966,7 @@
      * @param message the WebMessage
      * @param targetOrigin the target origin.
      */
-    public void postWebMessage(WebMessage message, Uri targetOrigin) {
+    public void postWebMessage(@NonNull WebMessage message, @NonNull Uri targetOrigin) {
         checkThread();
         mProvider.postMessageToMainFrame(message, targetOrigin);
     }
@@ -1962,6 +1978,7 @@
      * @return a WebSettings object that can be used to control this WebView's
      *         settings
      */
+    @NonNull
     public WebSettings getSettings() {
         checkThread();
         return mProvider.getSettings();
@@ -2026,7 +2043,7 @@
      *                               in the current process.
      * @throws IllegalArgumentException if the suffix contains a path separator.
      */
-    public static void setDataDirectorySuffix(String suffix) {
+    public static void setDataDirectorySuffix(@NonNull String suffix) {
         WebViewFactory.setDataDirectorySuffix(suffix);
     }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f1e299d..25fa65e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -58,6 +58,7 @@
 import android.os.connectivity.GpsBatteryStats;
 import android.os.connectivity.WifiBatteryStats;
 import android.provider.Settings;
+import android.telephony.CellSignalStrength;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
 import android.telephony.ModemActivityInfo.TransmitPower;
@@ -832,7 +833,7 @@
     int mPhoneSignalStrengthBin = -1;
     int mPhoneSignalStrengthBinRaw = -1;
     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
-            new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+            new StopwatchTimer[CellSignalStrength.getNumSignalStrengthLevels()];
 
     StopwatchTimer mPhoneSignalScanningTimer;
 
@@ -5131,7 +5132,7 @@
 
     void stopAllPhoneSignalStrengthTimersLocked(int except) {
         final long elapsedRealtime = mClocks.elapsedRealtime();
-        for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
             if (i == except) {
                 continue;
             }
@@ -5146,7 +5147,7 @@
             // In this case we will always be STATE_OUT_OF_SERVICE, so need
             // to infer that we are scanning from other data.
             if (state == ServiceState.STATE_OUT_OF_SERVICE
-                    && signalBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+                    && signalBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
                 state = ServiceState.STATE_IN_SERVICE;
             }
         }
@@ -5169,7 +5170,7 @@
             // In this case we will always be STATE_OUT_OF_SERVICE, so need
             // to infer that we are scanning from other data.
             if (state == ServiceState.STATE_OUT_OF_SERVICE
-                    && strengthBin > SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+                    && strengthBin > CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
                 state = ServiceState.STATE_IN_SERVICE;
             }
         }
@@ -5186,7 +5187,7 @@
         // bin and have the scanning bit set.
         } else if (state == ServiceState.STATE_OUT_OF_SERVICE) {
             scanning = true;
-            strengthBin = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            strengthBin = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
             if (!mPhoneSignalScanningTimer.isRunningLocked()) {
                 mHistoryCur.states |= HistoryItem.STATE_PHONE_SCANNING_FLAG;
                 newHistory = true;
@@ -9786,7 +9787,7 @@
         mDeviceLightIdlingTimer = new StopwatchTimer(mClocks, null, -15, null, mOnBatteryTimeBase);
         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase);
         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase);
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i, null,
                     mOnBatteryTimeBase);
         }
@@ -10495,7 +10496,7 @@
         mFlashlightOnTimer.reset(false);
         mCameraOnTimer.reset(false);
         mBluetoothScanTimer.reset(false);
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
             mPhoneSignalStrengthsTimer[i].reset(false);
         }
         mPhoneSignalScanningTimer.reset(false);
@@ -10801,10 +10802,10 @@
                 mHasWifiReporting = true;
 
                 // Measured in mAms
-                final long txTimeMs = info.getControllerTxTimeMillis();
-                final long rxTimeMs = info.getControllerRxTimeMillis();
-                final long scanTimeMs = info.getControllerScanTimeMillis();
-                final long idleTimeMs = info.getControllerIdleTimeMillis();
+                final long txTimeMs = info.getControllerTxDurationMillis();
+                final long rxTimeMs = info.getControllerRxDurationMillis();
+                final long scanTimeMs = info.getControllerScanDurationMillis();
+                final long idleTimeMs = info.getControllerIdleDurationMillis();
                 final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
 
                 long leftOverRxTimeMs = rxTimeMs;
@@ -10947,13 +10948,14 @@
 
 
                 // Update WiFi controller stats.
-                mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
+                mWifiActivity.getRxTimeCounter().addCountLocked(
+                        info.getControllerRxDurationMillis());
                 mWifiActivity.getTxTimeCounters()[0].addCountLocked(
-                        info.getControllerTxTimeMillis());
+                        info.getControllerTxDurationMillis());
                 mWifiActivity.getScanTimeCounter().addCountLocked(
-                    info.getControllerScanTimeMillis());
+                        info.getControllerScanDurationMillis());
                 mWifiActivity.getIdleTimeCounter().addCountLocked(
-                        info.getControllerIdleTimeMillis());
+                        info.getControllerIdleDurationMillis());
 
                 // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
                 final double opVolt = mPowerProfile.getAveragePower(
@@ -10961,7 +10963,7 @@
                 if (opVolt != 0) {
                     // We store the power drain as mAms.
                     mWifiActivity.getPowerCounter().addCountLocked(
-                            (long) (info.getControllerEnergyUsed() / opVolt));
+                            (long) (info.getControllerEnergyUsedMicroJoules() / opVolt));
                 }
                 // Converting uWs to mAms.
                 // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
@@ -11056,7 +11058,7 @@
                             mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
                     List<TransmitPower> txPowerInfo = deltaInfo.getTransmitPowerInfo();
                     for (int i = 0; i < Math.min(txPowerInfo.size(),
-                            SignalStrength.NUM_SIGNAL_STRENGTH_BINS); i++) {
+                            CellSignalStrength.getNumSignalStrengthLevels()); i++) {
                         energyUsed += txPowerInfo.get(i).getTimeInMillis() * mPowerProfile
                             .getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
                     }
@@ -12607,7 +12609,8 @@
         for (int i = 0; i < timeInRatMs.length; i++) {
            timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
         }
-        long[] timeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+        long[] timeInRxSignalStrengthLevelMs =
+                new long[CellSignalStrength.getNumSignalStrengthLevels()];
         for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
            timeInRxSignalStrengthLevelMs[i]
                = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
@@ -13615,7 +13618,7 @@
         mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
         mPhoneOnTimer.readSummaryFromParcelLocked(in);
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
         }
         mPhoneSignalScanningTimer.readSummaryFromParcelLocked(in);
@@ -14100,7 +14103,7 @@
         mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
         mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -14578,7 +14581,7 @@
                 mOnBatteryTimeBase, in);
         mDeviceIdlingTimer = new StopwatchTimer(mClocks, null, -12, null, mOnBatteryTimeBase, in);
         mPhoneOnTimer = new StopwatchTimer(mClocks, null, -3, null, mOnBatteryTimeBase, in);
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -200-i,
                     null, mOnBatteryTimeBase, in);
         }
@@ -14797,7 +14800,7 @@
         mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+        for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
         }
         mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
@@ -14988,7 +14991,7 @@
             mDeviceIdlingTimer.logState(pr, "  ");
             pr.println("*** Phone timer:");
             mPhoneOnTimer.logState(pr, "  ");
-            for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+            for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) {
                 pr.println("*** Phone signal strength #" + i + ":");
                 mPhoneSignalStrengthsTimer[i].logState(pr, "  ");
             }
diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
index 9e8f06d..7c77d28 100644
--- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
+++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
@@ -16,14 +16,14 @@
 package com.android.internal.os;
 
 import android.os.BatteryStats;
-import android.telephony.SignalStrength;
+import android.telephony.CellSignalStrength;
 import android.util.Log;
 
 public class MobileRadioPowerCalculator extends PowerCalculator {
     private static final String TAG = "MobileRadioPowerController";
     private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
     private final double mPowerRadioOn;
-    private final double[] mPowerBins = new double[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+    private final double[] mPowerBins = new double[CellSignalStrength.getNumSignalStrengthLevels()];
     private final double mPowerScan;
     private BatteryStats mStats;
     private long mTotalAppMobileActiveMs = 0;
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index bd28fe0..6095ffa 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -5,6 +5,7 @@
 #include "SkShader.h"
 #include "SkBlendMode.h"
 #include "core_jni_helpers.h"
+#include "src/shaders/SkRTShader.h"
 
 #include <jni.h>
 
@@ -212,6 +213,44 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
+static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderFactory, jlong matrixPtr,
+        jbyteArray inputs, jlong colorSpaceHandle) {
+    SkRuntimeShaderFactory* factory = reinterpret_cast<SkRuntimeShaderFactory*>(shaderFactory);
+    AutoJavaByteArray arInputs(env, inputs);
+
+    sk_sp<SkData> fData;
+    fData = SkData::MakeWithCopy(arInputs.ptr(), arInputs.length());
+    const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
+    sk_sp<SkShader> shader = factory->make(fData, matrix);
+    ThrowIAE_IfNull(env, shader);
+
+    return reinterpret_cast<jlong>(shader.release());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+static jlong RuntimeShader_createShaderFactory(JNIEnv* env, jobject, jstring sksl,
+        jboolean isOpaque) {
+    ScopedUtfChars strSksl(env, sksl);
+    SkRuntimeShaderFactory* shaderFactory = new SkRuntimeShaderFactory(SkString(strSksl.c_str()),
+            isOpaque == JNI_TRUE);
+    ThrowIAE_IfNull(env, shaderFactory);
+
+    return reinterpret_cast<jlong>(shaderFactory);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+static void RuntimeShader_delete(SkRuntimeShaderFactory* shaderFactory) {
+    delete shaderFactory;
+}
+
+static jlong RuntimeShader_getNativeFinalizer(JNIEnv*, jobject) {
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&RuntimeShader_delete));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
 static const JNINativeMethod gColorMethods[] = {
     { "nativeRGBToHSV",    "(III[F)V", (void*)Color_RGBToHSV   },
     { "nativeHSVToColor",  "(I[F)I",   (void*)Color_HSVToColor }
@@ -241,6 +280,13 @@
     { "nativeCreate",      "(JJJI)J",   (void*)ComposeShader_create     },
 };
 
+static const JNINativeMethod gRuntimeShaderMethods[] = {
+    { "nativeGetFinalizer",   "()J",    (void*)RuntimeShader_getNativeFinalizer },
+    { "nativeCreate",     "(JJ[BJ)J",  (void*)RuntimeShader_create     },
+    { "nativeCreateShaderFactory",     "(Ljava/lang/String;Z)J",
+      (void*)RuntimeShader_createShaderFactory     },
+};
+
 int register_android_graphics_Shader(JNIEnv* env)
 {
     android::RegisterMethodsOrDie(env, "android/graphics/Color", gColorMethods,
@@ -257,6 +303,8 @@
                                   NELEM(gSweepGradientMethods));
     android::RegisterMethodsOrDie(env, "android/graphics/ComposeShader", gComposeShaderMethods,
                                   NELEM(gComposeShaderMethods));
+    android::RegisterMethodsOrDie(env, "android/graphics/RuntimeShader", gRuntimeShaderMethods,
+                                  NELEM(gRuntimeShaderMethods));
 
     return 0;
 }
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 8fabb23..fd6984b 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -36,6 +36,7 @@
   "/apex/com.android.conscrypt/javalib/conscrypt.jar",
   "/apex/com.android.ipsec/javalib/ike.jar",
   "/apex/com.android.media/javalib/updatable-media.jar",
+  "/apex/com.android.sdkext/javalib/framework-sdkext.jar",
   "/dev/null",
   "/dev/socket/zygote",
   "/dev/socket/zygote_secondary",
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index d095690..4acdeeb 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Dien in"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Bestuurprogram werk tans"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tik om die bestuurprogram te verlaat."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Verbinding of Wi-Fi-warmkol aktief"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tik om op te stel."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Verbinding is gedeaktiveer"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Kontak jou administrateur vir besonderhede"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Terug"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Volgende"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Slaan oor"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 75444ea..c6e55c3 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"አስረክብ"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"የመንዳት መተግበሪያ እያሄደ ነው"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ከመንዳት መተግበሪያ ለመውጣት መታ ያድርጉ።"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"መሰካት ወይም ገባሪ ድረስ ነጥብ"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"ለማዋቀር መታ ያድርጉ።"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"እንደ ሞደም መሰካት ተሰናክሏል"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"ለዝርዝሮች የእርስዎን አስተዳዳሪ ያነጋግሩ"</string>
     <string name="back_button_label" msgid="4078224038025043387">"ተመለስ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"ቀጥሎ"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"ዝለል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 9928436..609b77e 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1509,10 +1509,6 @@
     <string name="submit" msgid="862795280643405865">"إرسال"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"تطبيق القيادة قيد التشغيل"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"انقر للخروج من تطبيق القيادة."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"النطاق أو نقطة الاتصال نشطة"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"انقر للإعداد."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"تم إيقاف التوصيل"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"اتصل بالمشرف للحصول على التفاصيل"</string>
     <string name="back_button_label" msgid="4078224038025043387">"رجوع"</string>
     <string name="next_button_label" msgid="6040209156399907780">"التالي"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"التخطي"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index cfd6239..091b563 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"দাখিল কৰক"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ড্ৰাইভিং এপ্ চলি আছে"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ড্ৰাইভিং এপৰ পৰা বাহিৰ হ\'বলৈ টিপক।"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"টেডাৰিং বা হটস্প\'ট সক্ৰিয় অৱস্থাত আছে"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"ছেট আপ কৰিবলৈ টিপক।"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"টেডাৰিং অক্ষম কৰি থোৱা হৈছে"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"সবিশেষ জানিবলৈ আপোনাৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক"</string>
     <string name="back_button_label" msgid="4078224038025043387">"উভতি যাওক"</string>
     <string name="next_button_label" msgid="6040209156399907780">"পৰৱৰ্তী"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"এৰি যাওক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index a26d49d..359dfb7 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Göndər"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Sürücülük tətbiqi işləyir"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Sürücülük tətbiqindən çıxmaq üçün klikləyin."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tezerinq və ya hotspot aktivdir"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Quraşdırmaq üçün tıklayın."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Birləşmə deaktivdir"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Məlumat üçün adminlə əlaqə saxlayın"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Geri"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Növbəti"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Keç"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 6d0ae6b..a27d359 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1449,10 +1449,6 @@
     <string name="submit" msgid="862795280643405865">"Pošalji"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Aplikacija za vožnju je pokrenuta"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Dodirnite da biste izašli iz aplikacije za vožnju."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Aktivno povezivanje sa internetom preko mobilnog uređaja ili hotspot"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Dodirnite da biste podesili."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Privezivanje je onemogućeno"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Potražite detalje od administratora"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Nazad"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Next"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Preskoči"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 390e8b1..fb0fa33 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1469,10 +1469,6 @@
     <string name="submit" msgid="862795280643405865">"Перадаць"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Праграма для ваджэння ўключана"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Націсніце, каб выйсці з праграмы для ваджэння."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"USB-мадэм або хот-спот Wi-Fi актыўныя"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Дакраніцеся, каб наладзіць."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Рэжым мадэма адключаны"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Звярніцеся да адміністратара па падрабязную інфармацыю"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Назад"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Далей"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Прапусціць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index d47229df..69c998d 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Изпращане"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Приложението за шофиране е включено"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Докоснете, за да излезете от приложението за шофиране."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Има активна споделена връзка или безжична точка за достъп"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Докоснете, за да настроите."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Функцията за тетъринг е деактивирана"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Свържете се с администратора си за подробности"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Назад"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Напред"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Пропускане"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index a767a71..e335396 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"জমা দিন"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ড্রাইভিং অ্যাপ চালু আছে"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ড্রাইভিং অ্যাপ বন্ধ করতে ট্যাপ করুন।"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"টিথারিং বা হটস্পট সক্রিয় আছে"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"সেট-আপ করার জন্য আলতো চাপুন৷"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"টিথারিং অক্ষম করা আছে"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"বিশদ বিবরণের জন্য প্রশাসকের সাথে যোগাযোগ করুন"</string>
     <string name="back_button_label" msgid="4078224038025043387">"ফিরুন"</string>
     <string name="next_button_label" msgid="6040209156399907780">"পরবর্তী"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"এড়িয়ে যান"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index f1c1500..d7bd7a1 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1451,10 +1451,6 @@
     <string name="submit" msgid="862795280643405865">"Potvrdi"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Aplikacija za vožnju je pokrenuta"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Dodirnite za izlaz iz aplikacije za vožnju."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Uređaj dijeli vezu ili djeluje kao pristupna tačka"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Dodirnite za postavke"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Povezivanje putem mobitela je onemogućeno"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Kontaktirajte svog administratora za dodatne detalje"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Nazad"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Naprijed"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Preskoči"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 4b19405..1f7d82e 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Envia"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"S\'està executant l\'aplicació de conducció"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Toca per sortir de l\'aplicació de conducció."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Compartició de xarxa o punt d\'accés Wi-Fi activat"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Toca per configurar."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"La compartició de xarxa està desactivada"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Contacta amb el teu administrador per obtenir més informació"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Enrere"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Següent"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Omet"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 22fd4c6..e05f299 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1469,10 +1469,6 @@
     <string name="submit" msgid="862795280643405865">"Odeslat"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Jízdní aplikace je spuštěna"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Jízdní aplikaci zavřete klepnutím."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Sdílené připojení nebo hotspot je aktivní."</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Klepnutím zahájíte nastavení."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering je zakázán"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"O podrobnosti požádejte administrátora"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Zpět"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Další"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Přeskočit"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 4475a1b..772b7b0 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Send"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Bilkørselsappen er aktiv"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tryk for at lukke bilkørselsappen."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Netdeling eller hotspot er aktivt"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tryk for at konfigurere"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Netdeling er deaktiveret"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Kontakt din administrator for at få oplysninger"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Tilbage"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Næste"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Spring over"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 2489fca..bb29a0e 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Senden"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Fahr-App wird ausgeführt"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tippen, um die Fahr-App zu beenden."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering oder Hotspot aktiv"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Zum Einrichten tippen."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering ist deaktiviert"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Bitte wende dich für weitere Informationen an den Administrator"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Zurück"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Weiter"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Überspringen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 6c76a1f..807c4c2 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Υποβολή"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Η εφαρμογή οδήγησης εκτελείται"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Πατήστε για να εξέλθετε από την εφαρμογή οδήγησης."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Πρόσδεση ή σύνδεση σημείου πρόσβασης ενεργή"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Πατήστε για ρύθμιση."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Η σύνδεση είναι απενεργοποιημένη"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Επικοινωνήστε με τον διαχειριστή σας για λεπτομέρειες"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Πίσω"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Επόμενο"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Παράλειψη"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index e5f610b..8d2f805 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Submit"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Driving app is running"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tap to exit driving app."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering or hotspot active"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tap to set up."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering is disabled"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Contact your admin for details"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Back"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Next"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Skip"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 2cff16f..e538587 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Submit"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Driving app is running"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tap to exit driving app."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering or hotspot active"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tap to set up."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering is disabled"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Contact your admin for details"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Back"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Next"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Skip"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index e5f610b..8d2f805 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Submit"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Driving app is running"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tap to exit driving app."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering or hotspot active"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tap to set up."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering is disabled"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Contact your admin for details"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Back"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Next"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Skip"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index e5f610b..8d2f805 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Submit"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Driving app is running"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tap to exit driving app."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering or hotspot active"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tap to set up."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering is disabled"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Contact your admin for details"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Back"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Next"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Skip"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 6d536e4..1436692 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎Submit‎‏‎‎‏‎"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‏‎‎‎‎‎Driving app is running‎‏‎‎‏‎"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‎Tap to exit driving app.‎‏‎‎‏‎"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‎Tethering or hotspot active‎‏‎‎‏‎"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎Tap to set up.‎‏‎‎‏‎"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‏‎Tethering is disabled‎‏‎‎‏‎"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎Contact your admin for details‎‏‎‎‏‎"</string>
     <string name="back_button_label" msgid="4078224038025043387">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎Back‎‏‎‎‏‎"</string>
     <string name="next_button_label" msgid="6040209156399907780">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‎‏‎‎‎Next‎‏‎‎‏‎"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎Skip‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 3b9c7ad..b04882a 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Enviar"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Se está ejecutando la app de conducción"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Presiona para salir de la app de conducción."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Anclaje a red o zona activa conectados"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Presiona para configurar."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Se inhabilitó la conexión mediante dispositivo portátil"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Para obtener más información, comunícate con el administrador"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Atrás"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Siguiente"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Omitir"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 2e74904..81f210b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Enviar"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Aplicación de conducción en uso"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Toca para salir de la aplicación de conducción."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Compartir conexión/Zona Wi-Fi activada"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Toca para configurar."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"La conexión compartida está inhabilitada"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Ponte en contacto con el administrador para obtener más información"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Atrás"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Siguiente"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Saltar"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 8561254..61b18bb 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Saada"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Sõidurakendus töötab"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Puudutage sõidurakendusest väljumiseks."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Jagamine või kuumkoht on aktiivne"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Puudutage seadistamiseks."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Jagamine on keelatud"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Lisateabe saamiseks võtke ühendust oma administraatoriga"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Tagasi"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Järgmine"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Jäta vahele"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 263b5ed..fda8565 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Bidali"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Abian da gidatzeko aplikazioa"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Sakatu gidatzeko aplikaziotik irteteko."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Konexioa partekatzea edo sare publikoa aktibo"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Sakatu konfiguratzeko."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Desgaituta dago konexioa partekatzeko aukera"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Xehetasunak lortzeko, jarri administratzailearekin harremanetan"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Atzera"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Hurrengoa"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Saltatu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 997b6af..433d4f3 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"ارسال"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"برنامه رانندگی درحال اجرا است"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"برای خروج از برنامه رانندگی ضربه بزنید."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"اشتراک‌گذاری اینترنت یا نقطه اتصال فعال"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"برای راه‌اندازی ضربه بزنید."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"اشتراک‌گذاری اینترنت غیرفعال است"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"برای جزئیات، با سرپرستتان تماس بگیرید"</string>
     <string name="back_button_label" msgid="4078224038025043387">"برگشت"</string>
     <string name="next_button_label" msgid="6040209156399907780">"بعدی"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"رد شدن"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 86badf6..0c7bd77 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Lähetä"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Ajosovellus on käynnissä"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Poistu ajosovelluksesta napauttamalla."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Internetin jakaminen tai yhteyspiste käytössä"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Määritä napauttamalla."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Yhteyden jakaminen poistettu käytöstä"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Kysy lisätietoja järjestelmänvalvojalta."</string>
     <string name="back_button_label" msgid="4078224038025043387">"Takaisin"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Seuraava"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Ohita"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 2b89065..3c8f75f 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Envoyer"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"L\'application de conduite est en cours d\'exécution"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Touchez pour quitter l\'application de conduite."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Partage de connexion ou point d\'accès sans fil activé"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Touchez pour configurer."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Le partage de connexion est désactivé"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Communiquez avec votre administrateur pour obtenir plus de détails"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Précédent"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Suivante"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Passer"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 7522b5aa..1b53bd9 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Envoyer"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"L\'application de conduite est en cours d\'exécution"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Appuyez ici pour quitter l\'application de conduite."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Partage de connexion ou point d\'accès sans fil activé"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Appuyez ici pour configurer."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Le partage de connexion est désactivé"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Pour en savoir plus, contactez votre administrateur"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Retour"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Suivant"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Ignorer"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 4d40e21..4572db7 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Enviar"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Estase executando a aplicación de condución"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Toca para saír da aplicación de condución."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Conexión compartida ou zona wifi activada"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tocar para configurar."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"A conexión compartida está desactivada"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Contacta co administrador para obter información"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Volver"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Seguinte"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Omitir"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index ea3a573..5e4f753 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"સબમિટ કરો"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ડ્રાઇવિંગ ઍપ ચાલી રહી છે"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ડ્રાઇવિંગ ઍપથી બહાર નીકળવા માટે ટૅપ કરો."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ટિથરિંગ અથવા હૉટસ્પૉટ સક્રિય"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"સેટ કરવા માટે ટૅપ કરો."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ટિથરિંગ અક્ષમ કરેલ છે"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"વિગતો માટે તમારા વ્યવસ્થાપકનો સંપર્ક કરો"</string>
     <string name="back_button_label" msgid="4078224038025043387">"પાછળ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"આગલું"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"છોડો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index e12fa08..eecfd5b 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"सबमिट करें"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ड्राइविंग ऐप्लिकेशन चल रहा है"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ड्राइविंग ऐप्लिकेशन से निकलने के लिए टैप करें."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"टेदरिंग या हॉटस्‍पॉट सक्रिय"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"सेट करने के लिए टैप करें."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"टेदरिंग अक्षम है"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"जानकारी के लिए अपने एडमिन से संपर्क करें"</string>
     <string name="back_button_label" msgid="4078224038025043387">"वापस जाएं"</string>
     <string name="next_button_label" msgid="6040209156399907780">"आगे बढ़ें"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"अभी नहीं"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 0871d06..e8f02b2 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1449,10 +1449,6 @@
     <string name="submit" msgid="862795280643405865">"Pošalji"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Pokrenuta je aplikacija za vožnju"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Dodirnite za zatvaranje aplikacije za vožnju."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Ograničenje ili aktivan hotspot"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Dodirnite da biste postavili."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Modemsko je povezivanje onemogućeno"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Obratite se administratoru da biste saznali pojedinosti"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Natrag"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Dalje"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Preskoči"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index ce11fc6..1d1b994 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Elküldés"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Az autós alkalmazás fut"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Koppintson ide az autós alkalmazásból való kilépéshez."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Megosztás vagy aktív hotspot"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Koppintson a beállításhoz."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Az internetmegosztás le van tiltva"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"A részletekért forduljon rendszergazdájához"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Vissza"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Tovább"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Kihagyás"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 629b225..599ce86 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Ուղարկել"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Հավելվածն աշխատում է"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Հպեք՝ հավելվածը փակելու համար:"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Մոդեմի ռեժիմը միացված է"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Հպեք՝ կարգավորելու համար:"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Մոդեմի ռեժիմն անջատված է"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Մանրամասների համար դիմեք ձեր ադմինիստրատորին"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Հետ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Հաջորդը"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Բաց թողնել"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index f99c107..1f81eb5 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Kirim"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Aplikasi mengemudi sedang berjalan"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Ketuk untuk keluar dari aplikasi mengemudi."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering (Penambatan) atau hotspot aktif"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Ketuk untuk menyiapkan."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering dinonaktifkan"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Hubungi admin untuk mengetahui detailnya"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Kembali"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Selanjutnya"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Lewati"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 0f4d6de..d23cf5f 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Senda"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Akstursforrit er í gangi"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Ýttu til að loka akstursforritinu."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Kveikt á tjóðrun eða aðgangsstað"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Ýttu til að setja upp."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Slökkt er á tjóðrun"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Hafðu samband við kerfisstjórann til að fá upplýsingar"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Til baka"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Áfram"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Sleppa"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index f14e858..8ebcb0e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Invia"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"App di guida in esecuzione"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tocca per uscire dall\'app di guida."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering oppure hotspot attivo"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tocca per impostare."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering disattivato"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Contatta il tuo amministratore per avere informazioni dettagliate"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Indietro"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Avanti"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Ignora"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 375d7d1..85d0f3b 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1469,10 +1469,6 @@
     <string name="submit" msgid="862795280643405865">"שלח"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"אפליקציית הנהיגה פועלת"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"יש להקיש כדי לצאת מאפליקציית הנהיגה."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"שיתוף אינטרנט פעיל"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"הקש כדי להגדיר."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"שיתוף האינטרנט בין ניידים מושבת"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"לפרטים, יש לפנות למנהל המערכת"</string>
     <string name="back_button_label" msgid="4078224038025043387">"הקודם"</string>
     <string name="next_button_label" msgid="6040209156399907780">"הבא"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"דילוג"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index eb990ec..e21035f 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"送信"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"運転アプリを実行しています"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"運転アプリを終了するにはタップしてください。"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"テザリングまたはアクセスポイントが有効です"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"タップしてセットアップします。"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"テザリングは無効に設定されています"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"詳しくは、管理者にお問い合わせください"</string>
     <string name="back_button_label" msgid="4078224038025043387">"戻る"</string>
     <string name="next_button_label" msgid="6040209156399907780">"次へ"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"スキップ"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index d2d1fed..941dbbd 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"გაგზავნა"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"მართვის აპი გაშვებულია"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"შეეხეთ მართვის აპიდან გასასვლელად."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ტეტერინგი ან უსადენო ქსელი აქტიურია"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"შეეხეთ დასაყენებლად."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ტეტერინგი გათიშულია"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"დამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს"</string>
     <string name="back_button_label" msgid="4078224038025043387">"უკან"</string>
     <string name="next_button_label" msgid="6040209156399907780">"მომდევნო"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"გამოტოვება"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index a1002f7..b142e58 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Жіберу"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Көлік жүргізу қолданбасы қосулы"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Көлік жүргізу қолданбасынан шығу үшін түртіңіз."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Тетеринг немесе хотспот қосулы"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Реттеу үшін түртіңіз."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Тетеринг өшірілді"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Мәліметтерді әкімшіден алыңыз"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Артқа"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Келесі"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Өткізіп жіберу"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 61a3ec6..43289eb 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1431,10 +1431,6 @@
     <string name="submit" msgid="862795280643405865">"ដាក់​ស្នើ"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"កម្មវិធី​បើកបរ​កំពុង​ដំណើរការ"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ចុច​ដើម្បី​ចាកចេញ​ពីកម្មវិធី​បើកបរ។"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ភ្ជាប់ ឬ​ហតស្ពត​សកម្ម"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"ប៉ះដើម្បីកំណត់"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ការភ្ជាប់​ត្រូវបានបិទ"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"ទាក់ទងអ្នកគ្រប់គ្រង​របស់អ្នកសម្រាប់​ព័ត៌មានលម្អិត"</string>
     <string name="back_button_label" msgid="4078224038025043387">"ថយក្រោយ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"បន្ទាប់​"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"រំលង"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 5524d40..6ebe7b4 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"ಸಲ್ಲಿಸು"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ಡ್ರೈವಿಂಗ್‌ ಅಪ್ಲಿಕೇಶನ್ ಚಾಲನೆಯಲ್ಲಿದೆ"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ಡ್ರೈವಿಂಗ್‌ ಅಪ್ಲಿಕೇಶನ್ ನಿರ್ಗಮಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ಟೆಥರಿಂಗ್ ಅಥವಾ ಹಾಟ್‌ಸ್ಪಾಟ್ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ಟೆಥರಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"ವಿವರಗಳಿಗಾಗಿ ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ"</string>
     <string name="back_button_label" msgid="4078224038025043387">"ಹಿಂದೆ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"ಮುಂದಿನದು"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"ಸ್ಕಿಪ್‌"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 423dbd6..c6caedf 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"제출"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"운전 앱 실행 중"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"운전 앱을 종료하려면 탭하세요."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"테더링 또는 핫스팟 사용"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"설정하려면 탭하세요."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"테더링이 사용 중지됨"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"자세한 정보는 관리자에게 문의하세요."</string>
     <string name="back_button_label" msgid="4078224038025043387">"뒤로"</string>
     <string name="next_button_label" msgid="6040209156399907780">"다음"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"건너뛰기"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index d1d773c..341c996 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Тапшыруу"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Унаа айдоо колдонмосу иштеп жатат"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Унаа айдоо колдонмосунан чыгуу үчүн таптаңыз."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Жалгаштыруу же хотспот жандырылган"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Жөндөө үчүн таптап коюңуз."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Жалгаштыруу функциясы өчүрүлгөн"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Кеңири маалымат үчүн администраторуңузга кайрылыңыз"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Артка"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Кийинки"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Өткөрүп жиберүү"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index ded2a4f..e0da206 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"ສົ່ງຂໍ້ມູນ"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ແອັບຂັບລົດກຳລັງເຮັດວຽກຢູ່"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ແຕະເພື່ອອອກຈາກແອັບຂັບລົດ."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ເປີດ​ການ​ປ່ອຍ​ສັນຍານ ຫຼື​ຮັອດສະປອດ​ແລ້ວ"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"ແຕະເພື່ອຕັ້ງຄ່າ."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ການປ່ອຍສັນຍານຖືກປິດໄວ້"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"ຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບສຳລັບລາຍລະອຽດ"</string>
     <string name="back_button_label" msgid="4078224038025043387">"ກັບຄືນ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"ຕໍ່ໄປ"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"ຂ້າມ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index eac535c..1212aa4 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1469,10 +1469,6 @@
     <string name="submit" msgid="862795280643405865">"Pateikti"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Veikia vairavimo programa"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Palieskite, kad išeitumėte iš vairavimo programos."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Susietas ar aktyvus"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Palieskite, kad nustatytumėte."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Įrenginio kaip modemo naudojimas išjungtas"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Jei reikia išsamios informacijos, susisiekite su administratoriumi"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Atgal"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Kitas"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Praleisti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index f586212..547b6c9 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1449,10 +1449,6 @@
     <string name="submit" msgid="862795280643405865">"Iesniegt"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Autovadīšanas lietotne darbojas"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Pieskarieties, lai izietu no autovadīšanas lietotnes"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Piesaiste vai tīklājs ir aktīvs."</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Pieskarieties, lai iestatītu."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Piesaiste ir atspējota"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Lai iegūtu detalizētu informāciju, sazinieties ar savu administratoru."</string>
     <string name="back_button_label" msgid="4078224038025043387">"Atpakaļ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Tālāk"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Izlaist"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 0d308a1..93f2da1 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Поднеси"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Апликацијата за возење работи"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Допрете за да излезете од апликацијата за возење."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Поврзувањето или точката на пристап се активни"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Допрете за поставување."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Врзувањето е оневозможено"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Контактирајте со администраторот за детали"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Назад"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Следно"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Прескокни"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 63a7194..c220cdd 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"സമർപ്പിക്കുക"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ഡ്രൈവിംഗ് ആപ്പ് റൺ ചെയ്യുകയാണ്"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ഡ്രൈവിംഗ് ആപ്പിൽ നിന്ന് പുറത്തുകടക്കാൻ ടാപ്പ് ചെയ്യുക."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ടെതറിംഗ് അല്ലെങ്കിൽ ഹോട്ട്സ്‌പോട്ട് സജീവമാണ്"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"സജ്ജമാക്കാൻ ടാപ്പുചെയ്യുക."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ടെതറിംഗ് പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"വിശദവിവരങ്ങൾക്ക് നിങ്ങളുടെ അഡ്മിനെ ബന്ധപ്പെടുക"</string>
     <string name="back_button_label" msgid="4078224038025043387">"മടങ്ങുക"</string>
     <string name="next_button_label" msgid="6040209156399907780">"അടുത്തത്"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"ഒഴിവാക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index b3cf5ce..8c26113 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Илгээх"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Жолоо барих апп ажиллаж байна"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Жолооны аппаас гарахын тулд товшино уу."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Модем болгох эсвэл идэвхтэй цэг болгох"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Тохируулахын тулд товшино уу."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Модем болгох боломжгүй байна"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Дэлгэрэнгүй мэдээлэл авахын тулд админтайгаа холбогдоно уу"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Буцах"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Дараах"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Алгасах"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 22b1dcc..2782caf 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"सबमिट करा"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ड्रायव्हिंग अ‍ॅप चालू आहे"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ड्रायव्हिंग ॲपमधून बाहेर पाडण्यासाठी टॅप करा."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"टेदरिंग किंवा हॉटस्पॉट सक्रिय"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"सेट करण्यासाठी टॅप करा."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"टेदरिंग बंद आहे"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"तपशीलांसाठी तुमच्या प्रशासकाशी संपर्क साधा"</string>
     <string name="back_button_label" msgid="4078224038025043387">"मागे"</string>
     <string name="next_button_label" msgid="6040209156399907780">"पुढील"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"वगळा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 88c12b6..a40eca0 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Serah"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Apl memandu sedang berjalan"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Ketik untuk keluar daripada apl memandu."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Penambatan atau titik panas aktif"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Ketik untuk membuat persediaan."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Penambatan dilumpuhkan"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Hubungi pentadbir anda untuk maklumat lanjut"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Kembali"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Seterusnya"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Langkau"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index cdf68cd..64e2376 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"ပေးပို့ရန်"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ကားမောင်းသည့်အက်ပ် ပွင့်နေပါသည်"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ကားမောင်းသည့်အက်ပ်မှ ထွက်ရန် တို့ပါ။"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"တဆင့်ပြန်လည်လွှင့်ခြင်း သို့မဟုတ် ဟော့စပေါ့ ဖွင့်ထားသည်"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"စနစ်ထည့်သွင်းရန် တို့ပါ။"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"မိုဘိုင်းဖုန်းကို မိုဒမ်အဖြစ်သုံးခြင်းအား ပိတ်ထားသည်"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"အသေးစိတ်အချက်အလက်များအတွက် သင့်စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ"</string>
     <string name="back_button_label" msgid="4078224038025043387">"နောက်သို့"</string>
     <string name="next_button_label" msgid="6040209156399907780">"ရှေ့သို့"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"ကျော်ရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b129c3c..69e341e 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Send inn"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Kjøreappen kjører"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Trykk for å lukke kjøreappen."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Internettdeling eller trådløs sone er aktiv"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Trykk for å konfigurere."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Internettdeling er slått av"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Ta kontakt med administratoren din for å få mer informasjon"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Tilbake"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Neste"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Hopp over"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 648f47c..0fb2213 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1435,10 +1435,6 @@
     <string name="submit" msgid="862795280643405865">"पेस गर्नुहोस्"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ड्राइभिङ अनुप्रयोग चलिरहेको छ"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ड्राइभिङ अनुप्रयोगबाट बाहिर निस्कन ट्याप गर्नुहोस्।"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"टेथर गर्ने वा हटस्पट सक्रिय"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"सेटअप गर्न ट्याप गर्नुहोस्।"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"टेदरिङलाई असक्षम पारिएको छ"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"विवरणहरूका लागि आफ्ना प्रशासकलाई सम्पर्क गर्नुहोस्"</string>
     <string name="back_button_label" msgid="4078224038025043387">"पछाडि"</string>
     <string name="next_button_label" msgid="6040209156399907780">"अर्को"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"छोड्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index e248ca1..363c3c3 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Verzenden"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Auto-app wordt uitgevoerd"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tik om de auto-app te sluiten."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering of hotspot actief"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tik om in te stellen."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering is uitgeschakeld"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Neem contact op met je beheerder voor meer informatie"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Vorige"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Volgende"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Overslaan"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 7a73cc6..566d778 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"ଦାଖଲ କରନ୍ତୁ"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ଡ୍ରାଇଭିଙ୍ଗ ଆପ୍ ଚାଲୁଛି"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ଡ୍ରାଇଭିଙ୍ଗ ଆପ୍‌ରୁ ବାହାରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ଟିଥରିଙ୍ଗ କିମ୍ୱା ହଟସ୍ପଟ୍‌ ସକ୍ରିୟ ଅଛି"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"ସେଟଅପ୍‍ କରିବାକୁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ଟିଥରିଙ୍ଗ ଅକ୍ଷମ କରାଯାଇଛି"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"ବିବରଣୀ ପାଇଁ ନିଜ ଆଡମିନ୍‌ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ"</string>
     <string name="back_button_label" msgid="4078224038025043387">"ଫେରନ୍ତୁ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"ପରବର୍ତ୍ତୀ"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"ଛାଡ଼ିଦିଅନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 3a245e3..7760db0 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"ਪ੍ਰਸਤੁਤ ਕਰੋ"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ਗੱਡੀ ਚਲਾਉਣ ਸੰਬੰਧੀ ਐਪ ਚੱਲ ਰਹੀ ਹੈ"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ਗੱਡੀ ਚਲਾਉਣ ਸੰਬੰਧੀ ਐਪ ਤੋਂ ਬਾਹਰ ਜਾਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ਟੈਦਰਿੰਗ ਜਾਂ ਹੌਟਸਪੌਟ ਕਿਰਿਆਸ਼ੀਲ"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"ਸਥਾਪਤ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ਟੈਦਰਿੰਗ ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"ਵੇਰਵਿਆਂ ਲਈ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ"</string>
     <string name="back_button_label" msgid="4078224038025043387">"ਪਿੱਛੇ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"ਅੱਗੇ"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"ਛੱਡੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 7a86bd5..4ff7cc4 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1469,10 +1469,6 @@
     <string name="submit" msgid="862795280643405865">"Prześlij"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Tryb samochodowy jest włączony"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Kliknij, by zakończyć tryb samochodowy."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Aktywny tethering lub punkt dostępu"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Kliknij, by skonfigurować."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering został wyłączony"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Aby uzyskać szczegółowe informacje, skontaktuj się z administratorem"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Wróć"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Dalej"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Pomiń"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 3f82a80..1750d2a 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Enviar"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"O app para carro está sendo usado"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Toque para sair do app para carro."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Ponto de acesso ou tethering ativo"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Toque para configurar."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering desativado"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Fale com seu administrador para saber detalhes"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Voltar"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Avançar"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Pular"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index f67c96f..5c21c0d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Enviar"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"A aplicação de condução está em execução."</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Toque para sair da aplicação de condução."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Ligação ponto a ponto ou hotspot activos"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Toque para configurar."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"A ligação (à Internet) via telemóvel está desativada."</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Contacte o gestor para obter detalhes."</string>
     <string name="back_button_label" msgid="4078224038025043387">"Anterior"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Seguinte"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Ignorar"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 3f82a80..1750d2a 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Enviar"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"O app para carro está sendo usado"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Toque para sair do app para carro."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Ponto de acesso ou tethering ativo"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Toque para configurar."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering desativado"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Fale com seu administrador para saber detalhes"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Voltar"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Avançar"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Pular"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 846b982..397525a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1449,10 +1449,6 @@
     <string name="submit" msgid="862795280643405865">"Trimiteți"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Aplicația pentru condus rulează"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Atingeți ca să ieșiți din aplicația pentru condus."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering sau hotspot activ"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Atingeți ca să configurați."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tetheringul este dezactivat"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Contactați administratorul pentru detalii"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Înapoi"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Înainte"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Omiteți"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 19fde9f..a7abbff 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1469,10 +1469,6 @@
     <string name="submit" msgid="862795280643405865">"Отправить"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Приложение для вождения включено"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Нажмите, чтобы выйти из приложения для вождения."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Включен режим модема"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Нажмите, чтобы настроить."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Включить режим модема нельзя"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Обратитесь к администратору, чтобы узнать подробности."</string>
     <string name="back_button_label" msgid="4078224038025043387">"Назад"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Далее"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Пропустить"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 676b48f..7d3f80d 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1431,10 +1431,6 @@
     <string name="submit" msgid="862795280643405865">"යොමු කරන්න"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"රියදුරු යෙදුම ධාවනය වේ."</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"රියදුරු යෙදුමෙන් පිටවීම සඳහා තට්ටු කරන්න."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ටෙදරින් හෝ හොට්ස්පොට් සක්‍රීයයි"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"පිහිටුවීමට තට්ටු කරන්න."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ටෙදරින් අබල කර ඇත"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"විස්තර සඳහා ඔබගේ පරිපාලක අමතන්න"</string>
     <string name="back_button_label" msgid="4078224038025043387">"ආපසු"</string>
     <string name="next_button_label" msgid="6040209156399907780">"මීලඟ"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"මඟ හරින්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index cde5466..3a81468c 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1469,10 +1469,6 @@
     <string name="submit" msgid="862795280643405865">"Odoslať"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Aplikácia na šoférovanie je spustená"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Klepnutím ukončíte aplikáciu na šoférovanie"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering alebo prístupový bod je aktívny"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Klepnutím prejdete na nastavenie."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering je deaktivovaný"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"O podrobnosti požiadajte svojho správcu"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Späť"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Ďalej"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Preskočiť"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 0494068..c28384c 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1469,10 +1469,6 @@
     <string name="submit" msgid="862795280643405865">"Pošlji"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Aplikacija za vožnjo se izvaja"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Dotaknite se, če želite zapreti aplikacijo za vožnjo."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Aktivna povezava z internetom ali dostopna točka sta aktivni"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Dotaknite se, če želite nastaviti."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Povezava z internetom prek mobilnega telefona je onemogočena"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Za podrobnosti se obrnite na skrbnika"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Nazaj"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Naprej"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Preskoči"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 20e6ae5..39f7377 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Dërgo"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Aplikacioni i drejtimit të makinës është në ekzekutim"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Trokit për të dalë nga aplikacioni i drejtimit të makinës."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Lidhja e çiftimit ose ajo e qasjes në zona publike interneti është aktive"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Trokit për ta konfiguruar."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Lidhja e çiftimit është çaktivizuar"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Kontakto me administratorin për detaje"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Prapa"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Përpara"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Kapërce"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index db53b23..e93c852 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1449,10 +1449,6 @@
     <string name="submit" msgid="862795280643405865">"Пошаљи"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Апликација за вожњу је покренута"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Додирните да бисте изашли из апликације за вожњу."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Активно повезивање са интернетом преко мобилног уређаја или хотспот"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Додирните да бисте подесили."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Привезивање је онемогућено"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Потражите детаље од администратора"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Назад"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Next"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Прескочи"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 9e99aec..cf0e0bb 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Skicka"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Bilkörningsappen körs"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tryck här om du vill avsluta bilkörningsappen."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Internetdelning eller surfzon aktiverad"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Tryck om du vill konfigurera."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Internetdelning har inaktiverats"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Kontakta administratören om du vill veta mer"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Tillbaka"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Nästa"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Hoppa över"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index d7b3555..f8cd19c 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Wasilisha"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Umewasha programu ya kuendesha gari"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Gusa ili ufunge programu ya kuendesha gari."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Kushiriki au kusambaza intaneti kumewashwa"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Gusa ili uweke mipangilio."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Umezima kipengele cha kusambaza mtandao"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Wasiliana na msimamizi wako ili upate maelezo zaidi"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Nyuma"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Endelea"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Ruka"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 569977c..ac284d3 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"சமர்ப்பி"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"\'வாகனம் ஓட்டும் பயன்முறை’ ஆனில் உள்ளது"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"வாகனம் ஓட்டும் பயன்முறையிலிருந்து வெளியேற, தட்டவும்."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"டெதெரிங்/ஹாட்ஸ்பாட் இயங்குகிறது"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"அமைக்க, தட்டவும்."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"இணைப்பு முறை முடக்கப்பட்டுள்ளது"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"விவரங்களுக்கு, உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்"</string>
     <string name="back_button_label" msgid="4078224038025043387">"முந்தையது"</string>
     <string name="next_button_label" msgid="6040209156399907780">"அடுத்து"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"தவிர்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 9600172..6641c41 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"సమర్పించు"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"డ్రైవింగ్ యాప్ అమలవుతోంది"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"డ్రైవింగ్ యాప్ నుండి నిష్క్రమించడం కోసం నొక్కండి."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"టీథర్ చేయబడినది లేదా హాట్‌స్పాట్ సక్రియంగా ఉండేది"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"సెటప్ చేయడానికి నొక్కండి."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"టెథెరింగ్ నిలిపివేయబడింది"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"వివరాల కోసం మీ నిర్వాహకులను సంప్రదించండి"</string>
     <string name="back_button_label" msgid="4078224038025043387">"వెనుకకు"</string>
     <string name="next_button_label" msgid="6040209156399907780">"తర్వాత"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"దాటవేయి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 4dd0d0f..bc4b79e 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"ส่ง"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"แอปสำหรับการขับขี่ทำงานอยู่"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"แตะเพื่อออกจากแอปสำหรับการขับขี่"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"การปล่อยสัญญาณหรือฮอตสปอตทำงานอยู่"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"แตะเพื่อตั้งค่า"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ปิดใช้การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือแล้ว"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"ติดต่อผู้ดูแลระบบเพื่อขอรายละเอียด"</string>
     <string name="back_button_label" msgid="4078224038025043387">"กลับ"</string>
     <string name="next_button_label" msgid="6040209156399907780">"ถัดไป"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"ข้าม"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index bde4027..b24e95a 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Isumite"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Tumatakbo ang driving app"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Mag-tap para lumabas sa app sa pagmamaneho."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Pagsasama o aktibong hotspot"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"I-tap upang i-set up."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Naka-disable ang pag-tether"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Makipag-ugnayan sa iyong admin para sa mga detalye"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Bumalik"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Susunod"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Laktawan"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 0168ba0..326ace9 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Gönder"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Sürüş uygulaması çalışıyor"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Sürüş uygulamasından çıkmak için dokunun."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Tethering veya hotspot etkin"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Ayarlamak için dokunun."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Tethering devre dışı bırakıldı"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Ayrıntılı bilgi için yöneticinize başvurun"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Geri"</string>
     <string name="next_button_label" msgid="6040209156399907780">"İleri"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Atla"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 32042ef..8007f9e 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1469,10 +1469,6 @@
     <string name="submit" msgid="862795280643405865">"Надіслати"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Працює додаток для автомобілів"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Торкніться, щоб вийти з додатка для автомобілів."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Прив\'язка чи точка дост. активна"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Торкніться, щоб налаштувати."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Використання телефона в режимі модема вимкнено"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Щоб дізнатися більше, зв’яжіться з адміністратором"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Назад"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Далі"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Пропустити"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 1dd8911..312aed7d 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"جمع کرائیں"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"ڈرائیونگ ایپ چل رہی ہے"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"ڈرائیونگ ایپ سے باہر نکلنے کے لئے تھپتھپائيں۔"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"ٹیدرنگ یا ہاٹ اسپاٹ فعال"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"سیٹ اپ کرنے کیلئے تھپتھپائیں۔"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"ٹیدرنگ غیر فعال ہے"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"تفصیلات کے لئے اپنے منتظم سے رابطہ کریں"</string>
     <string name="back_button_label" msgid="4078224038025043387">"واپس جائیں"</string>
     <string name="next_button_label" msgid="6040209156399907780">"اگلا"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"نظر انداز کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 4b7847d..c7987d1 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Yuborish"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Avtomobil ilovasi ishlayapti"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Avtomobil ilovasidan chiqish uchun bosing"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Modem rejimi yoniq"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Sozlash uchun bosing."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Modem rejimi faolsizlantirildi"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Tafsilotlari uchun administratoringizga murojaat qiling"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Orqaga"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Keyingisi"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Tashlab o‘tish"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 971cf34..13c75f6 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Gửi"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Ứng dụng lái xe đang chạy"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Nhấn để thoát khỏi ứng dụng lái xe."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Chức năng điểm truy cập Internet hoặc điểm phát sóng đang hoạt động"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Nhấn để thiết lập."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Đã tắt tính năng chia sẻ kết nối"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Hãy liên hệ với quản trị viên của bạn để biết chi tiết"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Quay lại"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Tiếp theo"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Bỏ qua"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index d7dd8b1..1df2a40 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"提交"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"驾驶应用正在运行"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"点按即可退出驾驶应用。"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"网络共享或热点已启用"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"点按即可进行设置。"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"网络共享已停用"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"请与您的管理员联系以了解详情"</string>
     <string name="back_button_label" msgid="4078224038025043387">"上一步"</string>
     <string name="next_button_label" msgid="6040209156399907780">"下一步"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"跳过"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 1a37844..d4d1f7c 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"提交"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"駕駛應用程式執行中"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"輕按即可退出駕駛應用程式。"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"已啟用網絡共享或熱點"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"輕按即可設定。"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"網絡共享已停用"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"請聯絡您的管理員以瞭解詳情"</string>
     <string name="back_button_label" msgid="4078224038025043387">"返回"</string>
     <string name="next_button_label" msgid="6040209156399907780">"繼續"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"略過"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5e655ac..9997b68 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"提交"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"行車應用程式執行中"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"輕觸即可結束行車應用程式。"</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"網路共用或無線基地台已啟用"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"輕觸即可進行設定。"</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"數據連線已停用"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"詳情請洽你的管理員"</string>
     <string name="back_button_label" msgid="4078224038025043387">"返回"</string>
     <string name="next_button_label" msgid="6040209156399907780">"繼續"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"略過"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 5f8d61e..5838a93 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1429,10 +1429,6 @@
     <string name="submit" msgid="862795280643405865">"Hambisa"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Uhlelo lokusebenza lokushayela luyasebenza"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Thepha ukuze uphume kuhlelo lokusebenza lokushayela."</string>
-    <string name="tethered_notification_title" msgid="2700523927485687353">"Ukusebenzisa njengemodemu noma i-hotspot ephathekayo kuvuliwe"</string>
-    <string name="tethered_notification_message" msgid="6228080755828019453">"Thepha ukuze usethe."</string>
-    <string name="disable_tether_notification_title" msgid="7158047514545848391">"Ukusebenzisa ifoni njengemodemu kukhutshaziwe"</string>
-    <string name="disable_tether_notification_message" msgid="98281313984014775">"Xhumana nomphathi wakho ukuze uthole imininingwane"</string>
     <string name="back_button_label" msgid="4078224038025043387">"Emuva"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Okulandelayo"</string>
     <string name="skip_button_label" msgid="3566599811326688389">"Yeqa"</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7310daf..dcf7379 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3838,18 +3838,6 @@
     <string name="car_mode_disable_notification_title">Driving app is running</string>
     <string name="car_mode_disable_notification_message">Tap to exit driving app.</string>
 
-    <!-- Strings for tethered notification -->
-    <!-- Shown when the device is tethered -->
-    <string name="tethered_notification_title">Tethering or hotspot active</string>
-    <string name="tethered_notification_message">Tap to set up.</string>
-
-    <!-- Strings for tether disabling notification -->
-    <!-- This notification is shown when tethering has been disabled on a user's device.
-    The device is managed by the user's employer. Tethering can't be turned on unless the
-    IT administrator allows it. The noun "admin" is another reference for "IT administrator." -->
-    <string name="disable_tether_notification_title">Tethering is disabled</string>
-    <string name="disable_tether_notification_message">Contact your admin for details</string>
-
     <!--  Strings for possible PreferenceActivity Back/Next buttons -->
     <string name="back_button_label">Back</string>
     <string name="next_button_label">Next</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 130b31f..d15d4d6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1893,9 +1893,6 @@
   <java-symbol type="drawable" name="stat_sys_battery_charge" />
   <java-symbol type="drawable" name="stat_sys_battery_unknown" />
   <java-symbol type="drawable" name="stat_sys_data_usb" />
-  <java-symbol type="drawable" name="stat_sys_tether_bluetooth" />
-  <java-symbol type="drawable" name="stat_sys_tether_general" />
-  <java-symbol type="drawable" name="stat_sys_tether_usb" />
   <java-symbol type="drawable" name="stat_sys_throttled" />
   <java-symbol type="drawable" name="vpn_connected" />
   <java-symbol type="drawable" name="vpn_disconnected" />
@@ -2071,10 +2068,6 @@
   <java-symbol type="string" name="select_keyboard_layout_notification_message" />
   <java-symbol type="string" name="smv_application" />
   <java-symbol type="string" name="smv_process" />
-  <java-symbol type="string" name="tethered_notification_message" />
-  <java-symbol type="string" name="tethered_notification_title" />
-  <java-symbol type="string" name="disable_tether_notification_message" />
-  <java-symbol type="string" name="disable_tether_notification_title" />
   <java-symbol type="string" name="adb_debugging_notification_channel_tv" />
   <java-symbol type="string" name="usb_accessory_notification_title" />
   <java-symbol type="string" name="usb_mtp_notification_title" />
diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
new file mode 100644
index 0000000..613ce90
--- /dev/null
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 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 android.graphics;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import libcore.util.NativeAllocationRegistry;
+
+/**
+ * Shader that calculates pixel output with a program (fragment shader) running on a GPU.
+ * @hide
+ */
+public class RuntimeShader extends Shader {
+
+    private static class NoImagePreloadHolder {
+        public static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                RuntimeShader.class.getClassLoader(), nativeGetFinalizer());
+    }
+
+    private byte[] mUniforms;
+
+    /**
+     * Current native shader factory instance.
+     */
+    private long mNativeInstanceRuntimeShaderFactory;
+
+    /**
+     * Creates a new RuntimeShader.
+     *
+     * @param sksl The text of SKSL program to run on the GPU.
+     * @param uniforms Array of parameters passed by the SKSL shader. Array size depends
+     *                 on number of uniforms declared by sksl.
+     * @param isOpaque True if all pixels have alpha 1.0f.
+     */
+    public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, boolean isOpaque) {
+        this(sksl, uniforms, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
+    }
+
+    private RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, boolean isOpaque,
+            ColorSpace colorSpace) {
+        super(colorSpace);
+        mUniforms = uniforms;
+        mNativeInstanceRuntimeShaderFactory = nativeCreateShaderFactory(sksl, isOpaque);
+        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this,
+                mNativeInstanceRuntimeShaderFactory);
+    }
+
+    /**
+     * Sets new value for shader parameters.
+     *
+     * @param uniforms Array of parameters passed by the SKSL shader. Array size depends
+     *                 on number of uniforms declared by mSksl.
+     */
+    public void updateUniforms(@Nullable byte[] uniforms) {
+        mUniforms = uniforms;
+        discardNativeInstance();
+    }
+
+    @Override
+    long createNativeInstance(long nativeMatrix) {
+        return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms,
+                colorSpace().getNativeInstance());
+    }
+
+    private static native long nativeCreate(long shaderFactory, long matrix, byte[] inputs,
+            long colorSpaceHandle);
+
+    private static native long nativeCreateShaderFactory(String sksl, boolean isOpaque);
+
+    private static native long nativeGetFinalizer();
+}
+
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index f25910b..572fa8c 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -68,6 +68,9 @@
     /** Key prefix for WIFI. */
     public static final String WIFI = "WIFI_";
 
+    /** Key prefix for App Source certificates. */
+    public static final String APP_SOURCE_CERTIFICATE = "FSV_";
+
     /** Key containing suffix of lockdown VPN profile. */
     public static final String LOCKDOWN_VPN = "LOCKDOWN_VPN";
 
@@ -80,6 +83,9 @@
     /** Name of WIFI certificate usage. */
     public static final String CERTIFICATE_USAGE_WIFI = "wifi";
 
+    /** Name of App Source certificate usage. */
+    public static final String CERTIFICATE_USAGE_APP_SOURCE = "appsrc";
+
     /** Data type for public keys. */
     public static final String EXTRA_PUBLIC_KEY = "KEY";
 
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 142078e..9e49826 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -32,9 +32,11 @@
 import static android.os.image.DynamicSystemClient.STATUS_NOT_STARTED;
 import static android.os.image.DynamicSystemClient.STATUS_READY;
 
+import static com.android.dynsystem.InstallationAsyncTask.RESULT_CANCELLED;
 import static com.android.dynsystem.InstallationAsyncTask.RESULT_ERROR_EXCEPTION;
-import static com.android.dynsystem.InstallationAsyncTask.RESULT_ERROR_INVALID_URL;
 import static com.android.dynsystem.InstallationAsyncTask.RESULT_ERROR_IO;
+import static com.android.dynsystem.InstallationAsyncTask.RESULT_ERROR_UNSUPPORTED_FORMAT;
+import static com.android.dynsystem.InstallationAsyncTask.RESULT_ERROR_UNSUPPORTED_URL;
 import static com.android.dynsystem.InstallationAsyncTask.RESULT_OK;
 
 import android.app.Notification;
@@ -66,11 +68,10 @@
  * cancel and confirm commnands.
  */
 public class DynamicSystemInstallationService extends Service
-        implements InstallationAsyncTask.InstallStatusListener {
+        implements InstallationAsyncTask.ProgressListener {
 
     private static final String TAG = "DynSystemInstallationService";
 
-
     // TODO (b/131866826): This is currently for test only. Will move this to System API.
     static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED";
 
@@ -121,9 +122,12 @@
     private DynamicSystemManager mDynSystem;
     private NotificationManager mNM;
 
-    private long mSystemSize;
-    private long mUserdataSize;
-    private long mInstalledSize;
+    private int mNumInstalledPartitions;
+
+    private String mCurrentPartitionName;
+    private long mCurrentPartitionSize;
+    private long mCurrentPartitionInstalledSize;
+
     private boolean mJustCancelledByUser;
 
     // This is for testing only now
@@ -176,8 +180,12 @@
     }
 
     @Override
-    public void onProgressUpdate(long installedSize) {
-        mInstalledSize = installedSize;
+    public void onProgressUpdate(InstallationAsyncTask.Progress progress) {
+        mCurrentPartitionName = progress.mPartitionName;
+        mCurrentPartitionSize = progress.mPartitionSize;
+        mCurrentPartitionInstalledSize = progress.mInstalledSize;
+        mNumInstalledPartitions = progress.mNumInstalledPartitions;
+
         postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null);
     }
 
@@ -197,11 +205,16 @@
         resetTaskAndStop();
 
         switch (result) {
+            case RESULT_CANCELLED:
+                postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED, null);
+                break;
+
             case RESULT_ERROR_IO:
                 postStatus(STATUS_NOT_STARTED, CAUSE_ERROR_IO, detail);
                 break;
 
-            case RESULT_ERROR_INVALID_URL:
+            case RESULT_ERROR_UNSUPPORTED_URL:
+            case RESULT_ERROR_UNSUPPORTED_FORMAT:
                 postStatus(STATUS_NOT_STARTED, CAUSE_ERROR_INVALID_URL, detail);
                 break;
 
@@ -211,12 +224,6 @@
         }
     }
 
-    @Override
-    public void onCancelled() {
-        resetTaskAndStop();
-        postStatus(STATUS_NOT_STARTED, CAUSE_INSTALL_CANCELLED, null);
-    }
-
     private void executeInstallCommand(Intent intent) {
         if (!verifyRequest(intent)) {
             Log.e(TAG, "Verification failed. Did you use VerificationActivity?");
@@ -234,12 +241,13 @@
         }
 
         String url = intent.getDataString();
-        mSystemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0);
-        mUserdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0);
+        long systemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0);
+        long userdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0);
         mEnableWhenCompleted = intent.getBooleanExtra(KEY_ENABLE_WHEN_COMPLETED, false);
 
+        // TODO: better constructor or builder
         mInstallTask = new InstallationAsyncTask(
-                url, mSystemSize, mUserdataSize, this, mDynSystem, this);
+                url, systemSize, userdataSize, this, mDynSystem, this);
 
         mInstallTask.execute();
 
@@ -257,7 +265,7 @@
         mJustCancelledByUser = true;
 
         if (mInstallTask.cancel(false)) {
-            // Will cleanup and post status in onCancelled()
+            // Will cleanup and post status in onResult()
             Log.d(TAG, "Cancel request filed successfully");
         } else {
             Log.e(TAG, "Trying to cancel installation while it's already completed.");
@@ -288,7 +296,7 @@
     private void executeRebootToDynSystemCommand() {
         boolean enabled = false;
 
-        if (mInstallTask != null && mInstallTask.getResult() == RESULT_OK) {
+        if (mInstallTask != null && mInstallTask.isCompleted()) {
             enabled = mInstallTask.commit();
         } else if (isDynamicSystemInstalled()) {
             enabled = mDynSystem.setEnable(true, true);
@@ -380,8 +388,16 @@
             case STATUS_IN_PROGRESS:
                 builder.setContentText(getString(R.string.notification_install_inprogress));
 
-                int max = (int) Math.max((mSystemSize + mUserdataSize) >> 20, 1);
-                int progress = (int) (mInstalledSize >> 20);
+                int max = 1024;
+                int progress = 0;
+
+                int currentMax = max >> (mNumInstalledPartitions + 1);
+                progress = max - currentMax * 2;
+
+                long currentProgress = (mCurrentPartitionInstalledSize >> 20) * currentMax
+                        / Math.max(mCurrentPartitionSize >> 20, 1);
+
+                progress += (int) currentProgress;
 
                 builder.setProgress(max, progress, false);
 
@@ -464,7 +480,8 @@
             throws RemoteException {
         Bundle bundle = new Bundle();
 
-        bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mInstalledSize);
+        // TODO: send more info to the clients
+        bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mCurrentPartitionInstalledSize);
 
         if (detail != null) {
             bundle.putSerializable(DynamicSystemClient.KEY_EXCEPTION_DETAIL,
@@ -492,9 +509,7 @@
                 return STATUS_IN_PROGRESS;
 
             case FINISHED:
-                int result = mInstallTask.getResult();
-
-                if (result == RESULT_OK) {
+                if (mInstallTask.isCompleted()) {
                     return STATUS_READY;
                 } else {
                     throw new IllegalStateException("A failed InstallationTask is not reset");
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index 19ae970..b206a1f 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -17,7 +17,6 @@
 package com.android.dynsystem;
 
 import android.content.Context;
-import android.gsi.GsiProgress;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.MemoryFile;
@@ -27,35 +26,70 @@
 import android.webkit.URLUtil;
 
 import java.io.BufferedInputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
 import java.util.Locale;
 import java.util.zip.GZIPInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
 
-class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
+class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Progress, Throwable> {
 
     private static final String TAG = "InstallationAsyncTask";
 
     private static final int READ_BUFFER_SIZE = 1 << 13;
+    private static final long MIN_PROGRESS_TO_PUBLISH = 1 << 27;
 
-    private class InvalidImageUrlException extends RuntimeException {
-        private InvalidImageUrlException(String message) {
+    private static final List<String> UNSUPPORTED_PARTITIONS =
+            Arrays.asList("vbmeta", "boot", "userdata", "dtbo", "super_empty", "system_other");
+
+    private class UnsupportedUrlException extends RuntimeException {
+        private UnsupportedUrlException(String message) {
             super(message);
         }
     }
 
-    /** Not completed, including being cancelled */
-    static final int NO_RESULT = 0;
+    private class UnsupportedFormatException extends RuntimeException {
+        private UnsupportedFormatException(String message) {
+            super(message);
+        }
+    }
+
+    /** UNSET means the installation is not completed */
+    static final int RESULT_UNSET = 0;
     static final int RESULT_OK = 1;
-    static final int RESULT_ERROR_IO = 2;
-    static final int RESULT_ERROR_INVALID_URL = 3;
+    static final int RESULT_CANCELLED = 2;
+    static final int RESULT_ERROR_IO = 3;
+    static final int RESULT_ERROR_UNSUPPORTED_URL = 4;
+    static final int RESULT_ERROR_UNSUPPORTED_FORMAT = 5;
     static final int RESULT_ERROR_EXCEPTION = 6;
 
-    interface InstallStatusListener {
-        void onProgressUpdate(long installedSize);
+    class Progress {
+        String mPartitionName;
+        long mPartitionSize;
+        long mInstalledSize;
+
+        int mNumInstalledPartitions;
+
+        Progress(String partitionName, long partitionSize, long installedSize,
+                int numInstalled) {
+            mPartitionName = partitionName;
+            mPartitionSize = partitionSize;
+            mInstalledSize = installedSize;
+
+            mNumInstalledPartitions = numInstalled;
+        }
+    }
+
+    interface ProgressListener {
+        void onProgressUpdate(Progress progress);
         void onResult(int resultCode, Throwable detail);
-        void onCancelled();
     }
 
     private final String mUrl;
@@ -63,16 +97,17 @@
     private final long mUserdataSize;
     private final Context mContext;
     private final DynamicSystemManager mDynSystem;
-    private final InstallStatusListener mListener;
+    private final ProgressListener mListener;
     private DynamicSystemManager.Session mInstallationSession;
 
-    private int mResult = NO_RESULT;
+    private boolean mIsZip;
+    private boolean mIsCompleted;
 
     private InputStream mStream;
-
+    private ZipFile mZipFile;
 
     InstallationAsyncTask(String url, long systemSize, long userdataSize, Context context,
-            DynamicSystemManager dynSystem, InstallStatusListener listener) {
+            DynamicSystemManager dynSystem, ProgressListener listener) {
         mUrl = url;
         mSystemSize = systemSize;
         mUserdataSize = userdataSize;
@@ -82,133 +117,292 @@
     }
 
     @Override
-    protected void onPreExecute() {
-        mListener.onProgressUpdate(0);
-    }
-
-    @Override
     protected Throwable doInBackground(String... voids) {
         Log.d(TAG, "Start doInBackground(), URL: " + mUrl);
 
         try {
-            long installedSize = 0;
-            long reportedInstalledSize = 0;
+            // call DynamicSystemManager to cleanup stuff
+            mDynSystem.remove();
 
-            long minStepToReport = (mSystemSize + mUserdataSize) / 100;
+            verifyAndPrepare();
 
-            // init input stream before calling startInstallation(), which takes 90 seconds.
-            initInputStream();
+            mDynSystem.startInstallation();
 
-            Thread thread =
-                    new Thread(
-                            () -> {
-                                mDynSystem.startInstallation();
-                                mDynSystem.createPartition("userdata", mUserdataSize, false);
-                                mInstallationSession =
-                                        mDynSystem.createPartition("system", mSystemSize, true);
-                            });
-
-            thread.start();
-
-            while (thread.isAlive()) {
-                if (isCancelled()) {
-                    boolean aborted = mDynSystem.abort();
-                    Log.d(TAG, "Called DynamicSystemManager.abort(), result = " + aborted);
-                    return null;
-                }
-
-                GsiProgress progress = mDynSystem.getInstallationProgress();
-                installedSize = progress.bytes_processed;
-
-                if (installedSize > reportedInstalledSize + minStepToReport) {
-                    publishProgress(installedSize);
-                    reportedInstalledSize = installedSize;
-                }
-
-                Thread.sleep(10);
+            installUserdata();
+            if (isCancelled()) {
+                mDynSystem.remove();
+                return null;
             }
 
-            if (mInstallationSession == null) {
-                throw new IOException(
-                        "Failed to start installation with requested size: "
-                                + (mSystemSize + mUserdataSize));
+            installImages();
+            if (isCancelled()) {
+                mDynSystem.remove();
+                return null;
             }
 
-            installedSize = mUserdataSize;
-
-            MemoryFile memoryFile = new MemoryFile("dsu", READ_BUFFER_SIZE);
-            byte[] bytes = new byte[READ_BUFFER_SIZE];
-            mInstallationSession.setAshmem(
-                    new ParcelFileDescriptor(memoryFile.getFileDescriptor()), READ_BUFFER_SIZE);
-            int numBytesRead;
-            Log.d(TAG, "Start installation loop");
-            while ((numBytesRead = mStream.read(bytes, 0, READ_BUFFER_SIZE)) != -1) {
-                memoryFile.writeBytes(bytes, 0, 0, numBytesRead);
-                if (isCancelled()) {
-                    break;
-                }
-                if (!mInstallationSession.submitFromAshmem(numBytesRead)) {
-                    throw new IOException("Failed write() to DynamicSystem");
-                }
-
-                installedSize += numBytesRead;
-
-                if (installedSize > reportedInstalledSize + minStepToReport) {
-                    publishProgress(installedSize);
-                    reportedInstalledSize = installedSize;
-                }
-            }
             mDynSystem.finishInstallation();
-            return null;
-
         } catch (Exception e) {
             e.printStackTrace();
+            mDynSystem.remove();
             return e;
         } finally {
             close();
         }
+
+        return null;
+    }
+
+    @Override
+    protected void onPostExecute(Throwable detail) {
+        int result = RESULT_UNSET;
+
+        if (detail == null) {
+            result = RESULT_OK;
+            mIsCompleted = true;
+        } else if (detail instanceof IOException) {
+            result = RESULT_ERROR_IO;
+        } else if (detail instanceof UnsupportedUrlException) {
+            result = RESULT_ERROR_UNSUPPORTED_URL;
+        } else if (detail instanceof UnsupportedFormatException) {
+            result = RESULT_ERROR_UNSUPPORTED_FORMAT;
+        } else {
+            result = RESULT_ERROR_EXCEPTION;
+        }
+
+        Log.d(TAG, "onPostExecute(), URL: " + mUrl + ", result: " + result);
+
+        mListener.onResult(result, detail);
     }
 
     @Override
     protected void onCancelled() {
         Log.d(TAG, "onCancelled(), URL: " + mUrl);
 
-        mListener.onCancelled();
-    }
-
-    @Override
-    protected void onPostExecute(Throwable detail) {
-        if (detail == null) {
-            mResult = RESULT_OK;
-        } else if (detail instanceof IOException) {
-            mResult = RESULT_ERROR_IO;
-        } else if (detail instanceof InvalidImageUrlException) {
-            mResult = RESULT_ERROR_INVALID_URL;
+        if (mDynSystem.abort()) {
+            Log.d(TAG, "Installation aborted");
         } else {
-            mResult = RESULT_ERROR_EXCEPTION;
+            Log.w(TAG, "DynamicSystemManager.abort() returned false");
         }
 
-        Log.d(TAG, "onPostExecute(), URL: " + mUrl + ", result: " + mResult);
-
-        mListener.onResult(mResult, detail);
+        mListener.onResult(RESULT_CANCELLED, null);
     }
 
     @Override
-    protected void onProgressUpdate(Long... values) {
-        long progress = values[0];
+    protected void onProgressUpdate(Progress... values) {
+        Progress progress = values[0];
         mListener.onProgressUpdate(progress);
     }
 
-    private void initInputStream() throws IOException, InvalidImageUrlException {
-        if (URLUtil.isNetworkUrl(mUrl) || URLUtil.isFileUrl(mUrl)) {
-            mStream = new BufferedInputStream(new GZIPInputStream(new URL(mUrl).openStream()));
-        } else if (URLUtil.isContentUrl(mUrl)) {
-            Uri uri = Uri.parse(mUrl);
-            mStream = new BufferedInputStream(new GZIPInputStream(
-                    mContext.getContentResolver().openInputStream(uri)));
+    private void verifyAndPrepare() throws Exception {
+        String extension = mUrl.substring(mUrl.lastIndexOf('.') + 1);
+
+        if ("gz".equals(extension) || "gzip".equals(extension)) {
+            mIsZip = false;
+        } else if ("zip".equals(extension)) {
+            mIsZip = true;
         } else {
-            throw new InvalidImageUrlException(
-                    String.format(Locale.US, "Unsupported file source: %s", mUrl));
+            throw new UnsupportedFormatException(
+                String.format(Locale.US, "Unsupported file format: %s", mUrl));
+        }
+
+        if (URLUtil.isNetworkUrl(mUrl)) {
+            mStream = new URL(mUrl).openStream();
+        } else if (URLUtil.isFileUrl(mUrl)) {
+            if (mIsZip) {
+                mZipFile = new ZipFile(new File(new URL(mUrl).toURI()));
+            } else {
+                mStream = new URL(mUrl).openStream();
+            }
+        } else if (URLUtil.isContentUrl(mUrl)) {
+            mStream = mContext.getContentResolver().openInputStream(Uri.parse(mUrl));
+        } else {
+            throw new UnsupportedUrlException(
+                    String.format(Locale.US, "Unsupported URL: %s", mUrl));
+        }
+    }
+
+    private void installUserdata() throws Exception {
+        Thread thread = new Thread(() -> {
+            mInstallationSession = mDynSystem.createPartition("userdata", mUserdataSize, false);
+        });
+
+        Log.d(TAG, "Creating partition: userdata");
+        thread.start();
+
+        long installedSize = 0;
+        Progress progress = new Progress("userdata", mUserdataSize, installedSize, 0);
+
+        while (thread.isAlive()) {
+            if (isCancelled()) {
+                return;
+            }
+
+            installedSize = mDynSystem.getInstallationProgress().bytes_processed;
+
+            if (installedSize > progress.mInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
+                progress.mInstalledSize = installedSize;
+                publishProgress(progress);
+            }
+
+            Thread.sleep(10);
+        }
+
+        if (mInstallationSession == null) {
+            throw new IOException(
+                    "Failed to start installation with requested size: " + mUserdataSize);
+        }
+    }
+
+    private void installImages() throws IOException, InterruptedException {
+        if (mStream != null) {
+            if (mIsZip) {
+                installStreamingZipUpdate();
+            } else {
+                installStreamingGzUpdate();
+            }
+        } else {
+            installLocalZipUpdate();
+        }
+    }
+
+    private void installStreamingGzUpdate() throws IOException, InterruptedException {
+        Log.d(TAG, "To install a streaming GZ update");
+        installImage("system", mSystemSize, new GZIPInputStream(mStream), 1);
+    }
+
+    private void installStreamingZipUpdate() throws IOException, InterruptedException {
+        Log.d(TAG, "To install a streaming ZIP update");
+
+        ZipInputStream zis = new ZipInputStream(mStream);
+        ZipEntry zipEntry = null;
+
+        int numInstalledPartitions = 1;
+
+        while ((zipEntry = zis.getNextEntry()) != null) {
+            if (installImageFromAnEntry(zipEntry, zis, numInstalledPartitions)) {
+                numInstalledPartitions++;
+            }
+
+            if (isCancelled()) {
+                break;
+            }
+        }
+    }
+
+    private void installLocalZipUpdate() throws IOException, InterruptedException {
+        Log.d(TAG, "To install a local ZIP update");
+
+        Enumeration<? extends ZipEntry> entries = mZipFile.entries();
+        int numInstalledPartitions = 1;
+
+        while (entries.hasMoreElements()) {
+            ZipEntry entry = entries.nextElement();
+            if (installImageFromAnEntry(
+                    entry, mZipFile.getInputStream(entry), numInstalledPartitions)) {
+                numInstalledPartitions++;
+            }
+
+            if (isCancelled()) {
+                break;
+            }
+        }
+    }
+
+    private boolean installImageFromAnEntry(ZipEntry entry, InputStream is,
+            int numInstalledPartitions) throws IOException, InterruptedException {
+        String name = entry.getName();
+
+        Log.d(TAG, "ZipEntry: " + name);
+
+        if (!name.endsWith(".img")) {
+            return false;
+        }
+
+        String partitionName = name.substring(0, name.length() - 4);
+
+        if (UNSUPPORTED_PARTITIONS.contains(partitionName)) {
+            Log.d(TAG, name + " installation is not supported, skip it.");
+            return false;
+        }
+
+        long uncompressedSize = entry.getSize();
+
+        installImage(partitionName, uncompressedSize, is, numInstalledPartitions);
+
+        return true;
+    }
+
+    private void installImage(String partitionName, long uncompressedSize, InputStream is,
+            int numInstalledPartitions) throws IOException, InterruptedException {
+
+        SparseInputStream sis = new SparseInputStream(new BufferedInputStream(is));
+
+        long unsparseSize = sis.getUnsparseSize();
+
+        final long partitionSize;
+
+        if (unsparseSize != -1) {
+            partitionSize = unsparseSize;
+            Log.d(TAG, partitionName + " is sparse, raw size = " + unsparseSize);
+        } else if (uncompressedSize != -1) {
+            partitionSize = uncompressedSize;
+            Log.d(TAG, partitionName + " is already unsparse, raw size = " + uncompressedSize);
+        } else {
+            throw new IOException("Cannot get raw size for " + partitionName);
+        }
+
+        Thread thread = new Thread(() -> {
+            mInstallationSession =
+                    mDynSystem.createPartition(partitionName, partitionSize, true);
+        });
+
+        Log.d(TAG, "Start creating partition: " + partitionName);
+        thread.start();
+
+        while (thread.isAlive()) {
+            if (isCancelled()) {
+                return;
+            }
+
+            Thread.sleep(10);
+        }
+
+        if (mInstallationSession == null) {
+            throw new IOException(
+                    "Failed to start installation with requested size: " + partitionSize);
+        }
+
+        Log.d(TAG, "Start installing: " + partitionName);
+
+        MemoryFile memoryFile = new MemoryFile("dsu_" + partitionName, READ_BUFFER_SIZE);
+        ParcelFileDescriptor pfd = new ParcelFileDescriptor(memoryFile.getFileDescriptor());
+
+        mInstallationSession.setAshmem(pfd, READ_BUFFER_SIZE);
+
+        long installedSize = 0;
+        Progress progress = new Progress(
+                partitionName, partitionSize, installedSize, numInstalledPartitions);
+
+        byte[] bytes = new byte[READ_BUFFER_SIZE];
+        int numBytesRead;
+
+        while ((numBytesRead = sis.read(bytes, 0, READ_BUFFER_SIZE)) != -1) {
+            if (isCancelled()) {
+                return;
+            }
+
+            memoryFile.writeBytes(bytes, 0, 0, numBytesRead);
+
+            if (!mInstallationSession.submitFromAshmem(numBytesRead)) {
+                throw new IOException("Failed write() to DynamicSystem");
+            }
+
+            installedSize += numBytesRead;
+
+            if (installedSize > progress.mInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
+                progress.mInstalledSize = installedSize;
+                publishProgress(progress);
+            }
         }
     }
 
@@ -218,20 +412,20 @@
                 mStream.close();
                 mStream = null;
             }
+            if (mZipFile != null) {
+                mZipFile.close();
+                mZipFile = null;
+            }
         } catch (IOException e) {
             // ignore
         }
     }
 
-    int getResult() {
-        return mResult;
+    boolean isCompleted() {
+        return mIsCompleted;
     }
 
     boolean commit() {
-        if (mInstallationSession == null) {
-            return false;
-        }
-
-        return mInstallationSession.commit();
+        return mDynSystem.setEnable(true, true);
     }
 }
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
new file mode 100644
index 0000000..72230b4
--- /dev/null
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
@@ -0,0 +1,199 @@
+/*
+ * 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.dynsystem;
+
+import static java.lang.Math.min;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+/**
+ * SparseInputStream read from upstream and detects the data format. If the upstream is a valid
+ * sparse data, it will unsparse it on the fly. Otherwise, it just passthrough as is.
+ */
+public class SparseInputStream extends InputStream {
+    static final int FILE_HDR_SIZE = 28;
+    static final int CHUNK_HDR_SIZE = 12;
+
+    /**
+     * This class represents a chunk in the Android sparse image.
+     *
+     * @see system/core/libsparse/sparse_format.h
+     */
+    private class SparseChunk {
+        static final short RAW = (short) 0xCAC1;
+        static final short FILL = (short) 0xCAC2;
+        static final short DONTCARE = (short) 0xCAC3;
+        public short mChunkType;
+        public int mChunkSize;
+        public int mTotalSize;
+        public byte[] fill;
+        public String toString() {
+            return String.format(
+                    "type: %x, chunk_size: %d, total_size: %d", mChunkType, mChunkSize, mTotalSize);
+        }
+    }
+
+    private byte[] readFull(InputStream in, int size) throws IOException {
+        byte[] buf = new byte[size];
+        for (int done = 0, n = 0; done < size; done += n) {
+            if ((n = in.read(buf, done, size - done)) < 0) {
+                throw new IOException("Failed to readFull");
+            }
+        }
+        return buf;
+    }
+
+    private ByteBuffer readBuffer(InputStream in, int size) throws IOException {
+        return ByteBuffer.wrap(readFull(in, size)).order(ByteOrder.LITTLE_ENDIAN);
+    }
+
+    private SparseChunk readChunk(InputStream in) throws IOException {
+        SparseChunk chunk = new SparseChunk();
+        ByteBuffer buf = readBuffer(in, CHUNK_HDR_SIZE);
+        chunk.mChunkType = buf.getShort();
+        buf.getShort();
+        chunk.mChunkSize = buf.getInt();
+        chunk.mTotalSize = buf.getInt();
+        return chunk;
+    }
+
+    private BufferedInputStream mIn;
+    private boolean mIsSparse;
+    private long mBlockSize;
+    private long mTotalBlocks;
+    private long mTotalChunks;
+    private SparseChunk mCur;
+    private long mLeft;
+    private int mCurChunks;
+
+    public SparseInputStream(BufferedInputStream in) throws IOException {
+        mIn = in;
+        in.mark(FILE_HDR_SIZE * 2);
+        ByteBuffer buf = readBuffer(mIn, FILE_HDR_SIZE);
+        mIsSparse = (buf.getInt() == 0xed26ff3a);
+        if (!mIsSparse) {
+            mIn.reset();
+            return;
+        }
+        int major = buf.getShort();
+        int minor = buf.getShort();
+
+        if (major > 0x1 || minor > 0x0) {
+            throw new IOException("Unsupported sparse version: " + major + "." + minor);
+        }
+
+        if (buf.getShort() != FILE_HDR_SIZE) {
+            throw new IOException("Illegal file header size");
+        }
+        if (buf.getShort() != CHUNK_HDR_SIZE) {
+            throw new IOException("Illegal chunk header size");
+        }
+        mBlockSize = buf.getInt();
+        if ((mBlockSize & 0x3) != 0) {
+            throw new IOException("Illegal block size, must be a multiple of 4");
+        }
+        mTotalBlocks = buf.getInt();
+        mTotalChunks = buf.getInt();
+        mLeft = mCurChunks = 0;
+    }
+
+    /**
+     * Check if it needs to open a new chunk.
+     *
+     * @return true if it's EOF
+     */
+    private boolean prepareChunk() throws IOException {
+        if (mCur == null || mLeft <= 0) {
+            if (++mCurChunks > mTotalChunks) return true;
+            mCur = readChunk(mIn);
+            if (mCur.mChunkType == SparseChunk.FILL) {
+                mCur.fill = readFull(mIn, 4);
+            }
+            mLeft = mCur.mChunkSize * mBlockSize;
+        }
+        return mLeft == 0;
+    }
+
+    /**
+     * It overrides the InputStream.read(byte[] buf)
+     */
+    public int read(byte[] buf) throws IOException {
+        if (!mIsSparse) {
+            return mIn.read(buf);
+        }
+        if (prepareChunk()) return -1;
+        int n = -1;
+        switch (mCur.mChunkType) {
+            case SparseChunk.RAW:
+                n = mIn.read(buf, 0, (int) min(mLeft, buf.length));
+                mLeft -= n;
+                return n;
+            case SparseChunk.DONTCARE:
+                n = (int) min(mLeft, buf.length);
+                Arrays.fill(buf, 0, n - 1, (byte) 0);
+                mLeft -= n;
+                return n;
+            case SparseChunk.FILL:
+                // The FILL type is rarely used, so use a simple implmentation.
+                return super.read(buf);
+            default:
+                throw new IOException("Unsupported Chunk:" + mCur.toString());
+        }
+    }
+
+    /**
+     * It overrides the InputStream.read()
+     */
+    public int read() throws IOException {
+        if (!mIsSparse) {
+            return mIn.read();
+        }
+        if (prepareChunk()) return -1;
+        int ret = -1;
+        switch (mCur.mChunkType) {
+            case SparseChunk.RAW:
+                ret = mIn.read();
+                break;
+            case SparseChunk.DONTCARE:
+                ret = 0;
+                break;
+            case SparseChunk.FILL:
+                ret = mCur.fill[(4 - ((int) mLeft & 0x3)) & 0x3];
+                break;
+            default:
+                throw new IOException("Unsupported Chunk:" + mCur.toString());
+        }
+        mLeft--;
+        return ret;
+    }
+
+    /**
+     * Get the unsparse size
+     * @return -1 if unknown
+     */
+    public long getUnsparseSize() {
+        if (!mIsSparse) {
+            return -1;
+        }
+        return mBlockSize * mTotalBlocks;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
index 5ac788e..3b41fa9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
@@ -32,7 +32,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.DrawableWrapper;
 import android.os.Handler;
-import android.telephony.SignalStrength;
+import android.telephony.CellSignalStrength;
 import android.util.LayoutDirection;
 import android.util.PathParser;
 
@@ -145,7 +145,7 @@
 
     private int unpackLevel(int packedState) {
         int numBins = (packedState & NUM_LEVEL_MASK) >> NUM_LEVEL_SHIFT;
-        int levelOffset = numBins == (SignalStrength.NUM_SIGNAL_STRENGTH_BINS + 1) ? 10 : 0;
+        int levelOffset = numBins == (CellSignalStrength.getNumSignalStrengthLevels() + 1) ? 10 : 0;
         int level = (packedState & LEVEL_MASK);
         return level + levelOffset;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index f14def1..653c8ad 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -328,7 +328,6 @@
             boolean enabled, int rowId, Uri conditionId) {
         if (tag.lines == null) {
             tag.lines = row.findViewById(android.R.id.content);
-            tag.lines.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
         }
         if (tag.line1 == null) {
             tag.line1 = (TextView) row.findViewById(android.R.id.text1);
@@ -364,6 +363,7 @@
             @Override
             public void onClick(View v) {
                 onClickTimeButton(row, tag, false /*down*/, rowId);
+                tag.lines.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
             }
         });
 
@@ -373,6 +373,7 @@
             @Override
             public void onClick(View v) {
                 onClickTimeButton(row, tag, true /*up*/, rowId);
+                tag.lines.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
             }
         });
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
index 66ee802..01a5789 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -234,6 +234,7 @@
             @Override
             public void onClick(View v) {
                 onClickTimeButton(row, tag, false /*down*/, rowIndex);
+                tag.lines.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
             }
         });
 
@@ -243,6 +244,7 @@
             @Override
             public void onClick(View v) {
                 onClickTimeButton(row, tag, true /*up*/, rowIndex);
+                tag.lines.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
             }
         });
 
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 7d06e6c..7b1c382 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -120,7 +120,7 @@
     private OsuProvider createOsuProvider() {
         Map<String, String> friendlyNames = new HashMap<>();
         friendlyNames.put("en", OSU_FRIENDLY_NAME);
-        return new OsuProvider((WifiSsid) null, friendlyNames, null, null, null, null, null);
+        return new OsuProvider((WifiSsid) null, friendlyNames, null, null, null, null);
     }
 
     @Before
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 94fbc54..81cf118 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -336,7 +336,7 @@
     private static OsuProvider buildOsuProvider(String friendlyName) {
         Map<String, String> friendlyNames = new HashMap<>();
         friendlyNames.put("en", friendlyName);
-        return new OsuProvider((WifiSsid) null, friendlyNames, null, null, null, null, null);
+        return new OsuProvider((WifiSsid) null, friendlyNames, null, null, null, null);
     }
 
     private WifiTracker createTrackerWithImmediateBroadcastsAndInjectInitialScanResults(
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 05246a4..21b3ba3 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -39,7 +39,6 @@
     <bool name="def_bluetooth_on">true</bool>
     <bool name="def_wifi_display_on">false</bool>
     <bool name="def_install_non_market_apps">false</bool>
-    <bool name="def_package_verifier_enable">true</bool>
     <!-- 0 == off, 3 == on -->
     <integer name="def_location_mode">3</integer>
     <bool name="assisted_gps_enabled">true</bool>
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/AccessibilityShortcutTargetListValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/AccessibilityShortcutTargetListValidator.java
new file mode 100644
index 0000000..5f3d7f1
--- /dev/null
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/AccessibilityShortcutTargetListValidator.java
@@ -0,0 +1,46 @@
+/*
+ * 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 android.provider.settings.validators;
+
+import static android.provider.settings.validators.SettingsValidators.COMPONENT_NAME_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
+
+import android.text.TextUtils;
+
+/**
+ * Ensure a restored value is a string in the format the accessibility shortcut system handles
+ *
+ * @hide
+ */
+public final class AccessibilityShortcutTargetListValidator extends ListValidator {
+    public AccessibilityShortcutTargetListValidator() {
+        super(":");
+    }
+
+    @Override
+    protected boolean isEntryValid(String entry) {
+        return !TextUtils.isEmpty(entry);
+    }
+
+    @Override
+    protected boolean isItemValid(String item) {
+        if (TextUtils.isEmpty(item)) {
+            return false;
+        }
+        return (COMPONENT_NAME_VALIDATOR.validate(item) || PACKAGE_NAME_VALIDATOR.validate(item));
+    }
+}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/ListValidator.java b/packages/SettingsProvider/src/android/provider/settings/validators/ListValidator.java
index a6001d2..104fa11 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/ListValidator.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/ListValidator.java
@@ -35,7 +35,7 @@
         if (!isEntryValid(value)) {
             return false;
         }
-        String[] items = value.split(",");
+        String[] items = value.split(mListSplitRegex);
         for (String item : items) {
             if (!isItemValid(item)) {
                 return false;
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 9460d27f..090af98 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -16,6 +16,7 @@
 
 package android.provider.settings.validators;
 
+import static android.provider.settings.validators.SettingsValidators.ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
 import static android.provider.settings.validators.SettingsValidators.COLON_SEPARATED_COMPONENT_LIST_VALIDATOR;
@@ -71,10 +72,13 @@
         VALIDATORS.put(Secure.TOUCH_EXPLORATION_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ACCESSIBILITY_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(
-                Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, NULLABLE_COMPONENT_NAME_VALIDATOR);
+                Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+                ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
         // technically either ComponentName or class name, but there's proper value
         // validation at callsites, so allow any non-null string
-        VALIDATORS.put(Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, value -> value != null);
+        VALIDATORS.put(
+                Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
+                ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
         VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
index 224042c..71c7544 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
@@ -204,4 +204,7 @@
             new InclusiveIntegerRangeValidator(0, 100);
 
     static final Validator VIBRATION_INTENSITY_VALIDATOR = new InclusiveIntegerRangeValidator(0, 3);
+
+    static final Validator ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR =
+            new AccessibilityShortcutTargetListValidator();
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 0c4db49..2027345 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1191,19 +1191,7 @@
         }
 
         if (upgradeVersion == 81) {
-            // Add package verification setting
-            db.beginTransaction();
-            SQLiteStatement stmt = null;
-            try {
-                stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
-                        + " VALUES(?,?);");
-                loadBooleanSetting(stmt, Settings.Global.PACKAGE_VERIFIER_ENABLE,
-                        R.bool.def_package_verifier_enable);
-                db.setTransactionSuccessful();
-            } finally {
-                db.endTransaction();
-                if (stmt != null) stmt.close();
-            }
+            // package_verifier_enable has been removed
             upgradeVersion = 82;
         }
 
@@ -1305,7 +1293,6 @@
                 db.beginTransaction();
                 try {
                     String[] settingsToMove = {
-                            Settings.Global.PACKAGE_VERIFIER_ENABLE,
                             Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
                             Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE
                     };
@@ -2470,9 +2457,6 @@
             loadDefaultAnimationSettings(stmt);
 
             // --- Previously in 'secure'
-            loadBooleanSetting(stmt, Settings.Global.PACKAGE_VERIFIER_ENABLE,
-                    R.bool.def_package_verifier_enable);
-
             loadBooleanSetting(stmt, Settings.Global.WIFI_ON,
                     R.bool.def_wifi_on);
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 33e0fd2..0a2dd38 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1162,9 +1162,6 @@
 
         final long pkgVerifierToken = p.start(GlobalSettingsProto.PACKAGE_VERIFIER);
         dumpSetting(s, p,
-                Settings.Global.PACKAGE_VERIFIER_ENABLE,
-                GlobalSettingsProto.PackageVerifier.ENABLED);
-        dumpSetting(s, p,
                 Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
                 GlobalSettingsProto.PackageVerifier.TIMEOUT);
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 0959de9..93a1407 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -967,11 +967,6 @@
                     final long identity = Binder.clearCallingIdentity();
                     try {
                         synchronized (mLock) {
-                            Setting enable = getGlobalSetting(
-                                    Settings.Global.PACKAGE_VERIFIER_ENABLE);
-                            String enableValue = enable != null ? enable.getValue() : null;
-                            updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_ENABLE,
-                                    enableValue, null, true, userId, true);
                             Setting include = getGlobalSetting(
                                     Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB);
                             String includeValue = include != null ? include.getValue() : null;
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index eefba5d..540726b 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -387,7 +387,6 @@
                     Settings.Global.OVERLAY_DISPLAY_DEVICES,
                     Settings.Global.PAC_CHANGE_DELAY,
                     Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
-                    Settings.Global.PACKAGE_VERIFIER_ENABLE,
                     Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
                     Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE,
                     Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
diff --git a/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java b/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java
index a3b0835..bb9e6f6 100644
--- a/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java
@@ -297,6 +297,18 @@
     }
 
     @Test
+    public void testAccessibilityShortcutTargetValidator() {
+        assertTrue(SettingsValidators.ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR.validate(
+                "com.google.android/.AccessibilityShortcutTarget"));
+        assertTrue(SettingsValidators.ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR.validate(
+                "com.google.android"));
+        assertTrue(SettingsValidators.ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR.validate(
+                "com.google.android/.AccessibilityShortcutTarget:com.google.android"));
+        assertFalse(SettingsValidators.ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR.validate(
+                "com.google.android/.AccessibilityShortcutTarget:com.google.@android"));
+    }
+
+    @Test
     public void ensureAllBackedUpGlobalSettingsHaveValidators() {
         String offenders = getOffenders(concat(GlobalSettings.SETTINGS_TO_BACKUP,
                 Settings.Global.LEGACY_RESTORE_SETTINGS), GlobalSettingsValidators.VALIDATORS);
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 281406f..26ec572 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -15,6 +15,9 @@
             "include-filter": "android.platform.test.scenario.notification"
         },
         {
+            "include-annotation": "android.platform.test.scenario.annotation.Scenario"
+        },
+        {
             "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 1bfc4c0..b90a371 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -24,7 +24,25 @@
     android:outlineProvider="none"
     android:elevation="5dp" > <!-- Put it above the status bar header -->
 
-    <include layout="@layout/keyguard_indication_area_overlay" />
+    <LinearLayout
+        android:id="@+id/keyguard_indication_area"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
+        android:layout_gravity="bottom|center_horizontal"
+        android:orientation="vertical">
+
+        <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
+            android:id="@+id/keyguard_indication_text"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:paddingStart="@dimen/keyguard_indication_text_padding"
+            android:paddingEnd="@dimen/keyguard_indication_text_padding"
+            android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
+            android:accessibilityLiveRegion="polite"/>
+
+    </LinearLayout>
 
     <FrameLayout
         android:id="@+id/preview_container"
diff --git a/packages/SystemUI/res/layout/keyguard_indication_area_overlay.xml b/packages/SystemUI/res/layout/keyguard_indication_area_overlay.xml
deleted file mode 100644
index cc30a68..0000000
--- a/packages/SystemUI/res/layout/keyguard_indication_area_overlay.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/keyguard_indication_area"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
-    android:layout_gravity="bottom|center_horizontal"
-    android:orientation="vertical">
-
-  <include layout="@layout/keyguard_indication_text_view" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_indication_text_view.xml b/packages/SystemUI/res/layout/keyguard_indication_text_view.xml
deleted file mode 100644
index 9376b1f..0000000
--- a/packages/SystemUI/res/layout/keyguard_indication_text_view.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
-        android:id="@+id/keyguard_indication_text"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:paddingStart="@dimen/keyguard_indication_text_padding"
-        android:paddingEnd="@dimen/keyguard_indication_text_padding"
-        android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
-        android:accessibilityLiveRegion="polite"/>
-</merge>
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 57dcbf2..4103d71 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -26,6 +26,7 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
 import android.os.Looper;
+import android.telephony.CellSignalStrength;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionInfo;
@@ -180,7 +181,7 @@
 
     @Test
     public void testCdmaSignalRoaming() {
-        for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        for (int testStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
                 testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
             setupDefaultSignal();
             setCdma();
@@ -203,7 +204,7 @@
 
     @Test
     public void testQsSignalStrength() {
-        for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        for (int testStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
                 testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
             setupDefaultSignal();
             setLevel(testStrength);
@@ -216,7 +217,7 @@
 
     @Test
     public void testCdmaQsSignalStrength() {
-        for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        for (int testStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
                 testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
             setupDefaultSignal();
             setCdma();
diff --git a/core/res/res/drawable-hdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-hdpi/stat_sys_tether_bluetooth.png
similarity index 100%
rename from core/res/res/drawable-hdpi/stat_sys_tether_bluetooth.png
rename to packages/Tethering/res/drawable-hdpi/stat_sys_tether_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-hdpi/stat_sys_tether_general.png
similarity index 100%
rename from core/res/res/drawable-hdpi/stat_sys_tether_general.png
rename to packages/Tethering/res/drawable-hdpi/stat_sys_tether_general.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-hdpi/stat_sys_tether_usb.png
similarity index 100%
rename from core/res/res/drawable-hdpi/stat_sys_tether_usb.png
rename to packages/Tethering/res/drawable-hdpi/stat_sys_tether_usb.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-ldpi/stat_sys_tether_bluetooth.png
similarity index 100%
rename from core/res/res/drawable-ldpi/stat_sys_tether_bluetooth.png
rename to packages/Tethering/res/drawable-ldpi/stat_sys_tether_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-ldpi/stat_sys_tether_general.png
similarity index 100%
rename from core/res/res/drawable-ldpi/stat_sys_tether_general.png
rename to packages/Tethering/res/drawable-ldpi/stat_sys_tether_general.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-ldpi/stat_sys_tether_usb.png
similarity index 100%
rename from core/res/res/drawable-ldpi/stat_sys_tether_usb.png
rename to packages/Tethering/res/drawable-ldpi/stat_sys_tether_usb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-mdpi/stat_sys_tether_bluetooth.png
similarity index 100%
rename from core/res/res/drawable-mdpi/stat_sys_tether_bluetooth.png
rename to packages/Tethering/res/drawable-mdpi/stat_sys_tether_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-mdpi/stat_sys_tether_general.png
similarity index 100%
rename from core/res/res/drawable-mdpi/stat_sys_tether_general.png
rename to packages/Tethering/res/drawable-mdpi/stat_sys_tether_general.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-mdpi/stat_sys_tether_usb.png
similarity index 100%
rename from core/res/res/drawable-mdpi/stat_sys_tether_usb.png
rename to packages/Tethering/res/drawable-mdpi/stat_sys_tether_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_bluetooth.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/stat_sys_tether_bluetooth.png
rename to packages/Tethering/res/drawable-xhdpi/stat_sys_tether_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_general.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/stat_sys_tether_general.png
rename to packages/Tethering/res/drawable-xhdpi/stat_sys_tether_general.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-xhdpi/stat_sys_tether_usb.png
similarity index 100%
rename from core/res/res/drawable-xhdpi/stat_sys_tether_usb.png
rename to packages/Tethering/res/drawable-xhdpi/stat_sys_tether_usb.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png b/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png
rename to packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_tether_general.png b/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_general.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/stat_sys_tether_general.png
rename to packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_general.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_tether_usb.png b/packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_usb.png
similarity index 100%
rename from core/res/res/drawable-xxhdpi/stat_sys_tether_usb.png
rename to packages/Tethering/res/drawable-xxhdpi/stat_sys_tether_usb.png
Binary files differ
diff --git a/packages/Tethering/res/values-af/strings.xml b/packages/Tethering/res/values-af/strings.xml
new file mode 100644
index 0000000..1258805
--- /dev/null
+++ b/packages/Tethering/res/values-af/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Verbinding of Wi-Fi-warmkol aktief"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tik om op te stel."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Verbinding is gedeaktiveer"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Kontak jou administrateur vir besonderhede"</string>
+</resources>
diff --git a/packages/Tethering/res/values-am/strings.xml b/packages/Tethering/res/values-am/strings.xml
new file mode 100644
index 0000000..9c36192
--- /dev/null
+++ b/packages/Tethering/res/values-am/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"መሰካት ወይም ገባሪ ድረስ ነጥብ"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"ለማዋቀር መታ ያድርጉ።"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"እንደ ሞደም መሰካት ተሰናክሏል"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"ለዝርዝሮች የእርስዎን አስተዳዳሪ ያነጋግሩ"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ar/strings.xml b/packages/Tethering/res/values-ar/strings.xml
new file mode 100644
index 0000000..9f84ce4
--- /dev/null
+++ b/packages/Tethering/res/values-ar/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"النطاق أو نقطة الاتصال نشطة"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"انقر للإعداد."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"تم إيقاف التوصيل"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"اتصل بالمشرف للحصول على التفاصيل"</string>
+</resources>
diff --git a/packages/Tethering/res/values-as/strings.xml b/packages/Tethering/res/values-as/strings.xml
new file mode 100644
index 0000000..8855822
--- /dev/null
+++ b/packages/Tethering/res/values-as/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"টেডাৰিং বা হটস্প\'ট সক্ৰিয় অৱস্থাত আছে"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"ছেট আপ কৰিবলৈ টিপক।"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"টেডাৰিং অক্ষম কৰি থোৱা হৈছে"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"সবিশেষ জানিবলৈ আপোনাৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক"</string>
+</resources>
diff --git a/packages/Tethering/res/values-az/strings.xml b/packages/Tethering/res/values-az/strings.xml
new file mode 100644
index 0000000..eba50eb
--- /dev/null
+++ b/packages/Tethering/res/values-az/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tezerinq və ya hotspot aktivdir"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Quraşdırmaq üçün tıklayın."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Birləşmə deaktivdir"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Məlumat üçün adminlə əlaqə saxlayın"</string>
+</resources>
diff --git a/packages/Tethering/res/values-b+sr+Latn/strings.xml b/packages/Tethering/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..5b0e488
--- /dev/null
+++ b/packages/Tethering/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Aktivno povezivanje sa internetom preko mobilnog uređaja ili hotspot"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Dodirnite da biste podesili."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Privezivanje je onemogućeno"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Potražite detalje od administratora"</string>
+</resources>
diff --git a/packages/Tethering/res/values-be/strings.xml b/packages/Tethering/res/values-be/strings.xml
new file mode 100644
index 0000000..5966c71
--- /dev/null
+++ b/packages/Tethering/res/values-be/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"USB-мадэм або хот-спот Wi-Fi актыўныя"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Дакраніцеся, каб наладзіць."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Рэжым мадэма адключаны"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Звярніцеся да адміністратара па падрабязную інфармацыю"</string>
+</resources>
diff --git a/packages/Tethering/res/values-bg/strings.xml b/packages/Tethering/res/values-bg/strings.xml
new file mode 100644
index 0000000..ed58d73
--- /dev/null
+++ b/packages/Tethering/res/values-bg/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Има активна споделена връзка или безжична точка за достъп"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Докоснете, за да настроите."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Функцията за тетъринг е деактивирана"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Свържете се с администратора си за подробности"</string>
+</resources>
diff --git a/packages/Tethering/res/values-bn/strings.xml b/packages/Tethering/res/values-bn/strings.xml
new file mode 100644
index 0000000..8d9880a
--- /dev/null
+++ b/packages/Tethering/res/values-bn/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"টিথারিং বা হটস্পট সক্রিয় আছে"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"সেট-আপ করার জন্য আলতো চাপুন৷"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"টিথারিং অক্ষম করা আছে"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"বিশদ বিবরণের জন্য প্রশাসকের সাথে যোগাযোগ করুন"</string>
+</resources>
diff --git a/packages/Tethering/res/values-bs/strings.xml b/packages/Tethering/res/values-bs/strings.xml
new file mode 100644
index 0000000..2361b9d
--- /dev/null
+++ b/packages/Tethering/res/values-bs/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Uređaj dijeli vezu ili djeluje kao pristupna tačka"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Dodirnite za postavke"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Povezivanje putem mobitela je onemogućeno"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Kontaktirajte svog administratora za dodatne detalje"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ca/strings.xml b/packages/Tethering/res/values-ca/strings.xml
new file mode 100644
index 0000000..6752b51
--- /dev/null
+++ b/packages/Tethering/res/values-ca/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Compartició de xarxa o punt d\'accés Wi-Fi activat"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Toca per configurar."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"La compartició de xarxa està desactivada"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Contacta amb el teu administrador per obtenir més informació"</string>
+</resources>
diff --git a/packages/Tethering/res/values-cs/strings.xml b/packages/Tethering/res/values-cs/strings.xml
new file mode 100644
index 0000000..5fdd53a
--- /dev/null
+++ b/packages/Tethering/res/values-cs/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Sdílené připojení nebo hotspot je aktivní."</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Klepnutím zahájíte nastavení."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering je zakázán"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"O podrobnosti požádejte administrátora"</string>
+</resources>
diff --git a/packages/Tethering/res/values-da/strings.xml b/packages/Tethering/res/values-da/strings.xml
new file mode 100644
index 0000000..2775dfa
--- /dev/null
+++ b/packages/Tethering/res/values-da/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Netdeling eller hotspot er aktivt"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tryk for at konfigurere"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Netdeling er deaktiveret"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Kontakt din administrator for at få oplysninger"</string>
+</resources>
diff --git a/packages/Tethering/res/values-de/strings.xml b/packages/Tethering/res/values-de/strings.xml
new file mode 100644
index 0000000..9046cd5
--- /dev/null
+++ b/packages/Tethering/res/values-de/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering oder Hotspot aktiv"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Zum Einrichten tippen."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering ist deaktiviert"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Bitte wende dich für weitere Informationen an den Administrator"</string>
+</resources>
diff --git a/packages/Tethering/res/values-el/strings.xml b/packages/Tethering/res/values-el/strings.xml
new file mode 100644
index 0000000..3b9f537
--- /dev/null
+++ b/packages/Tethering/res/values-el/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Πρόσδεση ή σύνδεση σημείου πρόσβασης ενεργή"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Πατήστε για ρύθμιση."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Η σύνδεση είναι απενεργοποιημένη"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Επικοινωνήστε με τον διαχειριστή σας για λεπτομέρειες"</string>
+</resources>
diff --git a/packages/Tethering/res/values-en-rAU/strings.xml b/packages/Tethering/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..56b88a5
--- /dev/null
+++ b/packages/Tethering/res/values-en-rAU/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering or hotspot active"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tap to set up."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering is disabled"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Contact your admin for details"</string>
+</resources>
diff --git a/packages/Tethering/res/values-en-rCA/strings.xml b/packages/Tethering/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..56b88a5
--- /dev/null
+++ b/packages/Tethering/res/values-en-rCA/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering or hotspot active"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tap to set up."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering is disabled"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Contact your admin for details"</string>
+</resources>
diff --git a/packages/Tethering/res/values-en-rGB/strings.xml b/packages/Tethering/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..56b88a5
--- /dev/null
+++ b/packages/Tethering/res/values-en-rGB/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering or hotspot active"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tap to set up."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering is disabled"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Contact your admin for details"</string>
+</resources>
diff --git a/packages/Tethering/res/values-en-rIN/strings.xml b/packages/Tethering/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..56b88a5
--- /dev/null
+++ b/packages/Tethering/res/values-en-rIN/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering or hotspot active"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tap to set up."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering is disabled"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Contact your admin for details"</string>
+</resources>
diff --git a/packages/Tethering/res/values-en-rXC/strings.xml b/packages/Tethering/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..7f47fc8
--- /dev/null
+++ b/packages/Tethering/res/values-en-rXC/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎Tethering or hotspot active‎‏‎‎‏‎"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‎‏‎Tap to set up.‎‏‎‎‏‎"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‏‏‎Tethering is disabled‎‏‎‎‏‎"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎Contact your admin for details‎‏‎‎‏‎"</string>
+</resources>
diff --git a/packages/Tethering/res/values-es-rUS/strings.xml b/packages/Tethering/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..e4618b8
--- /dev/null
+++ b/packages/Tethering/res/values-es-rUS/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Anclaje a red o zona activa conectados"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Presiona para configurar."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Se inhabilitó la conexión mediante dispositivo portátil"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Para obtener más información, comunícate con el administrador"</string>
+</resources>
diff --git a/packages/Tethering/res/values-es/strings.xml b/packages/Tethering/res/values-es/strings.xml
new file mode 100644
index 0000000..8dc1575
--- /dev/null
+++ b/packages/Tethering/res/values-es/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Compartir conexión/Zona Wi-Fi activada"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Toca para configurar."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"La conexión compartida está inhabilitada"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Ponte en contacto con el administrador para obtener más información"</string>
+</resources>
diff --git a/packages/Tethering/res/values-et/strings.xml b/packages/Tethering/res/values-et/strings.xml
new file mode 100644
index 0000000..872c8a7
--- /dev/null
+++ b/packages/Tethering/res/values-et/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Jagamine või kuumkoht on aktiivne"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Puudutage seadistamiseks."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Jagamine on keelatud"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Lisateabe saamiseks võtke ühendust oma administraatoriga"</string>
+</resources>
diff --git a/packages/Tethering/res/values-eu/strings.xml b/packages/Tethering/res/values-eu/strings.xml
new file mode 100644
index 0000000..6c4605e
--- /dev/null
+++ b/packages/Tethering/res/values-eu/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Konexioa partekatzea edo sare publikoa aktibo"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Sakatu konfiguratzeko."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Desgaituta dago konexioa partekatzeko aukera"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Xehetasunak lortzeko, jarri administratzailearekin harremanetan"</string>
+</resources>
diff --git a/packages/Tethering/res/values-fa/strings.xml b/packages/Tethering/res/values-fa/strings.xml
new file mode 100644
index 0000000..bc2ee23
--- /dev/null
+++ b/packages/Tethering/res/values-fa/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"اشتراک‌گذاری اینترنت یا نقطه اتصال فعال"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"برای راه‌اندازی ضربه بزنید."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"اشتراک‌گذاری اینترنت غیرفعال است"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"برای جزئیات، با سرپرستتان تماس بگیرید"</string>
+</resources>
diff --git a/packages/Tethering/res/values-fi/strings.xml b/packages/Tethering/res/values-fi/strings.xml
new file mode 100644
index 0000000..ff0fca6
--- /dev/null
+++ b/packages/Tethering/res/values-fi/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Internetin jakaminen tai yhteyspiste käytössä"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Määritä napauttamalla."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Yhteyden jakaminen poistettu käytöstä"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Kysy lisätietoja järjestelmänvalvojalta."</string>
+</resources>
diff --git a/packages/Tethering/res/values-fr-rCA/strings.xml b/packages/Tethering/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..1f5df0e
--- /dev/null
+++ b/packages/Tethering/res/values-fr-rCA/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Partage de connexion ou point d\'accès sans fil activé"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Touchez pour configurer."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Le partage de connexion est désactivé"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Communiquez avec votre administrateur pour obtenir plus de détails"</string>
+</resources>
diff --git a/packages/Tethering/res/values-fr/strings.xml b/packages/Tethering/res/values-fr/strings.xml
new file mode 100644
index 0000000..daf7c9d
--- /dev/null
+++ b/packages/Tethering/res/values-fr/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Partage de connexion ou point d\'accès sans fil activé"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Appuyez ici pour configurer."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Le partage de connexion est désactivé"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Pour en savoir plus, contactez votre administrateur"</string>
+</resources>
diff --git a/packages/Tethering/res/values-gl/strings.xml b/packages/Tethering/res/values-gl/strings.xml
new file mode 100644
index 0000000..0d16a1d
--- /dev/null
+++ b/packages/Tethering/res/values-gl/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Conexión compartida ou zona wifi activada"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tocar para configurar."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"A conexión compartida está desactivada"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Contacta co administrador para obter información"</string>
+</resources>
diff --git a/packages/Tethering/res/values-gu/strings.xml b/packages/Tethering/res/values-gu/strings.xml
new file mode 100644
index 0000000..9d6b02f
--- /dev/null
+++ b/packages/Tethering/res/values-gu/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ટિથરિંગ અથવા હૉટસ્પૉટ સક્રિય"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"સેટ કરવા માટે ટૅપ કરો."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ટિથરિંગ અક્ષમ કરેલ છે"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"વિગતો માટે તમારા વ્યવસ્થાપકનો સંપર્ક કરો"</string>
+</resources>
diff --git a/packages/Tethering/res/values-hi/strings.xml b/packages/Tethering/res/values-hi/strings.xml
new file mode 100644
index 0000000..9c29d9a
--- /dev/null
+++ b/packages/Tethering/res/values-hi/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"टेदरिंग या हॉटस्‍पॉट सक्रिय"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"सेट करने के लिए टैप करें."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"टेदरिंग अक्षम है"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"जानकारी के लिए अपने एडमिन से संपर्क करें"</string>
+</resources>
diff --git a/packages/Tethering/res/values-hr/strings.xml b/packages/Tethering/res/values-hr/strings.xml
new file mode 100644
index 0000000..d0d25bb
--- /dev/null
+++ b/packages/Tethering/res/values-hr/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Ograničenje ili aktivan hotspot"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Dodirnite da biste postavili."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Modemsko je povezivanje onemogućeno"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Obratite se administratoru da biste saznali pojedinosti"</string>
+</resources>
diff --git a/packages/Tethering/res/values-hu/strings.xml b/packages/Tethering/res/values-hu/strings.xml
new file mode 100644
index 0000000..3129659
--- /dev/null
+++ b/packages/Tethering/res/values-hu/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Megosztás vagy aktív hotspot"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Koppintson a beállításhoz."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Az internetmegosztás le van tiltva"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"A részletekért forduljon rendszergazdájához"</string>
+</resources>
diff --git a/packages/Tethering/res/values-hy/strings.xml b/packages/Tethering/res/values-hy/strings.xml
new file mode 100644
index 0000000..8ba6435
--- /dev/null
+++ b/packages/Tethering/res/values-hy/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Մոդեմի ռեժիմը միացված է"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Հպեք՝ կարգավորելու համար:"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Մոդեմի ռեժիմն անջատված է"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Մանրամասների համար դիմեք ձեր ադմինիստրատորին"</string>
+</resources>
diff --git a/packages/Tethering/res/values-in/strings.xml b/packages/Tethering/res/values-in/strings.xml
new file mode 100644
index 0000000..1e093ab
--- /dev/null
+++ b/packages/Tethering/res/values-in/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering (Penambatan) atau hotspot aktif"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Ketuk untuk menyiapkan."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering dinonaktifkan"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Hubungi admin untuk mengetahui detailnya"</string>
+</resources>
diff --git a/packages/Tethering/res/values-is/strings.xml b/packages/Tethering/res/values-is/strings.xml
new file mode 100644
index 0000000..f5769d5
--- /dev/null
+++ b/packages/Tethering/res/values-is/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Kveikt á tjóðrun eða aðgangsstað"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Ýttu til að setja upp."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Slökkt er á tjóðrun"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Hafðu samband við kerfisstjórann til að fá upplýsingar"</string>
+</resources>
diff --git a/packages/Tethering/res/values-it/strings.xml b/packages/Tethering/res/values-it/strings.xml
new file mode 100644
index 0000000..e0b3724
--- /dev/null
+++ b/packages/Tethering/res/values-it/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering oppure hotspot attivo"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tocca per impostare."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering disattivato"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Contatta il tuo amministratore per avere informazioni dettagliate"</string>
+</resources>
diff --git a/packages/Tethering/res/values-iw/strings.xml b/packages/Tethering/res/values-iw/strings.xml
new file mode 100644
index 0000000..c002c44
--- /dev/null
+++ b/packages/Tethering/res/values-iw/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"שיתוף אינטרנט פעיל"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"הקש כדי להגדיר."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"שיתוף האינטרנט בין ניידים מושבת"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"לפרטים, יש לפנות למנהל המערכת"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ja/strings.xml b/packages/Tethering/res/values-ja/strings.xml
new file mode 100644
index 0000000..314bde0
--- /dev/null
+++ b/packages/Tethering/res/values-ja/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"テザリングまたはアクセスポイントが有効です"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"タップしてセットアップします。"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"テザリングは無効に設定されています"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"詳しくは、管理者にお問い合わせください"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ka/strings.xml b/packages/Tethering/res/values-ka/strings.xml
new file mode 100644
index 0000000..7bbd81d
--- /dev/null
+++ b/packages/Tethering/res/values-ka/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ტეტერინგი ან უსადენო ქსელი აქტიურია"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"შეეხეთ დასაყენებლად."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ტეტერინგი გათიშულია"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"დამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს"</string>
+</resources>
diff --git a/packages/Tethering/res/values-kk/strings.xml b/packages/Tethering/res/values-kk/strings.xml
new file mode 100644
index 0000000..7fd87a1
--- /dev/null
+++ b/packages/Tethering/res/values-kk/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Тетеринг немесе хотспот қосулы"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Реттеу үшін түртіңіз."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Тетеринг өшірілді"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Мәліметтерді әкімшіден алыңыз"</string>
+</resources>
diff --git a/packages/Tethering/res/values-km/strings.xml b/packages/Tethering/res/values-km/strings.xml
new file mode 100644
index 0000000..2f85224
--- /dev/null
+++ b/packages/Tethering/res/values-km/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ភ្ជាប់ ឬ​ហតស្ពត​សកម្ម"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"ប៉ះដើម្បីកំណត់"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ការភ្ជាប់​ត្រូវបានបិទ"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"ទាក់ទងអ្នកគ្រប់គ្រង​របស់អ្នកសម្រាប់​ព័ត៌មានលម្អិត"</string>
+</resources>
diff --git a/packages/Tethering/res/values-kn/strings.xml b/packages/Tethering/res/values-kn/strings.xml
new file mode 100644
index 0000000..f11a83ea
--- /dev/null
+++ b/packages/Tethering/res/values-kn/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ಟೆಥರಿಂಗ್ ಅಥವಾ ಹಾಟ್‌ಸ್ಪಾಟ್ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ಟೆಥರಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"ವಿವರಗಳಿಗಾಗಿ ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ko/strings.xml b/packages/Tethering/res/values-ko/strings.xml
new file mode 100644
index 0000000..57f24f5
--- /dev/null
+++ b/packages/Tethering/res/values-ko/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"테더링 또는 핫스팟 사용"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"설정하려면 탭하세요."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"테더링이 사용 중지됨"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"자세한 정보는 관리자에게 문의하세요."</string>
+</resources>
diff --git a/packages/Tethering/res/values-ky/strings.xml b/packages/Tethering/res/values-ky/strings.xml
new file mode 100644
index 0000000..7985485
--- /dev/null
+++ b/packages/Tethering/res/values-ky/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Жалгаштыруу же хотспот жандырылган"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Жөндөө үчүн таптап коюңуз."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Жалгаштыруу функциясы өчүрүлгөн"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Кеңири маалымат үчүн администраторуңузга кайрылыңыз"</string>
+</resources>
diff --git a/packages/Tethering/res/values-lo/strings.xml b/packages/Tethering/res/values-lo/strings.xml
new file mode 100644
index 0000000..78f1585
--- /dev/null
+++ b/packages/Tethering/res/values-lo/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ເປີດ​ການ​ປ່ອຍ​ສັນຍານ ຫຼື​ຮັອດສະປອດ​ແລ້ວ"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"ແຕະເພື່ອຕັ້ງຄ່າ."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ການປ່ອຍສັນຍານຖືກປິດໄວ້"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"ຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບສຳລັບລາຍລະອຽດ"</string>
+</resources>
diff --git a/packages/Tethering/res/values-lt/strings.xml b/packages/Tethering/res/values-lt/strings.xml
new file mode 100644
index 0000000..ebff8ac
--- /dev/null
+++ b/packages/Tethering/res/values-lt/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Susietas ar aktyvus"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Palieskite, kad nustatytumėte."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Įrenginio kaip modemo naudojimas išjungtas"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Jei reikia išsamios informacijos, susisiekite su administratoriumi"</string>
+</resources>
diff --git a/packages/Tethering/res/values-lv/strings.xml b/packages/Tethering/res/values-lv/strings.xml
new file mode 100644
index 0000000..54d0048
--- /dev/null
+++ b/packages/Tethering/res/values-lv/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Piesaiste vai tīklājs ir aktīvs."</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Pieskarieties, lai iestatītu."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Piesaiste ir atspējota"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Lai iegūtu detalizētu informāciju, sazinieties ar savu administratoru."</string>
+</resources>
diff --git a/packages/Tethering/res/values-mk/strings.xml b/packages/Tethering/res/values-mk/strings.xml
new file mode 100644
index 0000000..0fab8aa
--- /dev/null
+++ b/packages/Tethering/res/values-mk/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Поврзувањето или точката на пристап се активни"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Допрете за поставување."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Врзувањето е оневозможено"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Контактирајте со администраторот за детали"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ml/strings.xml b/packages/Tethering/res/values-ml/strings.xml
new file mode 100644
index 0000000..fd7e556
--- /dev/null
+++ b/packages/Tethering/res/values-ml/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ടെതറിംഗ് അല്ലെങ്കിൽ ഹോട്ട്സ്‌പോട്ട് സജീവമാണ്"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"സജ്ജമാക്കാൻ ടാപ്പുചെയ്യുക."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ടെതറിംഗ് പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"വിശദവിവരങ്ങൾക്ക് നിങ്ങളുടെ അഡ്മിനെ ബന്ധപ്പെടുക"</string>
+</resources>
diff --git a/packages/Tethering/res/values-mn/strings.xml b/packages/Tethering/res/values-mn/strings.xml
new file mode 100644
index 0000000..4596577
--- /dev/null
+++ b/packages/Tethering/res/values-mn/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Модем болгох эсвэл идэвхтэй цэг болгох"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Тохируулахын тулд товшино уу."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Модем болгох боломжгүй байна"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Дэлгэрэнгүй мэдээлэл авахын тулд админтайгаа холбогдоно уу"</string>
+</resources>
diff --git a/packages/Tethering/res/values-mr/strings.xml b/packages/Tethering/res/values-mr/strings.xml
new file mode 100644
index 0000000..85c9ade
--- /dev/null
+++ b/packages/Tethering/res/values-mr/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"टेदरिंग किंवा हॉटस्पॉट सक्रिय"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"सेट करण्यासाठी टॅप करा."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"टेदरिंग बंद आहे"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"तपशीलांसाठी तुमच्या प्रशासकाशी संपर्क साधा"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ms/strings.xml b/packages/Tethering/res/values-ms/strings.xml
new file mode 100644
index 0000000..ec6bdbd
--- /dev/null
+++ b/packages/Tethering/res/values-ms/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Penambatan atau titik panas aktif"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Ketik untuk membuat persediaan."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Penambatan dilumpuhkan"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Hubungi pentadbir anda untuk maklumat lanjut"</string>
+</resources>
diff --git a/packages/Tethering/res/values-my/strings.xml b/packages/Tethering/res/values-my/strings.xml
new file mode 100644
index 0000000..83978b6
--- /dev/null
+++ b/packages/Tethering/res/values-my/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"တဆင့်ပြန်လည်လွှင့်ခြင်း သို့မဟုတ် ဟော့စပေါ့ ဖွင့်ထားသည်"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"စနစ်ထည့်သွင်းရန် တို့ပါ။"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"မိုဘိုင်းဖုန်းကို မိုဒမ်အဖြစ်သုံးခြင်းအား ပိတ်ထားသည်"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"အသေးစိတ်အချက်အလက်များအတွက် သင့်စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ"</string>
+</resources>
diff --git a/packages/Tethering/res/values-nb/strings.xml b/packages/Tethering/res/values-nb/strings.xml
new file mode 100644
index 0000000..9abf32d
--- /dev/null
+++ b/packages/Tethering/res/values-nb/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Internettdeling eller trådløs sone er aktiv"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Trykk for å konfigurere."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Internettdeling er slått av"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Ta kontakt med administratoren din for å få mer informasjon"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ne/strings.xml b/packages/Tethering/res/values-ne/strings.xml
new file mode 100644
index 0000000..c886929
--- /dev/null
+++ b/packages/Tethering/res/values-ne/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"टेथर गर्ने वा हटस्पट सक्रिय"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"सेटअप गर्न ट्याप गर्नुहोस्।"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"टेदरिङलाई असक्षम पारिएको छ"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"विवरणहरूका लागि आफ्ना प्रशासकलाई सम्पर्क गर्नुहोस्"</string>
+</resources>
diff --git a/packages/Tethering/res/values-nl/strings.xml b/packages/Tethering/res/values-nl/strings.xml
new file mode 100644
index 0000000..0ec4bff
--- /dev/null
+++ b/packages/Tethering/res/values-nl/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering of hotspot actief"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tik om in te stellen."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering is uitgeschakeld"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Neem contact op met je beheerder voor meer informatie"</string>
+</resources>
diff --git a/packages/Tethering/res/values-or/strings.xml b/packages/Tethering/res/values-or/strings.xml
new file mode 100644
index 0000000..4576857
--- /dev/null
+++ b/packages/Tethering/res/values-or/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ଟିଥରିଙ୍ଗ କିମ୍ୱା ହଟସ୍ପଟ୍‌ ସକ୍ରିୟ ଅଛି"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"ସେଟଅପ୍‍ କରିବାକୁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ଟିଥରିଙ୍ଗ ଅକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"ବିବରଣୀ ପାଇଁ ନିଜ ଆଡମିନ୍‌ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ"</string>
+</resources>
diff --git a/packages/Tethering/res/values-pa/strings.xml b/packages/Tethering/res/values-pa/strings.xml
new file mode 100644
index 0000000..deddf2e
--- /dev/null
+++ b/packages/Tethering/res/values-pa/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ਟੈਦਰਿੰਗ ਜਾਂ ਹੌਟਸਪੌਟ ਕਿਰਿਆਸ਼ੀਲ"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"ਸਥਾਪਤ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ਟੈਦਰਿੰਗ ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"ਵੇਰਵਿਆਂ ਲਈ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ"</string>
+</resources>
diff --git a/packages/Tethering/res/values-pl/strings.xml b/packages/Tethering/res/values-pl/strings.xml
new file mode 100644
index 0000000..48d8468
--- /dev/null
+++ b/packages/Tethering/res/values-pl/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Aktywny tethering lub punkt dostępu"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Kliknij, by skonfigurować."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering został wyłączony"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Aby uzyskać szczegółowe informacje, skontaktuj się z administratorem"</string>
+</resources>
diff --git a/packages/Tethering/res/values-pt-rBR/strings.xml b/packages/Tethering/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..32c22b8
--- /dev/null
+++ b/packages/Tethering/res/values-pt-rBR/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Ponto de acesso ou tethering ativo"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Toque para configurar."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering desativado"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Fale com seu administrador para saber detalhes"</string>
+</resources>
diff --git a/packages/Tethering/res/values-pt-rPT/strings.xml b/packages/Tethering/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..641e22f
--- /dev/null
+++ b/packages/Tethering/res/values-pt-rPT/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Ligação ponto a ponto ou hotspot activos"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Toque para configurar."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"A ligação (à Internet) via telemóvel está desativada."</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Contacte o gestor para obter detalhes."</string>
+</resources>
diff --git a/packages/Tethering/res/values-pt/strings.xml b/packages/Tethering/res/values-pt/strings.xml
new file mode 100644
index 0000000..32c22b8
--- /dev/null
+++ b/packages/Tethering/res/values-pt/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Ponto de acesso ou tethering ativo"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Toque para configurar."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering desativado"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Fale com seu administrador para saber detalhes"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ro/strings.xml b/packages/Tethering/res/values-ro/strings.xml
new file mode 100644
index 0000000..f861f73
--- /dev/null
+++ b/packages/Tethering/res/values-ro/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering sau hotspot activ"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Atingeți ca să configurați."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tetheringul este dezactivat"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Contactați administratorul pentru detalii"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ru/strings.xml b/packages/Tethering/res/values-ru/strings.xml
new file mode 100644
index 0000000..027cb41
--- /dev/null
+++ b/packages/Tethering/res/values-ru/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Включен режим модема"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Нажмите, чтобы настроить."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Включить режим модема нельзя"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Обратитесь к администратору, чтобы узнать подробности."</string>
+</resources>
diff --git a/packages/Tethering/res/values-si/strings.xml b/packages/Tethering/res/values-si/strings.xml
new file mode 100644
index 0000000..7d8599f
--- /dev/null
+++ b/packages/Tethering/res/values-si/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ටෙදරින් හෝ හොට්ස්පොට් සක්‍රීයයි"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"පිහිටුවීමට තට්ටු කරන්න."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ටෙදරින් අබල කර ඇත"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"විස්තර සඳහා ඔබගේ පරිපාලක අමතන්න"</string>
+</resources>
diff --git a/packages/Tethering/res/values-sk/strings.xml b/packages/Tethering/res/values-sk/strings.xml
new file mode 100644
index 0000000..a8fe297
--- /dev/null
+++ b/packages/Tethering/res/values-sk/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering alebo prístupový bod je aktívny"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Klepnutím prejdete na nastavenie."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering je deaktivovaný"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"O podrobnosti požiadajte svojho správcu"</string>
+</resources>
diff --git a/packages/Tethering/res/values-sl/strings.xml b/packages/Tethering/res/values-sl/strings.xml
new file mode 100644
index 0000000..b5e5e38
--- /dev/null
+++ b/packages/Tethering/res/values-sl/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Aktivna povezava z internetom ali dostopna točka sta aktivni"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Dotaknite se, če želite nastaviti."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Povezava z internetom prek mobilnega telefona je onemogočena"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Za podrobnosti se obrnite na skrbnika"</string>
+</resources>
diff --git a/packages/Tethering/res/values-sq/strings.xml b/packages/Tethering/res/values-sq/strings.xml
new file mode 100644
index 0000000..fdd4906
--- /dev/null
+++ b/packages/Tethering/res/values-sq/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Lidhja e çiftimit ose ajo e qasjes në zona publike interneti është aktive"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Trokit për ta konfiguruar."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Lidhja e çiftimit është çaktivizuar"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Kontakto me administratorin për detaje"</string>
+</resources>
diff --git a/packages/Tethering/res/values-sr/strings.xml b/packages/Tethering/res/values-sr/strings.xml
new file mode 100644
index 0000000..9fab34589
--- /dev/null
+++ b/packages/Tethering/res/values-sr/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Активно повезивање са интернетом преко мобилног уређаја или хотспот"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Додирните да бисте подесили."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Привезивање је онемогућено"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Потражите детаље од администратора"</string>
+</resources>
diff --git a/packages/Tethering/res/values-sv/strings.xml b/packages/Tethering/res/values-sv/strings.xml
new file mode 100644
index 0000000..10eeb0f
--- /dev/null
+++ b/packages/Tethering/res/values-sv/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Internetdelning eller surfzon aktiverad"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Tryck om du vill konfigurera."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Internetdelning har inaktiverats"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Kontakta administratören om du vill veta mer"</string>
+</resources>
diff --git a/packages/Tethering/res/values-sw/strings.xml b/packages/Tethering/res/values-sw/strings.xml
new file mode 100644
index 0000000..3353963
--- /dev/null
+++ b/packages/Tethering/res/values-sw/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Kushiriki au kusambaza intaneti kumewashwa"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Gusa ili uweke mipangilio."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Umezima kipengele cha kusambaza mtandao"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Wasiliana na msimamizi wako ili upate maelezo zaidi"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ta/strings.xml b/packages/Tethering/res/values-ta/strings.xml
new file mode 100644
index 0000000..b1e5cc2
--- /dev/null
+++ b/packages/Tethering/res/values-ta/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"டெதெரிங்/ஹாட்ஸ்பாட் இயங்குகிறது"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"அமைக்க, தட்டவும்."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"இணைப்பு முறை முடக்கப்பட்டுள்ளது"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"விவரங்களுக்கு, உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்"</string>
+</resources>
diff --git a/packages/Tethering/res/values-te/strings.xml b/packages/Tethering/res/values-te/strings.xml
new file mode 100644
index 0000000..aae40de
--- /dev/null
+++ b/packages/Tethering/res/values-te/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"టీథర్ చేయబడినది లేదా హాట్‌స్పాట్ సక్రియంగా ఉండేది"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"సెటప్ చేయడానికి నొక్కండి."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"టెథెరింగ్ నిలిపివేయబడింది"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"వివరాల కోసం మీ నిర్వాహకులను సంప్రదించండి"</string>
+</resources>
diff --git a/packages/Tethering/res/values-th/strings.xml b/packages/Tethering/res/values-th/strings.xml
new file mode 100644
index 0000000..1b80056
--- /dev/null
+++ b/packages/Tethering/res/values-th/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"การปล่อยสัญญาณหรือฮอตสปอตทำงานอยู่"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"แตะเพื่อตั้งค่า"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ปิดใช้การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือแล้ว"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"ติดต่อผู้ดูแลระบบเพื่อขอรายละเอียด"</string>
+</resources>
diff --git a/packages/Tethering/res/values-tl/strings.xml b/packages/Tethering/res/values-tl/strings.xml
new file mode 100644
index 0000000..12863f9
--- /dev/null
+++ b/packages/Tethering/res/values-tl/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Pagsasama o aktibong hotspot"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"I-tap upang i-set up."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Naka-disable ang pag-tether"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Makipag-ugnayan sa iyong admin para sa mga detalye"</string>
+</resources>
diff --git a/packages/Tethering/res/values-tr/strings.xml b/packages/Tethering/res/values-tr/strings.xml
new file mode 100644
index 0000000..bfcf1ac
--- /dev/null
+++ b/packages/Tethering/res/values-tr/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering veya hotspot etkin"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Ayarlamak için dokunun."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Tethering devre dışı bırakıldı"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Ayrıntılı bilgi için yöneticinize başvurun"</string>
+</resources>
diff --git a/packages/Tethering/res/values-uk/strings.xml b/packages/Tethering/res/values-uk/strings.xml
new file mode 100644
index 0000000..8e159c07
--- /dev/null
+++ b/packages/Tethering/res/values-uk/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Прив\'язка чи точка дост. активна"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Торкніться, щоб налаштувати."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Використання телефона в режимі модема вимкнено"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Щоб дізнатися більше, зв’яжіться з адміністратором"</string>
+</resources>
diff --git a/packages/Tethering/res/values-ur/strings.xml b/packages/Tethering/res/values-ur/strings.xml
new file mode 100644
index 0000000..89195d4
--- /dev/null
+++ b/packages/Tethering/res/values-ur/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"ٹیدرنگ یا ہاٹ اسپاٹ فعال"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"سیٹ اپ کرنے کیلئے تھپتھپائیں۔"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"ٹیدرنگ غیر فعال ہے"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"تفصیلات کے لئے اپنے منتظم سے رابطہ کریں"</string>
+</resources>
diff --git a/packages/Tethering/res/values-uz/strings.xml b/packages/Tethering/res/values-uz/strings.xml
new file mode 100644
index 0000000..0ac4d4a
--- /dev/null
+++ b/packages/Tethering/res/values-uz/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Modem rejimi yoniq"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Sozlash uchun bosing."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Modem rejimi faolsizlantirildi"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Tafsilotlari uchun administratoringizga murojaat qiling"</string>
+</resources>
diff --git a/packages/Tethering/res/values-vi/strings.xml b/packages/Tethering/res/values-vi/strings.xml
new file mode 100644
index 0000000..85a4db8
--- /dev/null
+++ b/packages/Tethering/res/values-vi/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Chức năng điểm truy cập Internet hoặc điểm phát sóng đang hoạt động"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Nhấn để thiết lập."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Đã tắt tính năng chia sẻ kết nối"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Hãy liên hệ với quản trị viên của bạn để biết chi tiết"</string>
+</resources>
diff --git a/packages/Tethering/res/values-zh-rCN/strings.xml b/packages/Tethering/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..ff1fe03
--- /dev/null
+++ b/packages/Tethering/res/values-zh-rCN/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"网络共享或热点已启用"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"点按即可进行设置。"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"网络共享已停用"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"请与您的管理员联系以了解详情"</string>
+</resources>
diff --git a/packages/Tethering/res/values-zh-rHK/strings.xml b/packages/Tethering/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..0de39fa
--- /dev/null
+++ b/packages/Tethering/res/values-zh-rHK/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"已啟用網絡共享或熱點"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"輕按即可設定。"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"網絡共享已停用"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"請聯絡您的管理員以瞭解詳情"</string>
+</resources>
diff --git a/packages/Tethering/res/values-zh-rTW/strings.xml b/packages/Tethering/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..9a117bb
--- /dev/null
+++ b/packages/Tethering/res/values-zh-rTW/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"網路共用或無線基地台已啟用"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"輕觸即可進行設定。"</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"數據連線已停用"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"詳情請洽你的管理員"</string>
+</resources>
diff --git a/packages/Tethering/res/values-zu/strings.xml b/packages/Tethering/res/values-zu/strings.xml
new file mode 100644
index 0000000..8fe10d8
--- /dev/null
+++ b/packages/Tethering/res/values-zu/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Ukusebenzisa njengemodemu noma i-hotspot ephathekayo kuvuliwe"</string>
+    <string name="tethered_notification_message" msgid="2113628520792055377">"Thepha ukuze usethe."</string>
+    <string name="disable_tether_notification_title" msgid="7526977944111313195">"Ukusebenzisa ifoni njengemodemu kukhutshaziwe"</string>
+    <string name="disable_tether_notification_message" msgid="2913366428516852495">"Xhumana nomphathi wakho ukuze uthole imininingwane"</string>
+</resources>
diff --git a/packages/Tethering/res/values/strings.xml b/packages/Tethering/res/values/strings.xml
new file mode 100644
index 0000000..ca866a9
--- /dev/null
+++ b/packages/Tethering/res/values/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Shown when the device is tethered -->
+    <!-- Strings for tethered notification title [CHAR LIMIT=200] -->
+    <string name="tethered_notification_title">Tethering or hotspot active</string>
+    <!-- Strings for tethered notification message [CHAR LIMIT=200] -->
+    <string name="tethered_notification_message">Tap to set up.</string>
+
+    <!-- This notification is shown when tethering has been disabled on a user's device.
+    The device is managed by the user's employer. Tethering can't be turned on unless the
+    IT administrator allows it. The noun "admin" is another reference for "IT administrator." -->
+    <!-- Strings for tether disabling notification title  [CHAR LIMIT=200] -->
+    <string name="disable_tether_notification_title">Tethering is disabled</string>
+    <!-- Strings for tether disabling notification message  [CHAR LIMIT=200] -->
+    <string name="disable_tether_notification_message">Contact your admin for details</string>
+</resources>
\ No newline at end of file
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index f1228129..7c78ef8 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -109,6 +109,7 @@
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.tethering.R;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -675,14 +676,14 @@
         int icon = 0;
         switch(id) {
             case SystemMessage.NOTE_TETHER_USB:
-                icon = com.android.internal.R.drawable.stat_sys_tether_usb;
+                icon = R.drawable.stat_sys_tether_usb;
                 break;
             case SystemMessage.NOTE_TETHER_BLUETOOTH:
-                icon = com.android.internal.R.drawable.stat_sys_tether_bluetooth;
+                icon = R.drawable.stat_sys_tether_bluetooth;
                 break;
             case SystemMessage.NOTE_TETHER_GENERAL:
             default:
-                icon = com.android.internal.R.drawable.stat_sys_tether_general;
+                icon = R.drawable.stat_sys_tether_general;
                 break;
         }
 
@@ -702,16 +703,16 @@
         PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
                 null, UserHandle.CURRENT);
 
-        Resources r = Resources.getSystem();
+        Resources r = mContext.getResources();
         final CharSequence title;
         final CharSequence message;
 
         if (tetheringOn) {
-            title = r.getText(com.android.internal.R.string.tethered_notification_title);
-            message = r.getText(com.android.internal.R.string.tethered_notification_message);
+            title = r.getText(R.string.tethered_notification_title);
+            message = r.getText(R.string.tethered_notification_message);
         } else {
-            title = r.getText(com.android.internal.R.string.disable_tether_notification_title);
-            message = r.getText(com.android.internal.R.string.disable_tether_notification_message);
+            title = r.getText(R.string.disable_tether_notification_title);
+            message = r.getText(R.string.disable_tether_notification_message);
         }
 
         if (mTetheredNotificationBuilder == null) {
@@ -909,7 +910,7 @@
 
             if (newlyDisallowed && isTetheringActiveOnDevice) {
                 mWrapper.showTetheredNotification(
-                        com.android.internal.R.drawable.stat_sys_tether_general, false);
+                        R.drawable.stat_sys_tether_general, false);
                 mWrapper.untetherAll();
             }
         }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 2eb2f33..203bc61 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -162,3 +162,9 @@
     name: "protolog.conf.json.gz",
     src: ":services.core.json.gz",
 }
+
+platform_compat_config {
+    name: "services-core-platform-compat-config",
+    src: ":services.core.unboosted",
+}
+
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 798a4c6..a318844 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -74,6 +74,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.HashMap;
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.Locale;
 import java.util.Map;
@@ -695,6 +696,35 @@
         return mIsHearingAidProfileSupported;
     }
 
+    @Override
+    /** @hide */
+    public java.util.List<String> getSystemConfigEnabledProfilesForPackage(String packageName) {
+        if (Binder.getCallingUid() != Process.BLUETOOTH_UID) {
+            Slog.w(TAG, "getSystemConfigEnabledProfilesForPackage(): not allowed for non-bluetooth");
+            return null;
+        }
+
+        SystemConfig systemConfig = SystemConfig.getInstance();
+        if (systemConfig == null) {
+            return null;
+        }
+
+        android.util.ArrayMap<String, Boolean> componentEnabledStates =
+                systemConfig.getComponentsEnabledStates(packageName);
+        if (componentEnabledStates == null) {
+            return null;
+        }
+
+        ArrayList enabledProfiles = new ArrayList<String>();
+        for (Map.Entry<String, Boolean> entry : componentEnabledStates.entrySet()) {
+            if (entry.getValue()) {
+                enabledProfiles.add(entry.getKey());
+            }
+        }
+
+        return enabledProfiles;
+    }
+
     // Monitor change of BLE scan only mode settings.
     private void registerForBleScanModeChange() {
         ContentObserver contentObserver = new ContentObserver(null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e119d1e..5b8ffde 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3784,7 +3784,7 @@
     }
 
     @GuardedBy("this")
-    void waitForProcKillLocked(final ProcessRecord app, final String formatString,
+    private void waitForProcKillLocked(final ProcessRecord app, final String formatString,
             final long startTime) {
         app.mAppDiedCallback = () -> {
             synchronized (ActivityManagerService.this) {
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 0524f91..638111e 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -126,7 +126,7 @@
     // Keep the last WiFi stats so we can compute a delta.
     @GuardedBy("mWorkerLock")
     private WifiActivityEnergyInfo mLastInfo =
-            new WifiActivityEnergyInfo(0, 0, 0, new long[]{0}, 0, 0, 0, 0);
+            new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0, 0);
 
     /**
      * Timestamp at which all external stats were last collected in
@@ -548,42 +548,45 @@
 
     @GuardedBy("mWorkerLock")
     private WifiActivityEnergyInfo extractDeltaLocked(WifiActivityEnergyInfo latest) {
-        final long timePeriodMs = latest.mTimestamp - mLastInfo.mTimestamp;
-        final long lastScanMs = mLastInfo.mControllerScanTimeMs;
-        final long lastIdleMs = mLastInfo.mControllerIdleTimeMs;
-        final long lastTxMs = mLastInfo.mControllerTxTimeMs;
-        final long lastRxMs = mLastInfo.mControllerRxTimeMs;
-        final long lastEnergy = mLastInfo.mControllerEnergyUsed;
+        final long timePeriodMs = latest.getTimeSinceBootMillis()
+                - mLastInfo.getTimeSinceBootMillis();
+        final long lastScanMs = mLastInfo.getControllerScanDurationMillis();
+        final long lastIdleMs = mLastInfo.getControllerIdleDurationMillis();
+        final long lastTxMs = mLastInfo.getControllerTxDurationMillis();
+        final long lastRxMs = mLastInfo.getControllerRxDurationMillis();
+        final long lastEnergy = mLastInfo.getControllerEnergyUsedMicroJoules();
 
         // We will modify the last info object to be the delta, and store the new
         // WifiActivityEnergyInfo object as our last one.
         final WifiActivityEnergyInfo delta = mLastInfo;
-        delta.mTimestamp = latest.getTimeStamp();
-        delta.mStackState = latest.getStackState();
+        delta.setTimeSinceBootMillis(latest.getTimeSinceBootMillis());
+        delta.setStackState(latest.getStackState());
 
-        final long txTimeMs = latest.mControllerTxTimeMs - lastTxMs;
-        final long rxTimeMs = latest.mControllerRxTimeMs - lastRxMs;
-        final long idleTimeMs = latest.mControllerIdleTimeMs - lastIdleMs;
-        final long scanTimeMs = latest.mControllerScanTimeMs - lastScanMs;
+        final long txTimeMs = latest.getControllerTxDurationMillis() - lastTxMs;
+        final long rxTimeMs = latest.getControllerRxDurationMillis() - lastRxMs;
+        final long idleTimeMs = latest.getControllerIdleDurationMillis() - lastIdleMs;
+        final long scanTimeMs = latest.getControllerScanDurationMillis() - lastScanMs;
 
         if (txTimeMs < 0 || rxTimeMs < 0 || scanTimeMs < 0 || idleTimeMs < 0) {
             // The stats were reset by the WiFi system (which is why our delta is negative).
             // Returns the unaltered stats. The total on time should not exceed the time
             // duartion between reports.
-            final long totalOnTimeMs = latest.mControllerTxTimeMs + latest.mControllerRxTimeMs
-                        + latest.mControllerIdleTimeMs;
+            final long totalOnTimeMs = latest.getControllerTxDurationMillis()
+                    + latest.getControllerRxDurationMillis()
+                    + latest.getControllerIdleDurationMillis();
             if (totalOnTimeMs <= timePeriodMs + MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS) {
-                delta.mControllerEnergyUsed = latest.mControllerEnergyUsed;
-                delta.mControllerRxTimeMs = latest.mControllerRxTimeMs;
-                delta.mControllerTxTimeMs = latest.mControllerTxTimeMs;
-                delta.mControllerIdleTimeMs = latest.mControllerIdleTimeMs;
-                delta.mControllerScanTimeMs = latest.mControllerScanTimeMs;
+                delta.setControllerEnergyUsedMicroJoules(
+                        latest.getControllerEnergyUsedMicroJoules());
+                delta.setControllerRxDurationMillis(latest.getControllerRxDurationMillis());
+                delta.setControllerTxDurationMillis(latest.getControllerTxDurationMillis());
+                delta.setControllerIdleDurationMillis(latest.getControllerIdleDurationMillis());
+                delta.setControllerScanDurationMillis(latest.getControllerScanDurationMillis());
             } else {
-                delta.mControllerEnergyUsed = 0;
-                delta.mControllerRxTimeMs = 0;
-                delta.mControllerTxTimeMs = 0;
-                delta.mControllerIdleTimeMs = 0;
-                delta.mControllerScanTimeMs = 0;
+                delta.setControllerEnergyUsedMicroJoules(0);
+                delta.setControllerRxDurationMillis(0);
+                delta.setControllerTxDurationMillis(0);
+                delta.setControllerIdleDurationMillis(0);
+                delta.setControllerScanDurationMillis(0);
             }
             Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + delta);
         } else {
@@ -608,28 +611,30 @@
                     sb.append(" e=").append(lastEnergy);
                     sb.append("\n");
                     sb.append("Current WiFi snapshot: ").append("idle=");
-                    TimeUtils.formatDuration(latest.mControllerIdleTimeMs, sb);
+                    TimeUtils.formatDuration(latest.getControllerIdleDurationMillis(), sb);
                     sb.append(" rx=");
-                    TimeUtils.formatDuration(latest.mControllerRxTimeMs, sb);
+                    TimeUtils.formatDuration(latest.getControllerRxDurationMillis(), sb);
                     sb.append(" tx=");
-                    TimeUtils.formatDuration(latest.mControllerTxTimeMs, sb);
-                    sb.append(" e=").append(latest.mControllerEnergyUsed);
+                    TimeUtils.formatDuration(latest.getControllerTxDurationMillis(), sb);
+                    sb.append(" e=").append(latest.getControllerEnergyUsedMicroJoules());
                     Slog.wtf(TAG, sb.toString());
                 }
             } else {
                 maxExpectedIdleTimeMs = timePeriodMs - totalActiveTimeMs;
             }
             // These times seem to be the most reliable.
-            delta.mControllerTxTimeMs = txTimeMs;
-            delta.mControllerRxTimeMs = rxTimeMs;
-            delta.mControllerScanTimeMs = scanTimeMs;
+            delta.setControllerTxDurationMillis(txTimeMs);
+            delta.setControllerRxDurationMillis(rxTimeMs);
+            delta.setControllerScanDurationMillis(scanTimeMs);
             // WiFi calculates the idle time as a difference from the on time and the various
             // Rx + Tx times. There seems to be some missing time there because this sometimes
             // becomes negative. Just cap it at 0 and ensure that it is less than the expected idle
             // time from the difference in timestamps.
             // b/21613534
-            delta.mControllerIdleTimeMs = Math.min(maxExpectedIdleTimeMs, Math.max(0, idleTimeMs));
-            delta.mControllerEnergyUsed = Math.max(0, latest.mControllerEnergyUsed - lastEnergy);
+            delta.setControllerIdleDurationMillis(
+                    Math.min(maxExpectedIdleTimeMs, Math.max(0, idleTimeMs)));
+            delta.setControllerEnergyUsedMicroJoules(
+                    Math.max(0, latest.getControllerEnergyUsedMicroJoules() - lastEnergy));
         }
 
         mLastInfo = latest;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 375da8a..2bb7035 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1421,7 +1421,7 @@
         if (app.pendingStart) {
             return true;
         }
-        long startTime = SystemClock.uptimeMillis();
+        long startTime = SystemClock.elapsedRealtime();
         if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
             checkSlow(startTime, "startProcess: removing from pids map");
             mService.mPidsSelfLocked.remove(app);
@@ -1856,7 +1856,7 @@
             boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
             boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
             String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
-        long startTime = SystemClock.uptimeMillis();
+        long startTime = SystemClock.elapsedRealtime();
         ProcessRecord app;
         if (!isolated) {
             app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
@@ -1917,9 +1917,10 @@
             // An application record is attached to a previous process,
             // clean it up now.
             if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App died: " + app);
+            checkSlow(startTime, "startProcess: bad proc running, killing");
             ProcessList.killProcessGroup(app.uid, app.pid);
-            mService.waitForProcKillLocked(app, "startProcess: bad proc running, killing: %s",
-                    startTime);
+            mService.handleAppDiedLocked(app, true, true);
+            checkSlow(startTime, "startProcess: done killing old proc");
         }
 
         if (app == null) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 7e9a17b..366766e 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1115,6 +1115,7 @@
                     // There is some actively running operation...  need to find it
                     // and appropriately update its state.
                     final long now = System.currentTimeMillis();
+                    final long nowElapsed = SystemClock.elapsedRealtime();
                     for (int i = uidState.pkgOps.size() - 1; i >= 0; i--) {
                         final Ops ops = uidState.pkgOps.valueAt(i);
                         for (int j = ops.size() - 1; j >= 0; j--) {
@@ -1136,7 +1137,7 @@
                                     featureOp.finished(now, duration, oldPendingState,
                                             AppOpsManager.OP_FLAG_SELF);
                                     // Start the op in the new state
-                                    featureOp.startRealtime = now;
+                                    featureOp.startRealtime = nowElapsed;
                                     featureOp.started(now, newState, AppOpsManager.OP_FLAG_SELF);
                                 }
                             }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e426c6c..4bf1de6 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -269,6 +269,7 @@
     private static final int MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS = 27;
     private static final int MSG_HDMI_VOLUME_CHECK = 28;
     private static final int MSG_PLAYBACK_CONFIG_CHANGE = 29;
+    private static final int MSG_BROADCAST_MICROPHONE_MUTE = 30;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -2925,9 +2926,8 @@
             AudioSystem.muteMicrophone(muted);
             try {
                 if (muted != currentMute) {
-                    mContext.sendBroadcastAsUser(
-                        new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
-                                .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), UserHandle.ALL);
+                    sendMsg(mAudioHandler, MSG_BROADCAST_MICROPHONE_MUTE,
+                                SENDMSG_NOOP, 0, 0, null, 0);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -5236,6 +5236,13 @@
                 case MSG_PLAYBACK_CONFIG_CHANGE:
                     onPlaybackConfigChange((List<AudioPlaybackConfiguration>) msg.obj);
                     break;
+
+                case MSG_BROADCAST_MICROPHONE_MUTE:
+                    mContext.sendBroadcastAsUser(
+                            new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
+                                    .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
+                                    UserHandle.ALL);
+                    break;
             }
         }
     }
diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
index 111b95a..aad177e 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -25,7 +25,7 @@
 public class RuleBinaryParser implements RuleParser {
 
     @Override
-    public List<Rule> parse(String ruleText) {
+    public List<Rule> parse(byte[] ruleBytes) {
         // TODO: Implement binary text parser.
         return null;
     }
diff --git a/services/core/java/com/android/server/integrity/parser/RuleParser.java b/services/core/java/com/android/server/integrity/parser/RuleParser.java
index 4e1f914..81783d5 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleParser.java
@@ -24,8 +24,8 @@
 /** A helper class to parse rules into the {@link Rule} model. */
 public interface RuleParser {
 
-    /** Parse rules from a string. */
-    List<Rule> parse(String ruleText) throws RuleParseException;
+    /** Parse rules from bytes. */
+    List<Rule> parse(byte[] ruleBytes) throws RuleParseException;
 
     /** Parse rules from an input stream. */
     List<Rule> parse(InputStream inputStream) throws RuleParseException;
diff --git a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
index 1212a08..2e99d0f 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
@@ -51,10 +51,10 @@
     private static final String IS_HASHED_VALUE_ATTRIBUTE = "H";
 
     @Override
-    public List<Rule> parse(String ruleText) throws RuleParseException {
+    public List<Rule> parse(byte[] ruleBytes) throws RuleParseException {
         try {
             XmlPullParser xmlPullParser = Xml.newPullParser();
-            xmlPullParser.setInput(new StringReader(ruleText));
+            xmlPullParser.setInput(new StringReader(new String(ruleBytes, StandardCharsets.UTF_8)));
             return parseRules(xmlPullParser);
         } catch (Exception e) {
             throw new RuleParseException(e.getMessage(), e);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 863991c..3c76c67 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -8268,7 +8268,7 @@
             try {
                 assistant.onAllowedAdjustmentsChanged();
             } catch (RemoteException ex) {
-                Slog.e(TAG, "unable to notify assistant (capabilities): " + assistant, ex);
+                Slog.e(TAG, "unable to notify assistant (capabilities): " + info, ex);
             }
         }
 
@@ -8278,7 +8278,7 @@
             try {
                 assistant.onNotificationsSeen(keys);
             } catch (RemoteException ex) {
-                Slog.e(TAG, "unable to notify assistant (seen): " + assistant, ex);
+                Slog.e(TAG, "unable to notify assistant (seen): " + info, ex);
             }
         }
 
@@ -8584,7 +8584,7 @@
                         listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
                     } catch (RemoteException ex) {
                         Slog.e(TAG, "unable to notify listener "
-                                + "(hideSilentStatusIcons): " + listener, ex);
+                                + "(hideSilentStatusIcons): " + info, ex);
                     }
                 });
             }
@@ -8877,7 +8877,7 @@
             try {
                 listener.onNotificationPosted(sbnHolder, rankingUpdate);
             } catch (RemoteException ex) {
-                Slog.e(TAG, "unable to notify listener (posted): " + listener, ex);
+                Slog.e(TAG, "unable to notify listener (posted): " + info, ex);
             }
         }
 
@@ -8891,7 +8891,7 @@
             try {
                 listener.onNotificationRemoved(sbnHolder, rankingUpdate, stats, reason);
             } catch (RemoteException ex) {
-                Slog.e(TAG, "unable to notify listener (removed): " + listener, ex);
+                Slog.e(TAG, "unable to notify listener (removed): " + info, ex);
             }
         }
 
@@ -8901,7 +8901,7 @@
             try {
                 listener.onNotificationRankingUpdate(rankingUpdate);
             } catch (RemoteException ex) {
-                Slog.e(TAG, "unable to notify listener (ranking update): " + listener, ex);
+                Slog.e(TAG, "unable to notify listener (ranking update): " + info, ex);
             }
         }
 
@@ -8910,7 +8910,7 @@
             try {
                 listener.onListenerHintsChanged(hints);
             } catch (RemoteException ex) {
-                Slog.e(TAG, "unable to notify listener (listener hints): " + listener, ex);
+                Slog.e(TAG, "unable to notify listener (listener hints): " + info, ex);
             }
         }
 
@@ -8920,7 +8920,7 @@
             try {
                 listener.onInterruptionFilterChanged(interruptionFilter);
             } catch (RemoteException ex) {
-                Slog.e(TAG, "unable to notify listener (interruption filter): " + listener, ex);
+                Slog.e(TAG, "unable to notify listener (interruption filter): " + info, ex);
             }
         }
 
@@ -8931,7 +8931,7 @@
             try {
                 listener.onNotificationChannelModification(pkg, user, channel, modificationType);
             } catch (RemoteException ex) {
-                Slog.e(TAG, "unable to notify listener (channel changed): " + listener, ex);
+                Slog.e(TAG, "unable to notify listener (channel changed): " + info, ex);
             }
         }
 
@@ -8942,7 +8942,7 @@
             try {
                 listener.onNotificationChannelGroupModification(pkg, user, group, modificationType);
             } catch (RemoteException ex) {
-                Slog.e(TAG, "unable to notify listener (channel group changed): " + listener, ex);
+                Slog.e(TAG, "unable to notify listener (channel group changed): " + info, ex);
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8439a0d..4e0e4ff 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2364,6 +2364,37 @@
         PackageManagerService m = new PackageManagerService(injector, factoryTest, onlyCore);
         t.traceEnd(); // "create package manager"
 
+        injector.getCompatibility().registerListener(SELinuxMMAC.SELINUX_LATEST_CHANGES,
+                packageName -> {
+                    synchronized (m.mInstallLock) {
+                        final PackageParser.Package pkg;
+                        final SharedUserSetting sharedUser;
+                        synchronized (m.mLock) {
+                            PackageSetting ps = m.mSettings.getPackageLPr(packageName);
+                            if (ps == null) {
+                                Slog.e(TAG, "Failed to find package setting " + packageName);
+                                return;
+                            }
+                            pkg = ps.pkg;
+                            sharedUser = ps.sharedUser;
+                        }
+
+                        if (pkg == null) {
+                            Slog.e(TAG, "Failed to find package " + packageName);
+                            return;
+                        }
+                        final String newSeInfo = SELinuxMMAC.getSeInfo(pkg, sharedUser,
+                                m.mInjector.getCompatibility());
+
+                        if (!newSeInfo.equals(pkg.applicationInfo.seInfo)) {
+                            Slog.i(TAG, "Updating seInfo for package " + packageName + " from: "
+                                    + pkg.applicationInfo.seInfo + " to: " + newSeInfo);
+                            pkg.applicationInfo.seInfo = newSeInfo;
+                            m.prepareAppDataAfterInstallLIF(pkg);
+                        }
+                    }
+                });
+
         m.installWhitelistedSystemPackages();
         ServiceManager.addService("package", m);
         final PackageManagerNative pmn = m.new PackageManagerNative();
@@ -10784,24 +10815,8 @@
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
         }
 
-        // Apps which share a sharedUserId must be placed in the same selinux domain. If this
-        // package is the first app installed as this shared user, set seInfoTargetSdkVersion to its
-        // targetSdkVersion. These are later adjusted in PackageManagerService's constructor to be
-        // the lowest targetSdkVersion of all apps within the shared user, which corresponds to the
-        // least restrictive selinux domain.
-        // NOTE: As new packages are installed / updated, the shared user's seinfoTargetSdkVersion
-        // will NOT be modified until next boot, even if a lower targetSdkVersion is used. This
-        // ensures that all packages continue to run in the same selinux domain.
-        final int targetSdkVersion =
-            ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) ?
-            sharedUserSetting.seInfoTargetSdkVersion : pkg.applicationInfo.targetSdkVersion;
-        // TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync.
-        // They currently can be if the sharedUser apps are signed with the platform key.
-        final boolean isPrivileged = (sharedUserSetting != null) ?
-            sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged();
-
-        pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
-                targetSdkVersion);
+        pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, sharedUserSetting,
+                injector.getCompatibility());
         pkg.applicationInfo.seInfoUser = SELinuxUtil.assignSeinfoUser(pkgSetting.readUserState(
                 userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId));
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 9afc9a8..1b73602 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3279,7 +3279,7 @@
         pw.println("       [--user USER_ID] INTENT");
         pw.println("    Prints all broadcast receivers that can handle the given INTENT.");
         pw.println("");
-        pw.println("  install [-rtsfdgw] [-i PACKAGE] [--user USER_ID|all|current]");
+        pw.println("  install [-rtfdgw] [-i PACKAGE] [--user USER_ID|all|current]");
         pw.println("       [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
         pw.println("       [--install-reason 0/1/2/3/4] [--originating-uri URI]");
         pw.println("       [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
@@ -3293,7 +3293,6 @@
         pw.println("      -R: disallow replacement of existing application");
         pw.println("      -t: allow test packages");
         pw.println("      -i: specify package name of installer owning the app");
-        pw.println("      -s: install application on sdcard");
         pw.println("      -f: install application on internal flash");
         pw.println("      -d: allow version code downgrade (debuggable packages only)");
         pw.println("      -p: partial application install (new split on top of existing pkg)");
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index b464988..d20f20f 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -16,6 +16,8 @@
 
 package com.android.server.pm;
 
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.Signature;
@@ -23,6 +25,8 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.server.compat.PlatformCompat;
+
 import libcore.io.IoUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -72,6 +76,19 @@
     // Append targetSdkVersion=n to existing seinfo label where n is the app's targetSdkVersion
     private static final String TARGETSDKVERSION_STR = ":targetSdkVersion=";
 
+    /**
+     * This change gates apps access to untrusted_app_R-targetSDk SELinux domain. Allows opt-in
+     * to R targetSdkVersion enforced changes without changing target SDK. Turning this change
+     * off for an app targeting R is a no-op.
+     *
+     * <p>Has no effect for apps using shared user id.
+     *
+     * TODO(b/143539591): Update description with relevant SELINUX changes this opts in to.
+     */
+    @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.Q)
+    @ChangeId
+    static final long SELINUX_LATEST_CHANGES = 143539591L;
+
     // Only initialize sMacPermissions once.
     static {
         // Platform mac permissions.
@@ -319,6 +336,48 @@
         }
     }
 
+    private static int getTargetSdkVersionForSeInfo(PackageParser.Package pkg,
+            SharedUserSetting sharedUserSetting, PlatformCompat compatibility) {
+        // Apps which share a sharedUserId must be placed in the same selinux domain. If this
+        // package is the first app installed as this shared user, set seInfoTargetSdkVersion to its
+        // targetSdkVersion. These are later adjusted in PackageManagerService's constructor to be
+        // the lowest targetSdkVersion of all apps within the shared user, which corresponds to the
+        // least restrictive selinux domain.
+        // NOTE: As new packages are installed / updated, the shared user's seinfoTargetSdkVersion
+        // will NOT be modified until next boot, even if a lower targetSdkVersion is used. This
+        // ensures that all packages continue to run in the same selinux domain.
+        if ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) {
+            return sharedUserSetting.seInfoTargetSdkVersion;
+        }
+        if (compatibility.isChangeEnabled(SELINUX_LATEST_CHANGES, pkg.applicationInfo)) {
+            return android.os.Build.VERSION_CODES.R;
+        }
+
+        return pkg.applicationInfo.targetSdkVersion;
+    }
+
+    /**
+     * Selects a security label to a package based on input parameters and the seinfo tag taken
+     * from a matched policy. All signature based policy stanzas are consulted and, if no match
+     * is found, the default seinfo label of 'default' is used. The security label is attached to
+     * the ApplicationInfo instance of the package.
+     *
+     * @param pkg               object representing the package to be labeled.
+     * @param sharedUserSetting if the app shares a sharedUserId, then this has the shared setting.
+     * @param compatibility     the PlatformCompat service to ask about state of compat changes.
+     * @return String representing the resulting seinfo.
+     */
+    public static String getSeInfo(PackageParser.Package pkg, SharedUserSetting sharedUserSetting,
+            PlatformCompat compatibility) {
+        final int targetSdkVersion = getTargetSdkVersionForSeInfo(pkg, sharedUserSetting,
+                compatibility);
+        // TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync.
+        // They currently can be if the sharedUser apps are signed with the platform key.
+        final boolean isPrivileged = (sharedUserSetting != null)
+                ? sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged();
+        return getSeInfo(pkg, isPrivileged, targetSdkVersion);
+    }
+
     /**
      * Selects a security label to a package based on input parameters and the seinfo tag taken
      * from a matched policy. All signature based policy stanzas are consulted and, if no match
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index faff394..05f62b2 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3210,6 +3210,13 @@
                         flags |= UserInfo.FLAG_EPHEMERAL;
                     }
 
+                    // Always clear EPHEMERAL for pre-created users, otherwise the storage key
+                    // won't be persisted. The flag will be re-added (if needed) when the
+                    // pre-created user is "converted" to a normal user.
+                    if (preCreate) {
+                        flags &= ~UserInfo.FLAG_EPHEMERAL;
+                    }
+
                     userInfo = new UserInfo(userId, name, null, flags, userType);
                     userInfo.serialNumber = mNextSerialNumber++;
                     userInfo.creationTime = getCreationTime();
@@ -4428,6 +4435,7 @@
         pw.println("  Supports switchable users: " + UserManager.supportsMultipleUsers());
         pw.println("  All guests ephemeral: " + Resources.getSystem().getBoolean(
                 com.android.internal.R.bool.config_guestUserEphemeral));
+        pw.println("  Force ephemeral users: " + mForceEphemeralUsers);
         pw.println("  Is split-system user: " + UserManager.isSplitSystemUser());
         pw.println("  Is headless-system mode: " + UserManager.isHeadlessSystemUserMode());
         pw.println("  User version: " + mUserVersion);
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index f071c65..9b50307 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -578,10 +578,6 @@
                     if (newValue) {
                         android.provider.Settings.Global.putStringForUser(
                                 context.getContentResolver(),
-                                android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
-                                userId);
-                        android.provider.Settings.Global.putStringForUser(
-                                context.getContentResolver(),
                                 android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
                                 userId);
                     }
@@ -717,7 +713,6 @@
                 restriction = UserManager.DISALLOW_DEBUGGING_FEATURES;
                 break;
 
-            case android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE:
             case android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB:
                 if ("1".equals(value)) {
                     return false;
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 01f29dc..00779ec 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -67,6 +67,7 @@
 import java.time.Instant;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -82,6 +83,7 @@
 class RollbackManagerServiceImpl extends IRollbackManager.Stub {
 
     private static final String TAG = "RollbackManager";
+    private static final boolean LOCAL_LOGV = false;
 
     // Rollbacks expire after 14 days.
     private static final long DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS =
@@ -220,6 +222,9 @@
                 if (Intent.ACTION_CANCEL_ENABLE_ROLLBACK.equals(intent.getAction())) {
                     int token = intent.getIntExtra(
                             PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, -1);
+                    if (LOCAL_LOGV) {
+                        Slog.v(TAG, "broadcast=ACTION_CANCEL_ENABLE_ROLLBACK token=" + token);
+                    }
                     synchronized (mLock) {
                         for (NewRollback rollback : mNewRollbacks) {
                             if (rollback.hasToken(token)) {
@@ -269,10 +274,17 @@
                 String action = intent.getAction();
                 if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
                     String packageName = intent.getData().getSchemeSpecificPart();
+                    if (LOCAL_LOGV) {
+                        Slog.v(TAG, "broadcast=ACTION_PACKAGE_REPLACED" + " pkg=" + packageName);
+                    }
                     onPackageReplaced(packageName);
                 }
                 if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
                     String packageName = intent.getData().getSchemeSpecificPart();
+                    if (LOCAL_LOGV) {
+                        Slog.v(TAG, "broadcast=ACTION_PACKAGE_FULLY_REMOVED"
+                                + " pkg=" + packageName);
+                    }
                     onPackageFullyRemoved(packageName);
                 }
             }
@@ -359,7 +371,7 @@
      */
     private void commitRollbackInternal(int rollbackId, List<VersionedPackage> causePackages,
             String callerPackageName, IntentSender statusReceiver) {
-        Slog.i(TAG, "Initiating rollback");
+        Slog.i(TAG, "commitRollback id=" + rollbackId + " caller=" + callerPackageName);
 
         Rollback rollback = getRollbackForId(rollbackId);
         if (rollback == null) {
@@ -444,6 +456,9 @@
     }
 
     void onUnlockUser(int userId) {
+        if (LOCAL_LOGV) {
+            Slog.v(TAG, "onUnlockUser id=" + userId);
+        }
         // In order to ensure that no package begins running while a backup or restore is taking
         // place, onUnlockUser must remain blocked until all pending backups and restores have
         // completed.
@@ -611,6 +626,9 @@
                 if (!now.isBefore(
                         rollbackTimestamp
                                 .plusMillis(mRollbackLifetimeDurationInMillis))) {
+                    if (LOCAL_LOGV) {
+                        Slog.v(TAG, "runExpiration id=" + rollback.info.getRollbackId());
+                    }
                     iter.remove();
                     rollback.delete(mAppDataRollbackHelper);
                 } else if (oldest == null || oldest.isAfter(rollbackTimestamp)) {
@@ -675,6 +693,10 @@
      */
     private boolean enableRollback(
             int installFlags, File newPackageCodePath, @UserIdInt int user, int token) {
+        if (LOCAL_LOGV) {
+            Slog.v(TAG, "enableRollback user=" + user + " token=" + token
+                    + " path=" + newPackageCodePath.getAbsolutePath());
+        }
 
         // Find the session id associated with this install.
         // TODO: It would be nice if package manager or package installer told
@@ -838,6 +860,10 @@
     }
 
     private void snapshotUserDataInternal(String packageName, int[] userIds) {
+        if (LOCAL_LOGV) {
+            Slog.v(TAG, "snapshotUserData pkg=" + packageName
+                    + " users=" + Arrays.toString(userIds));
+        }
         synchronized (mLock) {
             // staged installs
             for (int i = 0; i < mRollbacks.size(); i++) {
@@ -854,6 +880,10 @@
 
     private void restoreUserDataInternal(
             String packageName, int[] userIds, int appId, String seInfo) {
+        if (LOCAL_LOGV) {
+            Slog.v(TAG, "restoreUserData pkg=" + packageName
+                    + " users=" + Arrays.toString(userIds));
+        }
         synchronized (mLock) {
             for (int i = 0; i < mRollbacks.size(); ++i) {
                 Rollback rollback = mRollbacks.get(i);
@@ -1041,6 +1071,9 @@
 
         @Override
         public void onFinished(int sessionId, boolean success) {
+            if (LOCAL_LOGV) {
+                Slog.v(TAG, "SessionCallback.onFinished id=" + sessionId + " success=" + success);
+            }
             NewRollback newRollback;
             synchronized (mLock) {
                 newRollback = getNewRollbackForPackageSessionLocked(sessionId);
@@ -1070,6 +1103,10 @@
      */
     private Rollback completeEnableRollback(NewRollback newRollback, boolean success) {
         Rollback rollback = newRollback.rollback;
+        if (LOCAL_LOGV) {
+            Slog.v(TAG, "completeEnableRollback id="
+                    + rollback.info.getRollbackId() + " success=" + success);
+        }
         if (!success) {
             // The install session was aborted, clean up the pending install.
             rollback.delete(mAppDataRollbackHelper);
@@ -1108,6 +1145,9 @@
 
     @GuardedBy("rollback.getLock")
     private void makeRollbackAvailable(Rollback rollback) {
+        if (LOCAL_LOGV) {
+            Slog.v(TAG, "makeRollbackAvailable id=" + rollback.info.getRollbackId());
+        }
         rollback.makeAvailable();
 
         // TODO(zezeozue): Provide API to explicitly start observing instead
@@ -1280,6 +1320,11 @@
         final Rollback rollback;
         int parentSessionId = parentSession.getSessionId();
 
+        if (LOCAL_LOGV) {
+            Slog.v(TAG, "createNewRollback id=" + rollbackId
+                    + " user=" + userId + " installer=" + installerPackageName);
+        }
+
         if (parentSession.isStaged()) {
             rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId, userId,
                     installerPackageName);
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index fcf87ee..7786833 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -165,7 +165,7 @@
         Settings.Global.putLong(cr, Settings.Global.ADB_ALLOWED_CONNECTION_TIME, 0);
         Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 1);
         Settings.Global.putInt(cr, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
-        Settings.Global.putInt(cr, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
+        Settings.Global.putInt(cr, Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 0);
         Settings.Global.putInt(
                 cr,
                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 45e3c68..db94cf1 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -73,7 +73,9 @@
 import android.view.Display;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.function.pooled.PooledConsumer;
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.util.function.pooled.PooledPredicate;
 import com.android.server.protolog.common.ProtoLog;
 
 import java.io.PrintWriter;
@@ -617,7 +619,7 @@
                 continue;
             }
 
-            stack.findTaskLocked(r, mTmpFindTaskResult);
+            mTmpFindTaskResult.process(r, stack);
             // It is possible to have tasks in multiple stacks with the same root affinity, so
             // we should keep looking after finding an affinity match to see if there is a
             // better match in another stack. Also, task affinity isn't a good enough reason
@@ -1190,12 +1192,11 @@
     }
 
     boolean isUidPresent(int uid) {
-        for (ActivityStack stack : mStacks) {
-            if (stack.isUidPresent(uid)) {
-                return true;
-            }
-        }
-        return false;
+        final PooledPredicate p = PooledLambda.obtainPredicate(
+                ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
+        final boolean isUidPresent = mDisplayContent.getActivity(p) != null;
+        p.recycle();
+        return isUidPresent;
     }
 
     /**
@@ -1291,12 +1292,16 @@
     /** Update and get all UIDs that are present on the display and have access to it. */
     IntArray getPresentUIDs() {
         mDisplayAccessUIDs.clear();
-        for (ActivityStack stack : mStacks) {
-            stack.getPresentUIDs(mDisplayAccessUIDs);
-        }
+        final PooledConsumer c = PooledLambda.obtainConsumer(ActivityDisplay::addActivityUid,
+                PooledLambda.__(ActivityRecord.class), mDisplayAccessUIDs);
+        mDisplayContent.forAllActivities(c);
+        c.recycle();
         return mDisplayAccessUIDs;
     }
 
+    private static void addActivityUid(ActivityRecord r, IntArray uids) {
+        uids.add(r.getUid());
+    }
     /**
      * Checks if system decorations should be shown on this display.
      *
@@ -1449,22 +1454,16 @@
             return null;
         }
 
-        final ArrayList<Task> tasks = mHomeStack.getAllTasks();
-        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = tasks.get(taskNdx);
-            if (!task.isActivityTypeHome()) {
-                continue;
-            }
+        final PooledPredicate p = PooledLambda.obtainPredicate(
+                ActivityDisplay::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class),
+                userId);
+        final ActivityRecord r = mHomeStack.getActivity(p);
+        p.recycle();
+        return r;
+    }
 
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (r.isActivityTypeHome()
-                        && ((userId == UserHandle.USER_ALL) || (r.mUserId == userId))) {
-                    return r;
-                }
-            }
-        }
-        return null;
+    private static boolean isHomeActivityForUser(ActivityRecord r, int userId) {
+        return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId);
     }
 
     boolean isSleeping() {
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 9fa5d9f1..a593ef8 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -546,13 +546,7 @@
 
     /** @return {@code true} if the given task has an activity will be drawn. */
     private static boolean hasActivityToBeDrawn(Task t) {
-        for (int i = t.getChildCount() - 1; i >= 0; --i) {
-            final ActivityRecord r = t.getChildAt(i);
-            if (r.mVisibleRequested && !r.mDrawn && !r.finishing) {
-                return true;
-            }
-        }
-        return false;
+        return t.forAllActivities((r) -> r.mVisibleRequested && !r.mDrawn && !r.finishing);
     }
 
     private void checkVisibility(Task t, ActivityRecord r) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b8b5efd..6af5025 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -301,6 +301,9 @@
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledFunction;
+import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.AttributeCache;
 import com.android.server.LocalServices;
 import com.android.server.am.AppTimeTracker;
@@ -695,12 +698,6 @@
         }
     }
 
-    void dump(PrintWriter pw, String prefix) {
-    }
-
-    /**
-     * Copied from old AppWindowToken.
-     */
     @Override
     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
         final long now = SystemClock.uptimeMillis();
@@ -940,6 +937,10 @@
         }
     }
 
+    void setAppTimeTracker(AppTimeTracker att) {
+        appTimeTracker = att;
+    }
+
     /** Update the saved state of an activity. */
     void setSavedState(@Nullable Bundle savedState) {
         mIcicle = savedState;
@@ -1167,6 +1168,15 @@
 
         super.onParentChanged(newParent, oldParent);
 
+        if (isPersistable()) {
+            if (oldTask != null) {
+                mAtmService.notifyTaskPersisterLocked(oldTask, false);
+            }
+            if (newTask != null) {
+                mAtmService.notifyTaskPersisterLocked(newTask, false);
+            }
+        }
+
         if (oldParent == null && newParent != null) {
             // First time we are adding the activity to the system.
             mVoiceInteraction = newTask.voiceSession != null;
@@ -1261,12 +1271,8 @@
 
         if (prevDc.mFocusedApp == this) {
             prevDc.setFocusedApp(null);
-            final ActivityStack stack = dc.getTopStack();
-            if (stack != null) {
-                final Task task = stack.getTopChild();
-                if (task != null && task.getTopChild() == this) {
-                    dc.setFocusedApp(this);
-                }
+            if (dc.getTopMostActivity() == this) {
+                dc.setFocusedApp(this);
             }
         }
 
@@ -2212,7 +2218,7 @@
                 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
     }
 
-    boolean isAlwaysFocusable() {
+    private boolean isAlwaysFocusable() {
         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
     }
 
@@ -2269,23 +2275,28 @@
         return true;
     }
 
+    void finishIfSubActivity(ActivityRecord parent, String otherResultWho, int otherRequestCode) {
+        if (resultTo != parent
+                || requestCode != otherRequestCode
+                || !Objects.equals(resultWho, otherResultWho)) return;
+
+        finishIfPossible("request-sub", false /* oomAdj */);
+    }
+
     /** Finish all activities in the task with the same affinity as this one. */
-    void finishActivityAffinity() {
-        final ArrayList<ActivityRecord> activities = task.mChildren;
-        for (int index = activities.indexOf(this); index >= 0; --index) {
-            final ActivityRecord cur = activities.get(index);
-            if (!Objects.equals(cur.taskAffinity, taskAffinity)) {
-                break;
-            }
-            cur.finishIfPossible("request-affinity", true /* oomAdj */);
-        }
+    boolean finishIfSameAffinity(ActivityRecord r) {
+        // End search once we get to the activity that doesn't have the same affinity.
+        if (!Objects.equals(r.taskAffinity, taskAffinity)) return true;
+
+        r.finishIfPossible("request-affinity", true /* oomAdj */);
+        return false;
     }
 
     /**
      * Sets the result for activity that started this one, clears the references to activities
      * started for result from this one, and clears new intents.
      */
-    void finishActivityResults(int resultCode, Intent resultData) {
+    private void finishActivityResults(int resultCode, Intent resultData) {
         // Send the result if needed
         if (resultTo != null) {
             if (DEBUG_RESULTS) {
@@ -2384,14 +2395,12 @@
             final Task task = getTask();
             EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),
                     task.mTaskId, shortComponentName, reason);
-            final ArrayList<ActivityRecord> activities = task.mChildren;
-            final int index = activities.indexOf(this);
-            if (index < (task.getChildCount() - 1)) {
+            ActivityRecord next = task.getActivityAbove(this);
+            if (next != null) {
                 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
                     // If the caller asked that this activity (and all above it)
                     // be cleared when the task is reset, don't lose that information,
                     // but propagate it up to the next activity.
-                    final ActivityRecord next = task.getChildAt(index + 1);
                     next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                 }
             }
@@ -2409,7 +2418,7 @@
                 } else {
                     // Only move the next stack to top in its display.
                     final ActivityDisplay display = stack.getDisplay();
-                    final ActivityRecord next = display.topRunningActivity();
+                    next = display.topRunningActivity();
                     if (next != null) {
                         display.positionChildAtTop(next.getActivityStack(),
                                 false /* includingParents */, "finish-display-top");
@@ -2419,7 +2428,8 @@
 
             finishActivityResults(resultCode, resultData);
 
-            final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
+            final boolean endTask = task.getActivityBelow(this) == null
+                    && !task.isClearingToReuseTask();
             final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
             if (isState(RESUMED)) {
                 if (endTask) {
@@ -2479,16 +2489,13 @@
                 // sync with the activity visibility being set for this finishing activity above.
                 // In this case, we can set the visibility of all the task overlay activities when
                 // we detect the last one is finishing to keep them in sync.
-                if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
-                    for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
-                        final ActivityRecord taskOverlay = task.getChildAt(i);
-                        if (!taskOverlay.mTaskOverlay) {
-                            continue;
-                        }
-                        taskOverlay.prepareActivityHideTransitionAnimation(transit);
-                    }
+                if (task.onlyHasTaskOverlayActivities(false /* includeFinishing */)) {
+                    final PooledConsumer c = PooledLambda.obtainConsumer(
+                            ActivityRecord::prepareActivityHideTransitionAnimationIfOvarlay,
+                            PooledLambda.__(ActivityRecord.class), transit);
+                    task.forAllActivities(c);
+                    c.recycle();
                 }
-
                 return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED;
             } else {
                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this);
@@ -2500,6 +2507,12 @@
         }
     }
 
+    private void prepareActivityHideTransitionAnimationIfOvarlay(int transit) {
+        if (mTaskOverlay) {
+            prepareActivityHideTransitionAnimation(transit);
+        }
+    }
+
     private void prepareActivityHideTransitionAnimation(int transit) {
         final DisplayContent dc = getDisplay().mDisplayContent;
         dc.prepareAppTransition(transit, false);
@@ -3271,15 +3284,16 @@
      * immediately finishes after, so we have to transfer T to M.
      */
     void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
-        for (int i = task.mChildren.size() - 1; i >= 0; i--) {
-            final ActivityRecord fromActivity = task.mChildren.get(i);
-            if (fromActivity == this) {
-                return;
-            }
-            if (!fromActivity.mVisibleRequested && transferStartingWindow(fromActivity.token)) {
-                return;
-            }
-        }
+        final PooledFunction p = PooledLambda.obtainFunction(ActivityRecord::transferStartingWindow,
+                this, PooledLambda.__(ActivityRecord.class));
+        task.forAllActivities(p);
+        p.recycle();
+    }
+
+    private boolean transferStartingWindow(ActivityRecord fromActivity) {
+        if (fromActivity == this) return true;
+
+        return !fromActivity.mVisibleRequested && transferStartingWindow(fromActivity.token);
     }
 
     void checkKeyguardFlagsChanged() {
@@ -3351,7 +3365,7 @@
         if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
             return true;
         } else if (mInheritShownWhenLocked) {
-            final ActivityRecord r = getActivityBelow();
+            final ActivityRecord r = task.getActivityBelow(this);
             return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
                     || r.containsShowWhenLockedWindow());
         } else {
@@ -3376,19 +3390,6 @@
                 true /* topToBottom */);
     }
 
-    /**
-     * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
-     * such activity exists.
-     */
-    @Nullable
-    private ActivityRecord getActivityBelow() {
-        final int pos = task.mChildren.indexOf(this);
-        if (pos == -1) {
-            throw new IllegalStateException("Activity not found in its task");
-        }
-        return pos == 0 ? null : task.getChildAt(pos - 1);
-    }
-
     WindowState getImeTargetBelowWindow(WindowState w) {
         final int index = mChildren.indexOf(w);
         if (index > 0) {
@@ -3432,7 +3433,8 @@
     }
 
     @Override
-    boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
+    boolean forAllActivities(
+            Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
         return callback.apply(this);
     }
 
@@ -3609,7 +3611,9 @@
                 clearOptionsLocked(false /* withAbort */);
             } else {
                 // This will clear the options for all the ActivityRecords for this Task.
-                task.clearAllPendingOptions();
+                task.forAllActivities((r) -> {
+                    r.clearOptionsLocked(false /* withAbort */);
+                });
             }
         }
     }
@@ -4602,16 +4606,15 @@
         }
 
         // Check if position in task allows to become paused
-        final int positionInTask = task.mChildren.indexOf(this);
-        if (positionInTask == -1) {
+        if (!task.hasChild(this)) {
             throw new IllegalStateException("Activity not found in its task");
         }
-        if (positionInTask == task.getChildCount() - 1) {
+        final ActivityRecord activityAbove = task.getActivityAbove(this);
+        if (activityAbove == null) {
             // It's the topmost activity in the task - should become resumed now
             return true;
         }
         // Check if activity above is finishing now and this one becomes the topmost in task.
-        final ActivityRecord activityAbove = task.getChildAt(positionInTask + 1);
         if (activityAbove.finishing) {
             return true;
         }
@@ -4667,7 +4670,7 @@
         stopped = false;
 
         if (isActivityTypeHome()) {
-            mStackSupervisor.updateHomeProcess(task.getChildAt(0).app);
+            mStackSupervisor.updateHomeProcess(task.getBottomMostActivity().app);
         }
 
         if (nowVisible) {
@@ -5294,6 +5297,10 @@
                 && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
     }
 
+    boolean canBeTopRunning() {
+        return !finishing && okToShowLocked();
+    }
+
     /**
      * This method will return true if the activity is either visible, is becoming visible, is
      * currently pausing, or is resumed.
@@ -5325,13 +5332,12 @@
 
     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
-        if (r == null) {
+        if (r == null || r.getParent() == null) {
             return INVALID_TASK_ID;
         }
         final Task task = r.task;
-        final int activityNdx = task.mChildren.indexOf(r);
-        if (activityNdx < 0
-                || (onlyRoot && activityNdx > task.findRootIndex(true /* effectiveRoot */))) {
+        if (onlyRoot && r.compareTo(task.getRootActivity(
+                false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)) > 0) {
             return INVALID_TASK_ID;
         }
         return task.mTaskId;
@@ -7222,6 +7228,10 @@
         return info.applicationInfo.uid;
     }
 
+    boolean isUid(int uid) {
+        return info.applicationInfo.uid == uid;
+    }
+
     int getPid() {
         return app != null ? app.getPid() : 0;
     }
@@ -7285,13 +7295,8 @@
         if (task == null) {
             return false;
         }
-        final ActivityRecord rootActivity = task.getRootActivity();
-        if (rootActivity != null) {
-            return this == rootActivity;
-        }
-        // No non-finishing activity found. In this case the bottom-most activity is considered to
-        // be the root.
-        return task.getChildAt(0) == this;
+        final ActivityRecord rootActivity = task.getRootActivity(true);
+        return this == rootActivity;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 6ddbb0d..bb3126b 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -76,12 +76,10 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
@@ -107,7 +105,6 @@
 import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
 import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
-import static com.android.server.wm.RootActivityContainer.FindTaskResult;
 import static com.android.server.wm.StackProto.ADJUSTED_BOUNDS;
 import static com.android.server.wm.StackProto.ADJUSTED_FOR_IME;
 import static com.android.server.wm.StackProto.ADJUST_DIVIDER_AMOUNT;
@@ -143,12 +140,10 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.net.Uri;
 import android.os.Binder;
 import android.os.Debug;
 import android.os.Handler;
@@ -162,7 +157,6 @@
 import android.service.voice.IVoiceInteractionSession;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
-import android.util.IntArray;
 import android.util.Log;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
@@ -178,7 +172,10 @@
 import com.android.internal.os.logging.MetricsLoggerWrapper;
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DockedDividerUtils;
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledFunction;
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.util.function.pooled.PooledPredicate;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
@@ -189,14 +186,12 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
-import java.util.Set;
 import java.util.function.Consumer;
 
 /**
  * State and management of a single stack of activities.
  */
-class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarget,
-        ConfigurationContainerListener {
+class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarget {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM;
     static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_APP = TAG + POSTFIX_APP;
@@ -499,7 +494,7 @@
                 case DESTROY_ACTIVITIES_MSG: {
                     ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
                     synchronized (mService.mGlobalLock) {
-                        destroyActivitiesLocked(args.mOwner, args.mReason);
+                        destroyActivities(args.mOwner, args.mReason);
                     }
                 } break;
                 case TRANSLUCENT_TIMEOUT_MSG: {
@@ -514,13 +509,226 @@
     private static final ResetTargetTaskHelper sResetTargetTaskHelper = new ResetTargetTaskHelper();
     private final EnsureActivitiesVisibleHelper mEnsureActivitiesVisibleHelper =
             new EnsureActivitiesVisibleHelper(this);
+    private final EnsureVisibleActivitiesConfigHelper mEnsureVisibleActivitiesConfigHelper =
+            new EnsureVisibleActivitiesConfigHelper();
+    private class EnsureVisibleActivitiesConfigHelper {
+        private boolean mUpdateConfig;
+        private boolean mPreserveWindow;
+        private boolean mBehindFullscreen;
 
-    int numActivities() {
-        int count = 0;
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            count += getChildAt(taskNdx).getChildCount();
+        void reset(boolean preserveWindow) {
+            mPreserveWindow = preserveWindow;
+            mUpdateConfig = false;
+            mBehindFullscreen = false;
         }
-        return count;
+
+        void process(ActivityRecord start, boolean preserveWindow) {
+            if (start == null || !start.mVisibleRequested) {
+                return;
+            }
+            reset(preserveWindow);
+
+            final PooledFunction f = PooledLambda.obtainFunction(
+                    EnsureVisibleActivitiesConfigHelper::processActivity, this,
+                    PooledLambda.__(ActivityRecord.class));
+            forAllActivities(f, start.getTask(), true /*includeBoundary*/,
+                    true /*traverseTopToBottom*/);
+            f.recycle();
+
+            if (mUpdateConfig) {
+                // Ensure the resumed state of the focus activity if we updated the configuration of
+                // any activity.
+                mRootActivityContainer.resumeFocusedStacksTopActivities();
+            }
+        }
+
+        boolean processActivity(ActivityRecord r) {
+            mUpdateConfig |= r.ensureActivityConfiguration(0 /*globalChanges*/, mPreserveWindow);
+            mBehindFullscreen |= r.occludesParent();
+            return mBehindFullscreen;
+        }
+    }
+
+    private final CheckBehindFullscreenActivityHelper mCheckBehindFullscreenActivityHelper =
+            new CheckBehindFullscreenActivityHelper();
+    private class CheckBehindFullscreenActivityHelper {
+        private boolean mAboveTop;
+        private boolean mBehindFullscreenActivity;
+        private ActivityRecord mToCheck;
+        private Consumer<ActivityRecord> mHandleBehindFullscreenActivity;
+        private boolean mHandlingOccluded;
+
+        private void reset(ActivityRecord toCheck,
+                Consumer<ActivityRecord> handleBehindFullscreenActivity) {
+            mToCheck = toCheck;
+            mHandleBehindFullscreenActivity = handleBehindFullscreenActivity;
+            mAboveTop = true;
+            mBehindFullscreenActivity = false;
+
+            if (!shouldBeVisible(null)) {
+                // The stack is not visible, so no activity in it should be displaying a starting
+                // window. Mark all activities below top and behind fullscreen.
+                mAboveTop = false;
+                mBehindFullscreenActivity = true;
+            }
+
+            mHandlingOccluded = mToCheck == null && mHandleBehindFullscreenActivity != null;
+        }
+
+        boolean process(ActivityRecord toCheck,
+                Consumer<ActivityRecord> handleBehindFullscreenActivity) {
+            reset(toCheck, handleBehindFullscreenActivity);
+
+            if (!mHandlingOccluded && mBehindFullscreenActivity) {
+                return true;
+            }
+
+            final ActivityRecord topActivity = topRunningActivityLocked();
+            final PooledFunction f = PooledLambda.obtainFunction(
+                    CheckBehindFullscreenActivityHelper::processActivity, this,
+                    PooledLambda.__(ActivityRecord.class), topActivity);
+            forAllActivities(f);
+            f.recycle();
+
+            return mBehindFullscreenActivity;
+        }
+
+        private boolean processActivity(ActivityRecord r, ActivityRecord topActivity) {
+            if (mAboveTop) {
+                if (r == topActivity) {
+                    if (r == mToCheck) {
+                        // It is the top activity in a visible stack.
+                        mBehindFullscreenActivity = false;
+                        return true;
+                    }
+                    mAboveTop = false;
+                }
+                mBehindFullscreenActivity |= r.occludesParent();
+                return false;
+            }
+
+            if (mHandlingOccluded) {
+                mHandleBehindFullscreenActivity.accept(r);
+            } else if (r == mToCheck) {
+                return true;
+            } else if (mBehindFullscreenActivity) {
+                // It is occluded before {@param toCheck} is found.
+                return true;
+            }
+            mBehindFullscreenActivity |= r.occludesParent();
+            return false;
+        }
+    }
+
+    // TODO: Can we just loop through WindowProcessController#mActivities instead of doing this?
+    private final RemoveHistoryRecordsForApp mRemoveHistoryRecordsForApp =
+            new RemoveHistoryRecordsForApp();
+    private class RemoveHistoryRecordsForApp {
+        private boolean mHasVisibleActivities;
+        private boolean mIsProcessRemoved;
+        private WindowProcessController mApp;
+        private ArrayList<ActivityRecord> mToRemove = new ArrayList<>();
+
+        boolean process(WindowProcessController app) {
+            mToRemove.clear();
+            mHasVisibleActivities = false;
+            mApp = app;
+            mIsProcessRemoved = app.isRemoved();
+            if (mIsProcessRemoved) {
+                // The package of the died process should be force-stopped, so make its activities
+                // as finishing to prevent the process from being started again if the next top
+                // (or being visible) activity also resides in the same process.
+                app.makeFinishingForProcessRemoved();
+            }
+
+            final PooledConsumer c = PooledLambda.obtainConsumer(
+                    RemoveHistoryRecordsForApp::addActivityToRemove, this,
+                    PooledLambda.__(ActivityRecord.class));
+            forAllActivities(c);
+            c.recycle();
+
+            while (!mToRemove.isEmpty()) {
+                processActivity(mToRemove.remove(0));
+            }
+
+            mApp = null;
+            return mHasVisibleActivities;
+        }
+
+        private void addActivityToRemove(ActivityRecord r) {
+            if (r.app == mApp) {
+                mToRemove.add(r);
+            }
+        }
+
+        private void processActivity(ActivityRecord r) {
+            if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record " + r + ": app=" + r.app);
+
+            if (r.app != mApp) {
+                return;
+            }
+            if (r.isVisible() || r.mVisibleRequested) {
+                // While an activity launches a new activity, it's possible that the old
+                // activity is already requested to be hidden (mVisibleRequested=false), but
+                // this visibility is not yet committed, so isVisible()=true.
+                mHasVisibleActivities = true;
+            }
+            final boolean remove;
+            if ((r.mRelaunchReason == RELAUNCH_REASON_WINDOWING_MODE_RESIZE
+                    || r.mRelaunchReason == RELAUNCH_REASON_FREE_RESIZE)
+                    && r.launchCount < 3 && !r.finishing) {
+                // If the process crashed during a resize, always try to relaunch it, unless
+                // it has failed more than twice. Skip activities that's already finishing
+                // cleanly by itself.
+                remove = false;
+            } else if ((!r.hasSavedState() && !r.stateNotNeeded
+                    && !r.isState(ActivityState.RESTARTING_PROCESS)) || r.finishing) {
+                // Don't currently have state for the activity, or
+                // it is finishing -- always remove it.
+                remove = true;
+            } else if (!r.mVisibleRequested && r.launchCount > 2
+                    && r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
+                // We have launched this activity too many times since it was
+                // able to run, so give up and remove it.
+                // (Note if the activity is visible, we don't remove the record.
+                // We leave the dead window on the screen but the process will
+                // not be restarted unless user explicitly tap on it.)
+                remove = true;
+            } else {
+                // The process may be gone, but the activity lives on!
+                remove = false;
+            }
+            if (remove) {
+                if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE,
+                        "Removing activity " + r + " from stack "
+                                + ": hasSavedState=" + r.hasSavedState()
+                                + " stateNotNeeded=" + r.stateNotNeeded
+                                + " finishing=" + r.finishing
+                                + " state=" + r.getState() + " callers=" + Debug.getCallers(5));
+                if (!r.finishing || mIsProcessRemoved) {
+                    Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
+                    EventLogTags.writeWmFinishActivity(r.mUserId,
+                        System.identityHashCode(r), r.getTask().mTaskId,
+                            r.shortComponentName, "proc died without state saved");
+                }
+            } else {
+                // We have the current state for this activity, so
+                // it can be restarted later when needed.
+                if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null");
+                if (DEBUG_APP) Slog.v(TAG_APP,
+                        "Clearing app during removeHistory for activity " + r);
+                r.app = null;
+                // Set nowVisible to previous visible state. If the app was visible while
+                // it died, we leave the dead window on screen so it's basically visible.
+                // This is needed when user later tap on the dead window, we need to stop
+                // other apps when user transfers focus to the restarted activity.
+                r.nowVisible = r.mVisibleRequested;
+            }
+            r.cleanUp(true /* cleanServices */, true /* setState */);
+            if (remove) {
+                r.removeFromHistory("appDied");
+            }
+        }
     }
 
     ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
@@ -941,7 +1149,7 @@
         }
     }
 
-    boolean updateBoundsAllowed(Rect bounds) {
+    private boolean updateBoundsAllowed(Rect bounds) {
         if (!mUpdateBoundsDeferred) {
             return true;
         }
@@ -954,7 +1162,7 @@
         return false;
     }
 
-    boolean updateDisplayedBoundsAllowed(Rect bounds) {
+    private boolean updateDisplayedBoundsAllowed(Rect bounds) {
         if (!mUpdateBoundsDeferred) {
             return true;
         }
@@ -971,47 +1179,29 @@
         return topRunningActivityLocked(false /* focusableOnly */);
     }
 
-    void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
-        outActivities.clear();
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            getChildAt(taskNdx).getAllRunningVisibleActivitiesLocked(outActivities);
-        }
-    }
-
     ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            ActivityRecord r = getChildAt(taskNdx).topRunningActivityLocked();
-            if (r != null && (!focusableOnly || r.isFocusable())) {
-                return r;
-            }
+        // Split into 2 to avoid object creation due to variable capture.
+        if (focusableOnly) {
+            return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
+        } else {
+            return getActivity(ActivityRecord::canBeTopRunning);
         }
-        return null;
     }
 
-    ActivityRecord topRunningNonOverlayTaskActivity() {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (!r.finishing && !r.mTaskOverlay) {
-                    return r;
-                }
-            }
-        }
-        return null;
+    private ActivityRecord topRunningNonOverlayTaskActivity() {
+        return getActivity((r) -> (r.canBeTopRunning() && !r.mTaskOverlay));
     }
 
     ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (!r.finishing && !r.delayedResume && r != notTop && r.okToShowLocked()) {
-                    return r;
-                }
-            }
-        }
-        return null;
+        final PooledPredicate p = PooledLambda.obtainPredicate(ActivityStack::isTopRunningNonDelayed
+                , PooledLambda.__(ActivityRecord.class), notTop);
+        final ActivityRecord r = getActivity(p);
+        p.recycle();
+        return r;
+    }
+
+    private static boolean isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop) {
+        return !r.delayedResume && r != notTop && r.canBeTopRunning();
     }
 
     /**
@@ -1024,30 +1214,19 @@
      * @return Returns the HistoryRecord of the next activity on the stack.
      */
     final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            Task task = getChildAt(taskNdx);
-            if (task.mTaskId == taskId) {
-                continue;
-            }
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                // Note: the taskId check depends on real taskId fields being non-zero
-                if (!r.finishing && (token != r.appToken) && r.okToShowLocked()) {
-                    return r;
-                }
-            }
-        }
-        return null;
+        final PooledPredicate p = PooledLambda.obtainPredicate(ActivityStack::isTopRunning,
+                PooledLambda.__(ActivityRecord.class), taskId, token);
+        final ActivityRecord r = getActivity(p);
+        p.recycle();
+        return r;
+    }
+
+    private static boolean isTopRunning(ActivityRecord r, int taskId, IBinder notTop) {
+        return r.getTask().mTaskId == taskId && r.appToken != notTop && r.canBeTopRunning();
     }
 
     ActivityRecord getTopNonFinishingActivity() {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final ActivityRecord r = getChildAt(taskNdx).getTopNonFinishingActivity();
-            if (r != null) {
-                return r;
-            }
-        }
-        return null;
+        return getTopActivity(false /*includeFinishing*/, true /*includeOverlays*/);
     }
 
     final Task topTask() {
@@ -1087,35 +1266,6 @@
         return null;
     }
 
-    boolean isInStackLocked(Task task) {
-        return mChildren.contains(task);
-    }
-
-    /** Checks if there are tasks with specific UID in the stack. */
-    boolean isUidPresent(int uid) {
-        for (int j = getChildCount() - 1; j >= 0; --j) {
-            final Task task = getChildAt(j);
-            for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
-                final ActivityRecord r = task.getChildAt(i);
-                if (r.getUid() == uid) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /** Get all UIDs that are present in the stack. */
-    void getPresentUIDs(IntArray presentUIDs) {
-        for (int j = getChildCount() - 1; j >= 0; --j) {
-            final Task task = getChildAt(j);
-            for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
-                final ActivityRecord r = task.getChildAt(i);
-                presentUIDs.add(r.getUid());
-            }
-        }
-    }
-
     /** @return true if the stack can only contain one task */
     boolean isSingleTaskInstance() {
         final ActivityDisplay display = getDisplay();
@@ -1232,138 +1382,6 @@
         return display != null && !display.isRemoved();
     }
 
-    /**
-     * Returns the top activity in any existing task matching the given Intent in the input result.
-     * Returns null if no such task is found.
-     */
-    void findTaskLocked(ActivityRecord target, FindTaskResult result) {
-        Intent intent = target.intent;
-        ActivityInfo info = target.info;
-        ComponentName cls = intent.getComponent();
-        if (info.targetActivity != null) {
-            cls = new ComponentName(info.packageName, info.targetActivity);
-        }
-        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
-        boolean isDocument = intent != null & intent.isDocument();
-        // If documentData is non-null then it must match the existing task data.
-        Uri documentData = isDocument ? intent.getData() : null;
-
-        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            if (task.voiceSession != null) {
-                // We never match voice sessions; those always run independently.
-                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
-                continue;
-            }
-            if (task.mUserId != userId) {
-                // Looking for a different task.
-                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
-                continue;
-            }
-
-            // Overlays should not be considered as the task's logical top activity.
-            final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */);
-            if (r == null || r.finishing || r.mUserId != userId ||
-                    r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
-                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
-                continue;
-            }
-            if (!r.hasCompatibleActivityType(target)) {
-                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
-                continue;
-            }
-
-            final Intent taskIntent = task.intent;
-            final Intent affinityIntent = task.affinityIntent;
-            final boolean taskIsDocument;
-            final Uri taskDocumentData;
-            if (taskIntent != null && taskIntent.isDocument()) {
-                taskIsDocument = true;
-                taskDocumentData = taskIntent.getData();
-            } else if (affinityIntent != null && affinityIntent.isDocument()) {
-                taskIsDocument = true;
-                taskDocumentData = affinityIntent.getData();
-            } else {
-                taskIsDocument = false;
-                taskDocumentData = null;
-            }
-
-            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
-                    + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
-                    + "/aff=" + r.getTask().rootAffinity + " to new cls="
-                    + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
-            // TODO Refactor to remove duplications. Check if logic can be simplified.
-            if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
-                    && Objects.equals(documentData, taskDocumentData)) {
-                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
-                //dump();
-                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
-                        "For Intent " + intent + " bringing to top: " + r.intent);
-                result.mRecord = r;
-                result.mIdealMatch = true;
-                break;
-            } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
-                    affinityIntent.getComponent().compareTo(cls) == 0 &&
-                    Objects.equals(documentData, taskDocumentData)) {
-                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
-                //dump();
-                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
-                        "For Intent " + intent + " bringing to top: " + r.intent);
-                result.mRecord = r;
-                result.mIdealMatch = true;
-                break;
-            } else if (!isDocument && !taskIsDocument
-                    && result.mRecord == null && task.rootAffinity != null) {
-                if (task.rootAffinity.equals(target.taskAffinity)) {
-                    if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
-                    // It is possible for multiple tasks to have the same root affinity especially
-                    // if they are in separate stacks. We save off this candidate, but keep looking
-                    // to see if there is a better candidate.
-                    result.mRecord = r;
-                    result.mIdealMatch = false;
-                }
-            } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
-        }
-    }
-
-    /**
-     * Returns the first activity (starting from the top of the stack) that
-     * is the same as the given activity.  Returns null if no such activity
-     * is found.
-     */
-    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
-                                      boolean compareIntentFilters) {
-        ComponentName cls = intent.getComponent();
-        if (info.targetActivity != null) {
-            cls = new ComponentName(info.packageName, info.targetActivity);
-        }
-        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
-
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (!r.okToShowLocked()) {
-                    continue;
-                }
-                if (!r.finishing && r.mUserId == userId) {
-                    if (compareIntentFilters) {
-                        if (r.intent.filterEquals(intent)) {
-                            return r;
-                        }
-                    } else {
-                        if (r.intent.getComponent().equals(cls)) {
-                            return r;
-                        }
-                    }
-                }
-            }
-        }
-
-        return null;
-    }
-
     // TODO: Should each user have there own stacks?
     @Override
     void switchUser(int userId) {
@@ -1401,35 +1419,13 @@
 
     void awakeFromSleepingLocked() {
         // Ensure activities are no longer sleeping.
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                r.setSleeping(false);
-            }
-        }
+        forAllActivities((Consumer<ActivityRecord>) (r) -> r.setSleeping(false));
         if (mPausingActivity != null) {
             Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause");
             activityPausedLocked(mPausingActivity.appToken, true);
         }
     }
 
-    void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
-        final String packageName = aInfo.packageName;
-        final int userId = UserHandle.getUserId(aInfo.uid);
-
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord ar = task.getChildAt(activityNdx);
-
-                if ((userId == ar.mUserId) && packageName.equals(ar.packageName)) {
-                    ar.updateApplicationInfo(aInfo);
-                }
-            }
-        }
-    }
-
     void checkReadyForSleep() {
         if (shouldSleepActivities() && goToSleepIfPossible(false /* shuttingDown */)) {
             mStackSupervisor.checkReadyForSleepLocked(true /* allowDelay */);
@@ -1495,15 +1491,11 @@
 
         // Make sure any paused or stopped but visible activities are now sleeping.
         // This ensures that the activity's onStop() is called.
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (r.isState(STARTED, STOPPING, STOPPED, PAUSED, PAUSING)) {
-                    r.setSleeping(true);
-                }
+        forAllActivities((r) -> {
+            if (r.isState(STARTED, STOPPING, STOPPED, PAUSED, PAUSING)) {
+                r.setSleeping(true);
             }
-        }
+        });
     }
 
     private boolean containsActivityFromStack(List<ActivityRecord> rs) {
@@ -1779,31 +1771,32 @@
         if (!isAttached() || mForceHidden) {
             return true;
         }
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
+        final PooledPredicate p = PooledLambda.obtainPredicate(ActivityStack::isOpaqueActivity,
+                PooledLambda.__(ActivityRecord.class), starting);
+        final ActivityRecord opaque = getActivity(p);
+        p.recycle();
+        return opaque == null;
+    }
 
-                if (r.finishing) {
-                    // We don't factor in finishing activities when determining translucency since
-                    // they will be gone soon.
-                    continue;
-                }
-
-                if (!r.visibleIgnoringKeyguard && r != starting) {
-                    // Also ignore invisible activities that are not the currently starting
-                    // activity (about to be visible).
-                    continue;
-                }
-
-                if (r.occludesParent() || r.hasWallpaper) {
-                    // Stack isn't translucent if it has at least one fullscreen activity
-                    // that is visible.
-                    return false;
-                }
-            }
+    private static boolean isOpaqueActivity(ActivityRecord r, ActivityRecord starting) {
+        if (r.finishing) {
+            // We don't factor in finishing activities when determining translucency since
+            // they will be gone soon.
+            return false;
         }
-        return true;
+
+        if (!r.visibleIgnoringKeyguard && r != starting) {
+            // Also ignore invisible activities that are not the currently starting
+            // activity (about to be visible).
+            return false;
+        }
+
+        if (r.occludesParent() || r.hasWallpaper) {
+            // Stack isn't translucent if it has at least one fullscreen activity
+            // that is visible.
+            return true;
+        }
+        return false;
     }
 
     boolean isTopStackOnDisplay() {
@@ -1958,20 +1951,6 @@
                 : STACK_VISIBILITY_VISIBLE;
     }
 
-    final int rankTaskLayers(int baseLayer) {
-        int layer = 0;
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            ActivityRecord r = task.topRunningActivityLocked();
-            if (r == null || r.finishing || !r.mVisibleRequested) {
-                task.mLayerRank = -1;
-            } else {
-                task.mLayerRank = baseLayer + layer++;
-            }
-        }
-        return layer;
-    }
-
     /**
      * Make sure that all activities that need to be visible in the stack (that is, they
      * currently can be seen by the user) actually are and update their configuration.
@@ -2006,12 +1985,6 @@
         }
     }
 
-    void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            getChildAt(taskNdx).addStartingWindowsForVisibleActivities(taskSwitch);
-        }
-    }
-
     /**
      * @return true if the top visible activity wants to occlude the Keyguard, false otherwise
      */
@@ -2127,18 +2100,6 @@
         mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
     }
 
-    void clearOtherAppTimeTrackers(AppTimeTracker except) {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if ( r.appTimeTracker != except) {
-                    r.appTimeTracker = null;
-                }
-            }
-        }
-    }
-
     /**
      * Called as activities below the top translucent activity are redrawn. When the last one is
      * redrawn notify the top activity by calling
@@ -2186,50 +2147,8 @@
      */
     boolean checkBehindFullscreenActivity(ActivityRecord toCheck,
             Consumer<ActivityRecord> handleBehindFullscreenActivity) {
-        boolean aboveTop = true;
-        boolean behindFullscreenActivity = false;
-
-        if (!shouldBeVisible(null)) {
-            // The stack is not visible, so no activity in it should be displaying a starting
-            // window. Mark all activities below top and behind fullscreen.
-            aboveTop = false;
-            behindFullscreenActivity = true;
-        }
-
-        final boolean handlingOccluded = toCheck == null && handleBehindFullscreenActivity != null;
-        if (!handlingOccluded && behindFullscreenActivity) {
-            return true;
-        }
-
-        final ActivityRecord topActivity = topRunningActivityLocked();
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (aboveTop) {
-                    if (r == topActivity) {
-                        if (r == toCheck) {
-                            // It is the top activity in a visible stack.
-                            return false;
-                        }
-                        aboveTop = false;
-                    }
-                    behindFullscreenActivity |= r.occludesParent();
-                    continue;
-                }
-
-                if (handlingOccluded) {
-                    handleBehindFullscreenActivity.accept(r);
-                } else if (r == toCheck) {
-                    return behindFullscreenActivity;
-                } else if (behindFullscreenActivity) {
-                    // It is occluded before {@param toCheck} is found.
-                    return true;
-                }
-                behindFullscreenActivity |= r.occludesParent();
-            }
-        }
-        return behindFullscreenActivity;
+        return mCheckBehindFullscreenActivityHelper.process(
+                toCheck, handleBehindFullscreenActivity);
     }
 
     /**
@@ -2787,7 +2706,7 @@
                     }
                     break;
                 } else if (!isOccluded) {
-                    isOccluded = task.forAllActivities(ActivityRecord::occludesParent);
+                    isOccluded = task.getActivity(ActivityRecord::occludesParent) != null;
                 }
             }
         }
@@ -2812,7 +2731,7 @@
 
         // The transition animation and starting window are not needed if {@code allowMoveToFront}
         // is false, because the activity won't be visible.
-        if ((!isHomeOrRecentsStack() || numActivities() > 0) && allowMoveToFront) {
+        if ((!isHomeOrRecentsStack() || hasActivity()) && allowMoveToFront) {
             final DisplayContent dc = getDisplay().mDisplayContent;
             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                     "Prepare open transition: starting " + r);
@@ -2915,8 +2834,7 @@
         return true;
     }
 
-    private boolean isTaskSwitch(ActivityRecord r,
-            ActivityRecord topFocusedActivity) {
+    private boolean isTaskSwitch(ActivityRecord r, ActivityRecord topFocusedActivity) {
         return topFocusedActivity != null && r.getTask() != topFocusedActivity.getTask();
     }
 
@@ -2996,23 +2914,6 @@
         return stack;
     }
 
-    /** Finish all activities that were started for result from the specified activity. */
-    final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (r.resultTo == self && r.requestCode == requestCode) {
-                    if ((r.resultWho == null && resultWho == null) ||
-                        (r.resultWho != null && r.resultWho.equals(resultWho))) {
-                        r.finishIfPossible("request-sub", false /* oomAdj */);
-                    }
-                }
-            }
-        }
-        mService.updateOomAdj();
-    }
-
     /**
      * Finish the topmost activity that belongs to the crashed app. We may also finish the activity
      * that requested launch of the crashed one to prevent launch-crash loop.
@@ -3023,103 +2924,84 @@
      */
     final Task finishTopCrashedActivityLocked(WindowProcessController app, String reason) {
         ActivityRecord r = topRunningActivityLocked();
-        Task finishedTask = null;
         if (r == null || r.app != app) {
             return null;
         }
         Slog.w(TAG, "  Force finishing activity "
                 + r.intent.getComponent().flattenToShortString());
-        finishedTask = r.getTask();
-        int taskNdx = mChildren.indexOf(finishedTask);
-        final Task task = finishedTask;
-        int activityNdx = task.mChildren.indexOf(r);
+        Task finishedTask = r.getTask();
         getDisplay().mDisplayContent.prepareAppTransition(
                 TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
         r.finishIfPossible(reason, false /* oomAdj */);
-        finishedTask = task;
-        // Also terminate any activities below it that aren't yet
-        // stopped, to avoid a situation where one will get
-        // re-start our crashing activity once it gets resumed again.
-        --activityNdx;
-        if (activityNdx < 0) {
-            do {
-                --taskNdx;
-                if (taskNdx < 0) {
-                    break;
-                }
-                activityNdx = getChildAt(taskNdx).getChildCount() - 1;
-            } while (activityNdx < 0);
-        }
-        if (activityNdx >= 0) {
-            r = getChildAt(taskNdx).getChildAt(activityNdx);
-            if (r.isState(STARTED, RESUMED, PAUSING, PAUSED)) {
-                if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) {
+
+        // Also terminate any activities below it that aren't yet stopped, to avoid a situation
+        // where one will get re-start our crashing activity once it gets resumed again.
+        final ActivityRecord activityBelow = getActivityBelow(r);
+        if (activityBelow != null) {
+            if (activityBelow.isState(STARTED, RESUMED, PAUSING, PAUSED)) {
+                if (!activityBelow.isActivityTypeHome()
+                        || mService.mHomeProcess != activityBelow.app) {
                     Slog.w(TAG, "  Force finishing activity "
-                            + r.intent.getComponent().flattenToShortString());
-                    r.finishIfPossible(reason, false /* oomAdj */);
+                            + activityBelow.intent.getComponent().flattenToShortString());
+                    activityBelow.finishIfPossible(reason, false /* oomAdj */);
                 }
             }
         }
+
         return finishedTask;
     }
 
-    final void finishVoiceTask(IVoiceInteractionSession session) {
-        IBinder sessionBinder = session.asBinder();
-        boolean didOne = false;
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            Task tr = getChildAt(taskNdx);
-            if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) {
-                for (int activityNdx = tr.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                    ActivityRecord r = tr.getChildAt(activityNdx);
-                    if (!r.finishing) {
-                        r.finishIfPossible("finish-voice", false /* oomAdj */);
-                        didOne = true;
-                    }
-                }
-            } else {
-                // Check if any of the activities are using voice
-                for (int activityNdx = tr.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                    ActivityRecord r = tr.getChildAt(activityNdx);
-                    if (r.voiceSession != null && r.voiceSession.asBinder() == sessionBinder) {
-                        // Inform of cancellation
-                        r.clearVoiceSessionLocked();
-                        try {
-                            r.app.getThread().scheduleLocalVoiceInteractionStarted(
-                                    r.appToken, null);
-                        } catch (RemoteException re) {
-                            // Ok
-                        }
-                        mService.finishRunningVoiceLocked();
-                        break;
-                    }
-                }
-            }
-        }
+    void finishVoiceTask(IVoiceInteractionSession session) {
+        final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::finishIfVoiceTask,
+                PooledLambda.__(Task.class), session.asBinder());
+        forAllTasks(c);
+        c.recycle();
+    }
 
-        if (didOne) {
-            mService.updateOomAdj();
+    private static void finishIfVoiceTask(Task tr, IBinder binder) {
+        if (tr.voiceSession != null && tr.voiceSession.asBinder() == binder) {
+            tr.forAllActivities((r) -> {
+                if (r.finishing) return;
+                r.finishIfPossible("finish-voice", false /* oomAdj */);
+                tr.mAtmService.updateOomAdj();
+            });
+        } else {
+            // Check if any of the activities are using voice
+            final PooledFunction f = PooledLambda.obtainFunction(
+                    ActivityStack::finishIfVoiceActivity, PooledLambda.__(ActivityRecord.class),
+                    binder);
+            tr.forAllActivities(f);
+            f.recycle();
         }
     }
 
+    private static boolean finishIfVoiceActivity(ActivityRecord r, IBinder binder) {
+        if (r.voiceSession == null || r.voiceSession.asBinder() != binder) return false;
+        // Inform of cancellation
+        r.clearVoiceSessionLocked();
+        try {
+            r.app.getThread().scheduleLocalVoiceInteractionStarted(r.appToken, null);
+        } catch (RemoteException re) {
+            // Ok Boomer...
+        }
+        r.mAtmService.finishRunningVoiceLocked();
+        return true;
+    }
+
     /** Finish all activities in the stack without waiting. */
     void finishAllActivitiesImmediately() {
-        boolean noActivitiesInStack = true;
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                noActivitiesInStack = false;
-                Slog.d(TAG, "finishAllActivitiesImmediatelyLocked: finishing " + r);
-                r.destroyIfPossible("finishAllActivitiesImmediatelyLocked");
-            }
-        }
-        if (noActivitiesInStack) {
+        if (!hasChild()) {
             removeIfPossible();
+            return;
         }
+        forAllActivities((r) -> {
+            Slog.d(TAG, "finishAllActivitiesImmediatelyLocked: finishing " + r);
+            r.destroyIfPossible("finishAllActivitiesImmediately");
+        });
     }
 
     /** @return true if the stack behind this one is a standard activity type. */
-    boolean inFrontOfStandardStack() {
+    private boolean inFrontOfStandardStack() {
         final ActivityDisplay display = getDisplay();
         if (display == null) {
             return false;
@@ -3166,28 +3048,25 @@
         return false;
     }
 
-    final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
+    boolean navigateUpTo(ActivityRecord srec, Intent destIntent, int resultCode,
             Intent resultData) {
         final Task task = srec.getTask();
-        final ArrayList<ActivityRecord> activities = task.mChildren;
-        final int start = activities.indexOf(srec);
-        if (!mChildren.contains(task) || (start < 0)) {
+
+        if (!mChildren.contains(task) || !task.hasChild(srec)) {
             return false;
         }
-        int finishTo = start - 1;
-        ActivityRecord parent = finishTo < 0 ? null : task.getChildAt(finishTo);
+
+        ActivityRecord parent = task.getActivityBelow(srec);
         boolean foundParentInTask = false;
         final ComponentName dest = destIntent.getComponent();
-        if (start > 0 && dest != null) {
-            for (int i = finishTo; i >= 0; i--) {
-                ActivityRecord r = task.getChildAt(i);
-                if (r.info.packageName.equals(dest.getPackageName()) &&
-                        r.info.name.equals(dest.getClassName())) {
-                    finishTo = i;
-                    parent = r;
-                    foundParentInTask = true;
-                    break;
-                }
+        if (task.getBottomMostActivity() != srec && dest != null) {
+            final ActivityRecord candidate = task.getActivity((ar) ->
+                    ar.info.packageName.equals(dest.getPackageName()) &&
+                    ar.info.name.equals(dest.getClassName()), srec, false /*includeBoundary*/,
+                    true /*traverseTopToBottom*/);
+            if (candidate != null) {
+                parent = candidate;
+                foundParentInTask = true;
             }
         }
 
@@ -3212,13 +3091,24 @@
             }
         }
         final long origId = Binder.clearCallingIdentity();
-        for (int i = start; i > finishTo; i--) {
-            final ActivityRecord r = activities.get(i);
-            r.finishIfPossible(resultCode, resultData, "navigate-up", true /* oomAdj */);
+
+        final int[] resultCodeHolder = new int[1];
+        resultCodeHolder[0] = resultCode;
+        final Intent[] resultDataHolder = new Intent[1];
+        resultDataHolder[0] = resultData;
+        final ActivityRecord finalParent = parent;
+        task.forAllActivities((ar) -> {
+            if (ar == finalParent) return true;
+
+            ar.finishIfPossible(
+                    resultCodeHolder[0], resultDataHolder[0], "navigate-up", true /* oomAdj */);
             // Only return the supplied result for the first activity finished
-            resultCode = Activity.RESULT_CANCELED;
-            resultData = null;
-        }
+            resultCodeHolder[0] = Activity.RESULT_CANCELED;
+            resultDataHolder[0] = null;
+            return false;
+        }, srec, true, true);
+        resultCode = resultCodeHolder[0];
+        resultData = resultDataHolder[0];
 
         if (parent != null && foundParentInTask) {
             final int parentLaunchMode = parent.info.launchMode;
@@ -3285,7 +3175,6 @@
         }
     }
 
-    /// HANDLER INTERFACE BEGIN
     void removeTimeoutsForActivity(ActivityRecord r) {
         mStackSupervisor.removeTimeoutsForActivityLocked(r);
         removePauseTimeoutForActivity(r);
@@ -3343,86 +3232,33 @@
     }
     /// HANDLER INTERFACE END
 
-    private void destroyActivitiesLocked(WindowProcessController owner, String reason) {
-        boolean lastIsOpaque = false;
-        boolean activityRemoved = false;
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (r.finishing) {
-                    continue;
-                }
-                if (r.occludesParent()) {
-                    lastIsOpaque = true;
-                }
-                if (owner != null && r.app != owner) {
-                    continue;
-                }
-                if (!lastIsOpaque) {
-                    continue;
-                }
-                if (r.isDestroyable()) {
-                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r
-                            + " in state " + r.getState()
-                            + " resumed=" + mResumedActivity
-                            + " pausing=" + mPausingActivity + " for reason " + reason);
-                    if (r.destroyImmediately(true /* removeFromTask */, reason)) {
-                        activityRemoved = true;
-                    }
-                }
-            }
-        }
-        if (activityRemoved) {
+    private void destroyActivities(WindowProcessController owner, String reason) {
+        try {
+            mStackSupervisor.beginDeferResume();
+
+            final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::destroyActivity,
+                    PooledLambda.__(ActivityRecord.class), owner, reason);
+            forAllActivities(c);
+            c.recycle();
+        } finally {
+            mStackSupervisor.endDeferResume();
             mRootActivityContainer.resumeFocusedStacksTopActivities();
         }
     }
 
-    final int releaseSomeActivitiesLocked(WindowProcessController app, ArraySet<Task> tasks,
-            String reason) {
-        // Iterate over tasks starting at the back (oldest) first.
-        if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + app);
-        int maxTasks = tasks.size() / 4;
-        if (maxTasks < 1) {
-            maxTasks = 1;
-        }
-        int numReleased = 0;
-        for (int taskNdx = 0; taskNdx < getChildCount() && maxTasks > 0; taskNdx++) {
-            final Task task = getChildAt(taskNdx);
-            if (!tasks.contains(task)) {
-                continue;
-            }
-            if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Looking for activities to release in " + task);
-            int curNum = 0;
-            for (int actNdx = 0; actNdx < task.getChildCount(); actNdx++) {
-                final ActivityRecord activity = task.getChildAt(actNdx);
-                if (activity.app == app && activity.isDestroyable()) {
-                    if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + activity
-                            + " in state " + activity.getState() + " resumed=" + mResumedActivity
-                            + " pausing=" + mPausingActivity + " for reason " + reason);
-                    activity.destroyImmediately(true /* removeFromApp */, reason);
-                    if (task.getChildAt(actNdx) != activity) {
-                        // Was removed from list, back up so we don't miss the next one.
-                        actNdx--;
-                    }
-                    curNum++;
-                }
-            }
-            if (curNum > 0) {
-                numReleased += curNum;
-                maxTasks--;
-                if (getChildAt(taskNdx) != task) {
-                    // The entire task got removed, back up so we don't miss the next one.
-                    taskNdx--;
-                }
-            }
-        }
-        if (DEBUG_RELEASE) Slog.d(TAG_RELEASE,
-                "Done releasing: did " + numReleased + " activities");
-        return numReleased;
+    private static void destroyActivity(
+            ActivityRecord r, WindowProcessController owner, String reason) {
+        if (r.finishing || (owner != null && r.app != owner) || !r.isDestroyable()) return;
+
+        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r
+                + " in state " + r.getState()
+                + " resumed=" + r.getStack().mResumedActivity
+                + " pausing=" + r.getStack().mPausingActivity + " for reason " + reason);
+
+        r.destroyImmediately(true /* removeFromTask */, reason);
     }
 
-    private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
+    private void removeHistoryRecordsForApp(ArrayList<ActivityRecord> list,
             WindowProcessController app, String listName) {
         int i = list.size();
         if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
@@ -3439,107 +3275,15 @@
         }
     }
 
-    private boolean removeHistoryRecordsForAppLocked(WindowProcessController app) {
-        removeHistoryRecordsForAppLocked(mLruActivities, app, "mLruActivities");
-        removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
+    private boolean removeHistoryRecordsForApp(WindowProcessController app) {
+        removeHistoryRecordsForApp(mLruActivities, app, "mLruActivities");
+        removeHistoryRecordsForApp(mStackSupervisor.mStoppingActivities, app,
                 "mStoppingActivities");
-        removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
+        removeHistoryRecordsForApp(mStackSupervisor.mGoingToSleepActivities, app,
                 "mGoingToSleepActivities");
-        removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
+        removeHistoryRecordsForApp(mStackSupervisor.mFinishingActivities, app,
                 "mFinishingActivities");
-
-        final boolean isProcessRemoved = app.isRemoved();
-        if (isProcessRemoved) {
-            // The package of the died process should be force-stopped, so make its activities as
-            // finishing to prevent the process from being started again if the next top (or being
-            // visible) activity also resides in the same process.
-            app.makeFinishingForProcessRemoved();
-        }
-
-        boolean hasVisibleActivities = false;
-
-        // Clean out the history list.
-        int i = numActivities();
-        if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
-                "Removing app " + app + " from history with " + i + " entries");
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = getChildAt(taskNdx).mChildren;
-            mTmpActivities.clear();
-            mTmpActivities.addAll(activities);
-
-            while (!mTmpActivities.isEmpty()) {
-                final int targetIndex = mTmpActivities.size() - 1;
-                final ActivityRecord r = mTmpActivities.remove(targetIndex);
-                if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
-                        "Record #" + targetIndex + " " + r + ": app=" + r.app);
-
-                if (r.app == app) {
-                    if (r.isVisible() || r.mVisibleRequested) {
-                        // While an activity launches a new activity, it's possible that the old
-                        // activity is already requested to be hidden (mVisibleRequested=false), but
-                        // this visibility is not yet committed, so isVisible()=true.
-                        hasVisibleActivities = true;
-                    }
-                    final boolean remove;
-                    if ((r.mRelaunchReason == RELAUNCH_REASON_WINDOWING_MODE_RESIZE
-                            || r.mRelaunchReason == RELAUNCH_REASON_FREE_RESIZE)
-                            && r.launchCount < 3 && !r.finishing) {
-                        // If the process crashed during a resize, always try to relaunch it, unless
-                        // it has failed more than twice. Skip activities that's already finishing
-                        // cleanly by itself.
-                        remove = false;
-                    } else if ((!r.hasSavedState() && !r.stateNotNeeded
-                            && !r.isState(ActivityState.RESTARTING_PROCESS)) || r.finishing) {
-                        // Don't currently have state for the activity, or
-                        // it is finishing -- always remove it.
-                        remove = true;
-                    } else if (!r.mVisibleRequested && r.launchCount > 2
-                            && r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
-                        // We have launched this activity too many times since it was
-                        // able to run, so give up and remove it.
-                        // (Note if the activity is visible, we don't remove the record.
-                        // We leave the dead window on the screen but the process will
-                        // not be restarted unless user explicitly tap on it.)
-                        remove = true;
-                    } else {
-                        // The process may be gone, but the activity lives on!
-                        remove = false;
-                    }
-                    if (remove) {
-                        if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE,
-                                "Removing activity " + r + " from stack at " + i
-                                + ": hasSavedState=" + r.hasSavedState()
-                                + " stateNotNeeded=" + r.stateNotNeeded
-                                + " finishing=" + r.finishing
-                                + " state=" + r.getState() + " callers=" + Debug.getCallers(5));
-                        if (!r.finishing || isProcessRemoved) {
-                            Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
-                            EventLogTags.writeWmFinishActivity(r.mUserId,
-                                    System.identityHashCode(r), r.getTask().mTaskId,
-                                    r.shortComponentName, "proc died without state saved");
-                        }
-                    } else {
-                        // We have the current state for this activity, so
-                        // it can be restarted later when needed.
-                        if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null");
-                        if (DEBUG_APP) Slog.v(TAG_APP,
-                                "Clearing app during removeHistory for activity " + r);
-                        r.app = null;
-                        // Set nowVisible to previous visible state. If the app was visible while
-                        // it died, we leave the dead window on screen so it's basically visible.
-                        // This is needed when user later tap on the dead window, we need to stop
-                        // other apps when user transfers focus to the restarted activity.
-                        r.nowVisible = r.mVisibleRequested;
-                    }
-                    r.cleanUp(true /* cleanServices */, true /* setState */);
-                    if (remove) {
-                        r.removeFromHistory("appDied");
-                    }
-                }
-            }
-        }
-
-        return hasVisibleActivities;
+        return mRemoveHistoryRecordsForApp.process(app);
     }
 
     private void updateTransitLocked(int transit, ActivityOptions options) {
@@ -3559,8 +3303,7 @@
         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
 
         final ActivityStack topStack = getDisplay().getTopStack();
-        final ActivityRecord topActivity = topStack != null
-                ? topStack.getTopNonFinishingActivity() : null;
+        final ActivityRecord topActivity = topStack != null ? topStack.getTopNonFinishingActivity() : null;
         final int numTasks = getChildCount();
         final int index = mChildren.indexOf(tr);
         if (numTasks == 0 || index < 0)  {
@@ -3575,9 +3318,10 @@
 
         if (timeTracker != null) {
             // The caller wants a time tracker associated with this task.
-            for (int i = tr.getChildCount() - 1; i >= 0; i--) {
-                tr.getChildAt(i).appTimeTracker = timeTracker;
-            }
+            final PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setAppTimeTracker,
+                    PooledLambda.__(ActivityRecord.class), timeTracker);
+            tr.forAllActivities(c);
+            c.recycle();
         }
 
         try {
@@ -3711,38 +3455,8 @@
     /**
      * Ensures all visible activities at or below the input activity have the right configuration.
      */
-    void ensureVisibleActivitiesConfigurationLocked(ActivityRecord start, boolean preserveWindow) {
-        if (start == null || !start.mVisibleRequested) {
-            return;
-        }
-
-        final Task startTask = start.getTask();
-        boolean behindFullscreen = false;
-        boolean updatedConfig = false;
-
-        for (int taskIndex = mChildren.indexOf(startTask); taskIndex >= 0; --taskIndex) {
-            final Task task = getChildAt(taskIndex);
-            final ArrayList<ActivityRecord> activities = task.mChildren;
-            int activityIndex = (start.getTask() == task)
-                    ? activities.indexOf(start) : activities.size() - 1;
-            for (; activityIndex >= 0; --activityIndex) {
-                final ActivityRecord r = activities.get(activityIndex);
-                updatedConfig |= r.ensureActivityConfiguration(0 /* globalChanges */,
-                        preserveWindow);
-                if (r.occludesParent()) {
-                    behindFullscreen = true;
-                    break;
-                }
-            }
-            if (behindFullscreen) {
-                break;
-            }
-        }
-        if (updatedConfig) {
-            // Ensure the resumed state of the focus activity if we updated the configuration of
-            // any activity.
-            mRootActivityContainer.resumeFocusedStacksTopActivities();
-        }
+    void ensureVisibleActivitiesConfiguration(ActivityRecord start, boolean preserveWindow) {
+        mEnsureVisibleActivitiesConfigHelper.process(start, preserveWindow);
     }
 
     // TODO: Can only be called from special methods in ActivityStackSupervisor.
@@ -3774,7 +3488,7 @@
             setBounds(bounds);
 
             if (!deferResume) {
-                ensureVisibleActivitiesConfigurationLocked(
+                ensureVisibleActivitiesConfiguration(
                         topRunningActivityLocked(), preserveWindows);
             }
         } finally {
@@ -3818,85 +3532,23 @@
         }
     }
 
-    boolean willActivityBeVisibleLocked(IBinder token) {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (r.appToken == token) {
-                    return true;
-                }
-                if (r.occludesParent() && !r.finishing) {
-                    return false;
-                }
-            }
-        }
+    boolean willActivityBeVisible(IBinder token) {
         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
         if (r == null) {
             return false;
         }
-        if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false,"
+
+        // See if there is an occluding activity on-top of this one.
+        final ActivityRecord occludingActivity = getActivity((ar) ->
+                ar.occludesParent() && !ar.finishing,
+                r, false /*includeBoundary*/, true /*traverseTopToBottom*/);
+        if (occludingActivity != null) return false;
+
+        if (r.finishing) Slog.e(TAG, "willActivityBeVisible: Returning false,"
                 + " would have returned true for r=" + r);
         return !r.finishing;
     }
 
-    void closeSystemDialogsLocked() {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
-                    r.finishIfPossible("close-sys", true /* oomAdj */);
-                }
-            }
-        }
-    }
-
-    boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses,
-            boolean doit, boolean evenPersistent, int userId) {
-        boolean didSomething = false;
-        Task lastTask = null;
-        ComponentName homeActivity = null;
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final ArrayList<ActivityRecord> activities = getChildAt(taskNdx).mChildren;
-            mTmpActivities.clear();
-            mTmpActivities.addAll(activities);
-
-            while (!mTmpActivities.isEmpty()) {
-                ActivityRecord r = mTmpActivities.remove(0);
-                final boolean sameComponent =
-                        (r.packageName.equals(packageName) && (filterByClasses == null
-                                || filterByClasses.contains(r.mActivityComponent.getClassName())))
-                        || (packageName == null && r.mUserId == userId);
-                if ((userId == UserHandle.USER_ALL || r.mUserId == userId)
-                        && (sameComponent || r.getTask() == lastTask)
-                        && (r.app == null || evenPersistent || !r.app.isPersistent())) {
-                    if (!doit) {
-                        if (r.finishing) {
-                            // If this activity is just finishing, then it is not
-                            // interesting as far as something to stop.
-                            continue;
-                        }
-                        return true;
-                    }
-                    if (r.isActivityTypeHome()) {
-                        if (homeActivity != null && homeActivity.equals(r.mActivityComponent)) {
-                            Slog.i(TAG, "Skip force-stop again " + r);
-                            continue;
-                        } else {
-                            homeActivity = r.mActivityComponent;
-                        }
-                    }
-                    didSomething = true;
-                    Slog.i(TAG, "  Force finishing activity " + r);
-                    lastTask = r.getTask();
-                    r.finishIfPossible("force-stop", true);
-                }
-            }
-        }
-        return didSomething;
-    }
-
     /**
      * @return The set of running tasks through {@param tasksOut} that are available to the caller.
      *         If {@param ignoreActivityType} or {@param ignoreWindowingMode} are not undefined,
@@ -3948,14 +3600,11 @@
     }
 
     void unhandledBackLocked() {
-        final int top = getChildCount() - 1;
-        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top);
-        if (top >= 0) {
-            final Task task = getChildAt(top);
-            int activityTop = task.getChildCount() - 1;
-            if (activityTop >= 0) {
-                task.getChildAt(activityTop).finishIfPossible("unhandled-back", true /* oomAdj */);
-            }
+        final ActivityRecord topActivity = getTopMostActivity();
+        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH,
+                "Performing unhandledBack(): top activity: " + topActivity);
+        if (topActivity != null) {
+            topActivity.finishIfPossible("unhandled-back", true /* oomAdj */);
         }
     }
 
@@ -3975,25 +3624,7 @@
             mLastNoHistoryActivity = null;
         }
 
-        return removeHistoryRecordsForAppLocked(app);
-    }
-
-    void handleAppCrash(WindowProcessController app) {
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = task.getChildAt(activityNdx);
-                if (r.app == app) {
-                    Slog.w(TAG, "  Force finishing activity "
-                            + r.intent.getComponent().flattenToShortString());
-                    // Force the destroy to skip right to removal.
-                    r.app = null;
-                    getDisplay().mDisplayContent.prepareAppTransition(
-                            TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
-                    r.destroyIfPossible("handleAppCrashedLocked");
-                }
-            }
-        }
+        return removeHistoryRecordsForApp(app);
     }
 
     boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
@@ -4004,8 +3635,7 @@
         pw.println("  isSleeping=" + shouldSleepActivities());
         pw.println("  mBounds=" + getRequestedOverrideBounds());
 
-        boolean printed = dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
-                needSep);
+        boolean printed = dumpActivities(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
 
         printed |= dumpHistoryList(fd, pw, mLruActivities, "    ", "Run", false,
                 !dumpAll, false, dumpPackage, true,
@@ -4037,15 +3667,14 @@
         return printed;
     }
 
-    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
+    private boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
             boolean dumpClient, String dumpPackage, boolean needSep) {
 
         if (!hasChild()) {
             return false;
         }
         final String prefix = "    ";
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
+        forAllTasks((task) -> {
             if (needSep) {
                 pw.println("");
             }
@@ -4056,9 +3685,11 @@
             pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
             pw.println(prefix + "* " + task);
             task.dump(pw, prefix + "  ");
-            dumpHistoryList(fd, pw, getChildAt(taskNdx).mChildren,
-                    prefix, "Hist", true, !dumpAll, dumpClient, dumpPackage, false, null, task);
-        }
+            final ArrayList<ActivityRecord> activities = new ArrayList<>();
+            forAllActivities((Consumer<ActivityRecord>) activities::add);
+            dumpHistoryList(fd, pw, activities, prefix, "Hist", true, !dumpAll, dumpClient,
+                    dumpPackage, false, null, task);
+        });
         return true;
     }
 
@@ -4066,31 +3697,21 @@
         ArrayList<ActivityRecord> activities = new ArrayList<>();
 
         if ("all".equals(name)) {
-            for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-                activities.addAll(getChildAt(taskNdx).mChildren);
-            }
+            forAllActivities((Consumer<ActivityRecord>) activities::add);
         } else if ("top".equals(name)) {
-            final int top = getChildCount() - 1;
-            if (top >= 0) {
-                final Task task = getChildAt(top);
-                int listTop = task.getChildCount() - 1;
-                if (listTop >= 0) {
-                    activities.add(task.getChildAt(listTop));
-                }
+            final ActivityRecord topActivity = getTopMostActivity();
+            if (topActivity != null) {
+                activities.add(topActivity);
             }
         } else {
             ItemMatcher matcher = new ItemMatcher();
             matcher.build(name);
 
-            for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-                final Task task = getChildAt(taskNdx);
-                for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                    final ActivityRecord r1 = task.getChildAt(activityNdx);
-                    if (matcher.match(r1, r1.intent.getComponent())) {
-                        activities.add(r1);
-                    }
+            forAllActivities((r) -> {
+                if (matcher.match(r, r.intent.getComponent())) {
+                    activities.add(r);
                 }
-            }
+            });
         }
 
         return activities;
@@ -4101,22 +3722,24 @@
 
         // All activities that came from the package must be
         // restarted as if there was a config change.
-        for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = getChildAt(taskNdx);
-            for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord a = task.getChildAt(activityNdx);
-                if (a.info.packageName.equals(packageName)) {
-                    a.forceNewConfig = true;
-                    if (starting != null && a == starting && a.mVisibleRequested) {
-                        a.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
-                    }
-                }
-            }
-        }
+        PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::restartPackage,
+                PooledLambda.__(ActivityRecord.class), starting, packageName);
+        forAllActivities(c);
+        c.recycle();
 
         return starting;
     }
 
+    private static void restartPackage(
+            ActivityRecord r, ActivityRecord starting, String packageName) {
+        if (r.info.packageName.equals(packageName)) {
+            r.forceNewConfig = true;
+            if (starting != null && r == starting && r.mVisibleRequested) {
+                r.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
+            }
+        }
+    }
+
     /**
      * Removes the input task from this stack.
      *
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index d088a5e..0376d2c 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -138,6 +138,7 @@
 import com.android.internal.os.TransferPipe;
 import com.android.internal.os.logging.MetricsLoggerWrapper;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.function.pooled.PooledConsumer;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.UserState;
@@ -825,7 +826,7 @@
                         task.mTaskId, r.shortComponentName);
                 if (r.isActivityTypeHome()) {
                     // Home process is the root process of the task.
-                    updateHomeProcess(task.getChildAt(0).app);
+                    updateHomeProcess(task.getBottomMostActivity().app);
                 }
                 mService.getPackageManagerInternalLocked().notifyPackageUse(
                         r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY);
@@ -1688,7 +1689,7 @@
                 }
             }
             if (!deferResume) {
-                stack.ensureVisibleActivitiesConfigurationLocked(r, preserveWindows);
+                stack.ensureVisibleActivitiesConfiguration(r, preserveWindows);
             }
         } finally {
             mAllowDockedStackResize = true;
@@ -2485,18 +2486,23 @@
             return;
         }
 
-        for (int i = task.getChildCount() - 1; i >= 0; i--) {
-            final ActivityRecord r = task.getChildAt(i);
-            if (r.attachedToProcess()) {
-                mMultiWindowModeChangedActivities.add(r);
-            }
-        }
+        final PooledConsumer c = PooledLambda.obtainConsumer(
+                ActivityStackSupervisor::addToMultiWindowModeChangedList, this,
+                PooledLambda.__(ActivityRecord.class));
+        task.forAllActivities(c);
+        c.recycle();
 
         if (!mHandler.hasMessages(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG)) {
             mHandler.sendEmptyMessage(REPORT_MULTI_WINDOW_MODE_CHANGED_MSG);
         }
     }
 
+    private void addToMultiWindowModeChangedList(ActivityRecord r) {
+        if (r.attachedToProcess()) {
+            mMultiWindowModeChangedActivities.add(r);
+        }
+    }
+
     void scheduleUpdatePictureInPictureModeIfNeeded(Task task, ActivityStack prevStack) {
         final ActivityStack stack = task.getStack();
         if (prevStack == null || prevStack == stack
@@ -2507,17 +2513,13 @@
         scheduleUpdatePictureInPictureModeIfNeeded(task, stack.getRequestedOverrideBounds());
     }
 
-    void scheduleUpdatePictureInPictureModeIfNeeded(Task task, Rect targetStackBounds) {
-        for (int i = task.getChildCount() - 1; i >= 0; i--) {
-            final ActivityRecord r = task.getChildAt(i);
-            if (r.attachedToProcess()) {
-                mPipModeChangedActivities.add(r);
-                // If we are scheduling pip change, then remove this activity from multi-window
-                // change list as the processing of pip change will make sure multi-window changed
-                // message is processed in the right order relative to pip changed.
-                mMultiWindowModeChangedActivities.remove(r);
-            }
-        }
+    private void scheduleUpdatePictureInPictureModeIfNeeded(Task task, Rect targetStackBounds) {
+        final PooledConsumer c = PooledLambda.obtainConsumer(
+                ActivityStackSupervisor::addToPipModeChangedList, this,
+                PooledLambda.__(ActivityRecord.class));
+        task.forAllActivities(c);
+        c.recycle();
+
         mPipModeChangedTargetStackBounds = targetStackBounds;
 
         if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
@@ -2525,14 +2527,23 @@
         }
     }
 
+    private void addToPipModeChangedList(ActivityRecord r) {
+        if (!r.attachedToProcess()) return;
+
+        mPipModeChangedActivities.add(r);
+        // If we are scheduling pip change, then remove this activity from multi-window
+        // change list as the processing of pip change will make sure multi-window changed
+        // message is processed in the right order relative to pip changed.
+        mMultiWindowModeChangedActivities.remove(r);
+    }
+
     void updatePictureInPictureMode(Task task, Rect targetStackBounds, boolean forceUpdate) {
         mHandler.removeMessages(REPORT_PIP_MODE_CHANGED_MSG);
-        for (int i = task.getChildCount() - 1; i >= 0; i--) {
-            final ActivityRecord r = task.getChildAt(i);
-            if (r.attachedToProcess()) {
-                r.updatePictureInPictureMode(targetStackBounds, forceUpdate);
-            }
-        }
+        final PooledConsumer c = PooledLambda.obtainConsumer(
+                ActivityRecord::updatePictureInPictureMode,
+                PooledLambda.__(ActivityRecord.class), targetStackBounds, forceUpdate);
+        task.forAllActivities(c);
+        c.recycle();
     }
 
     void wakeUp(String reason) {
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 8420695..b2fb93d 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -156,16 +156,16 @@
         mInTask = inTask;
         mActivityOptions = activityOptions;
 
-        if (interceptSuspendedPackageIfNeeded()) {
-            // Skip the rest of interceptions as the package is suspended by device admin so
-            // no user action can undo this.
-            return true;
-        }
         if (interceptQuietProfileIfNeeded()) {
             // If work profile is turned off, skip the work challenge since the profile can only
             // be unlocked when profile's user is running.
             return true;
         }
+        if (interceptSuspendedPackageIfNeeded()) {
+            // Skip the rest of interceptions as the package is suspended by device admin so
+            // no user action can undo this.
+            return true;
+        }
         if (interceptHarmfulAppIfNeeded()) {
             // If the app has a "harmful app" warning associated with it, we should ask to uninstall
             // before issuing the work challenge.
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 7960842..a496396 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1446,7 +1446,7 @@
 
         // Stack should also be detached from display and be removed if it's empty.
         if (startedActivityStack != null && startedActivityStack.isAttached()
-                && startedActivityStack.numActivities() == 0
+                && !startedActivityStack.hasActivity()
                 && !startedActivityStack.isActivityTypeHome()) {
             startedActivityStack.removeIfPossible();
             startedActivityStack = null;
@@ -1640,7 +1640,7 @@
             return START_CANCELED;
         }
 
-        if (mRestrictedBgActivity && (newTask || !targetTask.containsAppUid(mCallingUid))
+        if (mRestrictedBgActivity && (newTask || !targetTask.isUidPresent(mCallingUid))
                 && handleBackgroundActivityAbort(mStartActivity)) {
             Slog.e(TAG, "Abort background activity starts from " + mCallingUid);
             return START_ABORTED;
@@ -1880,8 +1880,8 @@
             // In this case, we are launching an activity in our own task that may
             // already be running somewhere in the history, and we want to shuffle it to
             // the front of the stack if so.
-            final ActivityRecord act = targetTask.findActivityInHistoryLocked(
-                    mStartActivity);
+            final ActivityRecord act =
+                    targetTask.findActivityInHistory(mStartActivity.mActivityComponent);
             if (act != null) {
                 final Task task = act.getTask();
                 task.moveActivityToFrontLocked(act);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index bcd5d36..df03940 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -247,6 +247,8 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledFunction;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.AttributeCache;
 import com.android.server.LocalServices;
@@ -695,6 +697,13 @@
         int caller() default NONE;
     }
 
+    private final Runnable mUpdateOomAdjRunnable = new Runnable() {
+        @Override
+	public void run() {
+            mAmInternal.updateOomAdj();
+        }
+    };
+
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     public ActivityTaskManagerService(Context context) {
         mContext = context;
@@ -1661,7 +1670,14 @@
                 if (getLockTaskController().activityBlockedFromFinish(r)) {
                     return false;
                 }
-                r.finishActivityAffinity();
+
+                final PooledFunction p = PooledLambda.obtainFunction(
+                        ActivityRecord::finishIfSameAffinity, r,
+                        PooledLambda.__(ActivityRecord.class));
+                r.getTask().forAllActivities(
+                        p, r, true /*includeBoundary*/, true /*traverseTopToBottom*/);
+                p.recycle();
+
                 return true;
             } finally {
                 Binder.restoreCallingIdentity(origId);
@@ -1994,10 +2010,8 @@
                 if (r == null) {
                     return false;
                 }
-                final Task task = r.getTask();
-                int index = task.mChildren.lastIndexOf(r);
-                if (index > 0) {
-                    ActivityRecord under = task.getChildAt(index - 1);
+                final ActivityRecord under = r.getTask().getActivityBelow(r);
+                if (under != null) {
                     under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
                 }
                 return r.setOccludesParent(false);
@@ -2163,7 +2177,7 @@
         synchronized (mGlobalLock) {
             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
             if (r != null) {
-                return r.getActivityStack().navigateUpToLocked(
+                return r.getActivityStack().navigateUpTo(
                         r, destIntent, resultCode, resultData);
             }
             return false;
@@ -2548,11 +2562,22 @@
     public final void finishSubActivity(IBinder token, String resultWho, int requestCode) {
         synchronized (mGlobalLock) {
             final long origId = Binder.clearCallingIdentity();
-            ActivityRecord r = ActivityRecord.isInStackLocked(token);
-            if (r != null) {
-                r.getActivityStack().finishSubActivityLocked(r, resultWho, requestCode);
+            try {
+                ActivityRecord r = ActivityRecord.isInStackLocked(token);
+                if (r == null) return;
+
+                final PooledConsumer c = PooledLambda.obtainConsumer(
+                        ActivityRecord::finishIfSubActivity, PooledLambda.__(ActivityRecord.class),
+                        r, resultWho, requestCode);
+                // TODO: This should probably only loop over the task since you need to be in the
+                // same task to return results.
+                r.getActivityStack().forAllActivities(c);
+                c.recycle();
+
+                updateOomAdj();
+            } finally {
+                Binder.restoreCallingIdentity(origId);
             }
-            Binder.restoreCallingIdentity(origId);
         }
     }
 
@@ -2561,7 +2586,7 @@
         synchronized (mGlobalLock) {
             ActivityStack stack = ActivityRecord.getStackLocked(token);
             if (stack != null) {
-                return stack.willActivityBeVisibleLocked(token);
+                return stack.willActivityBeVisible(token);
             }
             return false;
         }
@@ -3332,7 +3357,7 @@
             final long origId = Binder.clearCallingIdentity();
             try {
                 final WindowProcessController app = getProcessController(appInt);
-                mRootActivityContainer.releaseSomeActivitiesLocked(app, "low-mem");
+                app.releaseSomeActivities("low-mem");
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
@@ -5545,7 +5570,8 @@
     }
 
     void updateOomAdj() {
-        mH.post(mAmInternal::updateOomAdj);
+        mH.removeCallbacks(mUpdateOomAdjRunnable);
+        mH.post(mUpdateOomAdjRunnable);
     }
 
     void updateCpuStats() {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 283b92c..b046b08 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2482,7 +2482,7 @@
                 && !mDividerControllerLocked.isImeHideRequested();
         final ActivityStack dockedStack = getSplitScreenPrimaryStack();
         final boolean dockVisible = dockedStack != null;
-        final Task topDockedTask = dockVisible ? dockedStack.getTopChild() : null;
+        final Task topDockedTask = dockVisible ? dockedStack.getTask((t) -> true): null;
         final ActivityStack imeTargetStack = mWmService.getImeFocusStackLocked();
         final int imeDockSide = (dockVisible && imeTargetStack != null) ?
                 imeTargetStack.getDockSide() : DOCKED_INVALID;
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 3b58eca..7645de5 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -196,8 +196,7 @@
             // Some stack visibility might change (e.g. docked stack)
             mRootActivityContainer.resumeFocusedStacksTopActivities();
             mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
-            mRootActivityContainer.addStartingWindowsForVisibleActivities(
-                    true /* taskSwitch */);
+            mRootActivityContainer.addStartingWindowsForVisibleActivities();
             mWindowManager.executeAppTransition();
         } finally {
             mService.continueWindowLayout();
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 824a3c8..f2e9505 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -42,6 +42,8 @@
 import android.util.Slog;
 import android.view.IRecentsAnimationRunner;
 
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.util.function.pooled.PooledPredicate;
 import com.android.server.protolog.common.ProtoLog;
 import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
 
@@ -490,13 +492,15 @@
             return null;
         }
 
-        for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
-            final Task task = targetStack.getChildAt(i);
-            if (task.mUserId == mUserId
-                    && task.getBaseIntent().getComponent().equals(mTargetIntent.getComponent())) {
-                return task.getTopNonFinishingActivity();
-            }
-        }
-        return null;
+        final PooledPredicate p = PooledLambda.obtainPredicate(RecentsAnimation::matchesTarget,
+                this, PooledLambda.__(Task.class));
+        final Task task = targetStack.getTask(p);
+        p.recycle();
+        return task != null ? task.getTopNonFinishingActivity() : null;
+    }
+
+    private boolean matchesTarget(Task task) {
+        return task.mUserId == mUserId
+                && task.getBaseIntent().getComponent().equals(mTargetIntent.getComponent());
     }
 }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 282144e..4c5ca38 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -55,6 +55,9 @@
 import android.view.SurfaceControl.Transaction;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledFunction;
+import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.protolog.common.ProtoLog;
@@ -369,13 +372,13 @@
         final ActivityStack targetStack = mDisplayContent.getStack(WINDOWING_MODE_UNDEFINED,
                 targetActivityType);
         if (targetStack != null) {
-            for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
-                final Task t = targetStack.getChildAt(i);
-                if (!visibleTasks.contains(t)) {
-                    visibleTasks.add(t);
-                }
-            }
+            final PooledConsumer c = PooledLambda.obtainConsumer((t, outList) ->
+	            { if (!outList.contains(t)) outList.add(t); }, PooledLambda.__(Task.class),
+                    visibleTasks);
+            targetStack.forAllTasks(c);
+            c.recycle();
         }
+
         final int taskCount = visibleTasks.size();
         for (int i = 0; i < taskCount; i++) {
             final Task task = visibleTasks.get(i);
@@ -800,12 +803,12 @@
     private boolean isAnimatingApp(ActivityRecord activity) {
         for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
             final Task task = mPendingAnimations.get(i).mTask;
-            for (int j = task.getChildCount() - 1; j >= 0; j--) {
-                final ActivityRecord app = task.getChildAt(j);
-                if (app == activity) {
-                    return true;
-                }
-            }
+            final PooledFunction f = PooledLambda.obtainFunction(
+                    (a, b) -> a == b, activity,
+                    PooledLambda.__(ActivityRecord.class));
+            boolean isAnimatingApp = task.forAllActivities(f);
+            f.recycle();
+            return isAnimatingApp;
         }
         return false;
     }
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index 413dfd5..3aa91d5 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -125,8 +125,7 @@
                     // TODO: We should probably look for other stacks also, since corresponding
                     //  task with the same affinity is unlikely to be in the same stack.
                     final Task targetTask;
-                    final ActivityRecord bottom = mParent.getActivity(
-                            (ar) -> true, false /*traverseTopToBottom*/);
+                    final ActivityRecord bottom = mParent.getBottomMostActivity();
 
                     if (bottom != null && r.taskAffinity.equals(bottom.getTask().affinity)) {
                         // If the activity currently at the bottom has the same task affinity as
@@ -210,10 +209,8 @@
                 // we have put it on top of another instance of the same activity? Then we drop
                 // the instance below so it remains singleTop.
                 if (r.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
-                    final ArrayList<ActivityRecord> taskActivities = mTargetTask.mChildren;
-                    final int targetNdx = taskActivities.indexOf(r);
-                    if (targetNdx > 0) {
-                        final ActivityRecord p = taskActivities.get(targetNdx - 1);
+                    final ActivityRecord p = mTargetTask.getActivityBelow(r);
+                    if (p != null) {
                         if (p.intent.getComponent().equals(r.intent.getComponent())) {
                             p.finishIfPossible("replace", false /* oomAdj */);
                         }
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 8f1d6ee..5fd59fa 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -33,6 +33,7 @@
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
 
 import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
@@ -86,6 +87,7 @@
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.power.V1_0.PowerHint;
+import android.net.Uri;
 import android.os.FactoryTest;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -108,6 +110,11 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ResolverActivity;
+import com.android.internal.util.ToBooleanFunction;
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledFunction;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.util.function.pooled.PooledPredicate;
 import com.android.server.LocalServices;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.AppTimeTracker;
@@ -121,6 +128,7 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -201,14 +209,46 @@
 
     // Whether tasks have moved and we need to rank the tasks before next OOM scoring
     private boolean mTaskLayersChanged = true;
+    private int mTmpTaskLayerRank;
 
-    private final ArrayList<ActivityRecord> mTmpActivityList = new ArrayList<>();
+    private boolean mTmpBoolean;
+    private RemoteException mTmpRemoteException;
 
     private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
-    static class FindTaskResult {
+    static class FindTaskResult implements ToBooleanFunction<Task> {
         ActivityRecord mRecord;
         boolean mIdealMatch;
 
+        private ActivityRecord mTarget;
+        private Intent intent;
+        private ActivityInfo info;
+        private ComponentName cls;
+        private int userId;
+        private boolean isDocument;
+        private Uri documentData;
+
+        /**
+         * Returns the top activity in any existing task matching the given Intent in the input
+         * result. Returns null if no such task is found.
+         */
+        void process(ActivityRecord target, ActivityStack parent) {
+            mTarget = target;
+
+            intent = target.intent;
+            info = target.info;
+            cls = intent.getComponent();
+            if (info.targetActivity != null) {
+                cls = new ComponentName(info.packageName, info.targetActivity);
+            }
+            userId = UserHandle.getUserId(info.applicationInfo.uid);
+            isDocument = intent != null & intent.isDocument();
+            // If documentData is non-null then it must match the existing task data.
+            documentData = isDocument ? intent.getData() : null;
+
+            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + parent);
+            parent.forAllTasks(this);
+        }
+
         void clear() {
             mRecord = null;
             mIdealMatch = false;
@@ -218,6 +258,84 @@
             mRecord = result.mRecord;
             mIdealMatch = result.mIdealMatch;
         }
+
+        @Override
+        public boolean apply(Task task) {
+            if (task.voiceSession != null) {
+                // We never match voice sessions; those always run independently.
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
+                return false;
+            }
+            if (task.mUserId != userId) {
+                // Looking for a different task.
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
+                return false;
+            }
+
+            // Overlays should not be considered as the task's logical top activity.
+            final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */);
+            if (r == null || r.finishing || r.mUserId != userId ||
+                    r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
+                return false;
+            }
+            if (!r.hasCompatibleActivityType(mTarget)) {
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
+                return false;
+            }
+
+            final Intent taskIntent = task.intent;
+            final Intent affinityIntent = task.affinityIntent;
+            final boolean taskIsDocument;
+            final Uri taskDocumentData;
+            if (taskIntent != null && taskIntent.isDocument()) {
+                taskIsDocument = true;
+                taskDocumentData = taskIntent.getData();
+            } else if (affinityIntent != null && affinityIntent.isDocument()) {
+                taskIsDocument = true;
+                taskDocumentData = affinityIntent.getData();
+            } else {
+                taskIsDocument = false;
+                taskDocumentData = null;
+            }
+
+            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
+                    + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
+                    + "/aff=" + r.getTask().rootAffinity + " to new cls="
+                    + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
+            // TODO Refactor to remove duplications. Check if logic can be simplified.
+            if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
+                    && Objects.equals(documentData, taskDocumentData)) {
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
+                //dump();
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
+                        "For Intent " + intent + " bringing to top: " + r.intent);
+                mRecord = r;
+                mIdealMatch = true;
+                return true;
+            } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
+                    affinityIntent.getComponent().compareTo(cls) == 0 &&
+                    Objects.equals(documentData, taskDocumentData)) {
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
+                        "For Intent " + intent + " bringing to top: " + r.intent);
+                mRecord = r;
+                mIdealMatch = true;
+                return true;
+            } else if (!isDocument && !taskIsDocument
+                    && mRecord == null && task.rootAffinity != null) {
+                if (task.rootAffinity.equals(mTarget.taskAffinity)) {
+                    if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
+                    // It is possible for multiple tasks to have the same root affinity especially
+                    // if they are in separate stacks. We save off this candidate, but keep looking
+                    // to see if there is a better candidate.
+                    mRecord = r;
+                    mIdealMatch = false;
+                }
+            } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
+
+            return false;
+        }
     }
 
     RootActivityContainer(ActivityTaskManagerService service) {
@@ -772,27 +890,21 @@
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
             final ActivityStack stack = display.getFocusedStack();
-            if (stack != null) {
-                stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
-                final ActivityRecord top = stack.topRunningActivityLocked();
-                final int size = mTmpActivityList.size();
-                for (int i = 0; i < size; i++) {
-                    final ActivityRecord activity = mTmpActivityList.get(i);
-                    if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
-                            && processName.equals(activity.processName)) {
-                        try {
-                            if (mStackSupervisor.realStartActivityLocked(activity, app,
-                                    top == activity /* andResume */, true /* checkConfig */)) {
-                                didSomething = true;
-                            }
-                        } catch (RemoteException e) {
-                            Slog.w(TAG, "Exception in new application when starting activity "
-                                    + top.intent.getComponent().flattenToShortString(), e);
-                            throw e;
-                        }
-                    }
-                }
+            if (stack == null) {
+                continue;
             }
+
+            mTmpRemoteException = null;
+            mTmpBoolean = false; // Set to true if an activity was started.
+            final PooledFunction c = PooledLambda.obtainFunction(
+                    RootActivityContainer::startActivityForAttachedApplicationIfNeeded, this,
+                    PooledLambda.__(ActivityRecord.class), app, stack.topRunningActivityLocked());
+            stack.forAllActivities(c);
+            c.recycle();
+            if (mTmpRemoteException != null) {
+                throw mTmpRemoteException;
+            }
+            didSomething |= mTmpBoolean;
         }
         if (!didSomething) {
             ensureActivitiesVisible(null, 0, false /* preserve_windows */);
@@ -800,6 +912,27 @@
         return didSomething;
     }
 
+    private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
+            WindowProcessController app, ActivityRecord top) {
+        if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
+                || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
+            return false;
+        }
+
+        try {
+            if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/,
+                    true /*checkConfig*/)) {
+                mTmpBoolean = true;
+            }
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Exception in new application when starting activity "
+                    + top.intent.getComponent().flattenToShortString(), e);
+            mTmpRemoteException = e;
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Make sure that all activities that need to be visible in the system actually are and update
      * their configuration.
@@ -1526,14 +1659,12 @@
         }
     }
 
-    void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
-        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                stack.addStartingWindowsForVisibleActivities(taskSwitch);
+    void addStartingWindowsForVisibleActivities() {
+        mRootWindowContainer.forAllActivities((r) -> {
+            if (r.mVisibleRequested) {
+                r.showStartingWindow(null /* prev */, false /* newTask */, true /*taskSwitch*/);
             }
-        }
+        });
     }
 
     void invalidateTaskLayers() {
@@ -1541,27 +1672,37 @@
     }
 
     void rankTaskLayersIfNeeded() {
-        if (!mTaskLayersChanged) {
+        if (!mTaskLayersChanged || mRootWindowContainer == null) {
             return;
         }
         mTaskLayersChanged = false;
-        for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) {
-            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            int baseLayer = 0;
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                baseLayer += stack.rankTaskLayers(baseLayer);
-            }
+        mTmpTaskLayerRank = 0;
+        final PooledConsumer c = PooledLambda.obtainConsumer(
+                RootActivityContainer::rankTaskLayerForActivity, this,
+                PooledLambda.__(ActivityRecord.class));
+        mRootWindowContainer.forAllActivities(c);
+        c.recycle();
+    }
+
+    private void rankTaskLayerForActivity(ActivityRecord r) {
+        if (r.canBeTopRunning() && r.mVisibleRequested) {
+            r.getTask().mLayerRank = ++mTmpTaskLayerRank;
+        } else {
+            r.getTask().mLayerRank = -1;
         }
     }
 
     void clearOtherAppTimeTrackers(AppTimeTracker except) {
-        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                stack.clearOtherAppTimeTrackers(except);
-            }
+        final PooledConsumer c = PooledLambda.obtainConsumer(
+                RootActivityContainer::clearOtherAppTimeTrackers,
+                PooledLambda.__(ActivityRecord.class), except);
+        mRootWindowContainer.forAllActivities(c);
+        c.recycle();
+    }
+
+    private static void clearOtherAppTimeTrackers(ActivityRecord r, AppTimeTracker except) {
+        if ( r.appTimeTracker != except) {
+            r.appTimeTracker = null;
         }
     }
 
@@ -1575,30 +1716,6 @@
         }
     }
 
-    void releaseSomeActivitiesLocked(WindowProcessController app, String reason) {
-        // Tasks is non-null only if two or more tasks are found.
-        ArraySet<Task> tasks = app.getReleaseSomeActivitiesTasks();
-        if (tasks == null) {
-            if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Didn't find two or more tasks to release");
-            return;
-        }
-        // If we have activities in multiple tasks that are in a position to be destroyed,
-        // let's iterate through the tasks and release the oldest one.
-        final int numDisplays = mActivityDisplays.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            final int stackCount = display.getChildCount();
-            // Step through all stacks starting from behind, to hit the oldest things first.
-            for (int stackNdx = 0; stackNdx < stackCount; stackNdx++) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                // Try to release activities in this stack; if we manage to, we are done.
-                if (stack.releaseSomeActivitiesLocked(app, tasks, reason) > 0) {
-                    return;
-                }
-            }
-        }
-    }
-
     // Tries to put all activity stacks to sleep. Returns true if all stacks were
     // successfully put to sleep.
     boolean putStacksToSleep(boolean allowDelay, boolean shuttingDown) {
@@ -1625,28 +1742,52 @@
     }
 
     void handleAppCrash(WindowProcessController app) {
-        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                stack.handleAppCrash(app);
-            }
-        }
+        final PooledConsumer c = PooledLambda.obtainConsumer(
+                RootActivityContainer::handleAppCrash, PooledLambda.__(ActivityRecord.class), app);
+        mRootWindowContainer.forAllActivities(c);
+        c.recycle();
+    }
+
+    private static void handleAppCrash(ActivityRecord r, WindowProcessController app) {
+        if (r.app != app) return;
+        Slog.w(TAG, "  Force finishing activity "
+                + r.intent.getComponent().flattenToShortString());
+        // Force the destroy to skip right to removal.
+        r.app = null;
+        r.getDisplay().mDisplayContent.prepareAppTransition(
+                TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
+        r.destroyIfPossible("handleAppCrashed");
     }
 
     ActivityRecord findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters) {
-        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                final ActivityRecord ar = stack.findActivityLocked(
-                        intent, info, compareIntentFilters);
-                if (ar != null) {
-                    return ar;
-                }
+        ComponentName cls = intent.getComponent();
+        if (info.targetActivity != null) {
+            cls = new ComponentName(info.packageName, info.targetActivity);
+        }
+        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
+
+        final PooledPredicate p = PooledLambda.obtainPredicate(
+                RootActivityContainer::matchesActivity, PooledLambda.__(ActivityRecord.class),
+                userId, compareIntentFilters, intent, cls);
+        final ActivityRecord r = mRootWindowContainer.getActivity(p);
+        p.recycle();
+        return r;
+    }
+
+    private static boolean matchesActivity(ActivityRecord r, int userId,
+            boolean compareIntentFilters, Intent intent, ComponentName cls) {
+        if (!r.canBeTopRunning() || r.mUserId != userId)  return false;
+
+        if (compareIntentFilters) {
+            if (r.intent.filterEquals(intent)) {
+                return true;
+            }
+        } else {
+            if (r.intent.getComponent().equals(cls)) {
+                return true;
             }
         }
-        return null;
+        return false;
     }
 
     boolean hasAwakeDisplay() {
@@ -1978,39 +2119,104 @@
     }
 
     void closeSystemDialogs() {
-        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                stack.closeSystemDialogsLocked();
+        mRootWindowContainer.forAllActivities((r) -> {
+            if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
+                r.finishIfPossible("close-sys", true /* oomAdj */);
             }
+        });
+    }
+
+    FinishDisabledPackageActivitiesHelper mFinishDisabledPackageActivitiesHelper =
+            new FinishDisabledPackageActivitiesHelper();
+    class FinishDisabledPackageActivitiesHelper {
+        private boolean mDidSomething;
+        private String mPackageName;
+        private Set<String> mFilterByClasses;
+        private boolean mDoit;
+        private boolean mEvenPersistent;
+        private int mUserId;
+        private Task mLastTask;
+        private ComponentName mHomeActivity;
+
+        private void reset(String packageName, Set<String> filterByClasses,
+                boolean doit, boolean evenPersistent, int userId) {
+            mDidSomething = false;
+            mPackageName = packageName;
+            mFilterByClasses = filterByClasses;
+            mDoit = doit;
+            mEvenPersistent = evenPersistent;
+            mUserId = userId;
+            mLastTask = null;
+            mHomeActivity = null;
+        }
+
+        boolean process(String packageName, Set<String> filterByClasses,
+                boolean doit, boolean evenPersistent, int userId) {
+            reset(packageName, filterByClasses, doit, evenPersistent, userId);
+
+            final PooledFunction f = PooledLambda.obtainFunction(
+                    FinishDisabledPackageActivitiesHelper::processActivity, this,
+                    PooledLambda.__(ActivityRecord.class));
+            mRootWindowContainer.forAllActivities(f);
+            f.recycle();
+            return mDidSomething;
+        }
+
+        private boolean processActivity(ActivityRecord r) {
+            final boolean sameComponent =
+                    (r.packageName.equals(mPackageName) && (mFilterByClasses == null
+                            || mFilterByClasses.contains(r.mActivityComponent.getClassName())))
+                            || (mPackageName == null && r.mUserId == mUserId);
+            if ((mUserId == UserHandle.USER_ALL || r.mUserId == mUserId)
+                    && (sameComponent || r.getTask() == mLastTask)
+                    && (r.app == null || mEvenPersistent || !r.app.isPersistent())) {
+                if (!mDoit) {
+                    if (r.finishing) {
+                        // If this activity is just finishing, then it is not
+                        // interesting as far as something to stop.
+                        return false;
+                    }
+                    return true;
+                }
+                if (r.isActivityTypeHome()) {
+                    if (mHomeActivity != null && mHomeActivity.equals(r.mActivityComponent)) {
+                        Slog.i(TAG, "Skip force-stop again " + r);
+                        return false;
+                    } else {
+                        mHomeActivity = r.mActivityComponent;
+                    }
+                }
+                mDidSomething = true;
+                Slog.i(TAG, "  Force finishing activity " + r);
+                mLastTask = r.getTask();
+                r.finishIfPossible("force-stop", true);
+            }
+
+            return false;
         }
     }
 
     /** @return true if some activity was finished (or would have finished if doit were true). */
     boolean finishDisabledPackageActivities(String packageName, Set<String> filterByClasses,
             boolean doit, boolean evenPersistent, int userId) {
-        boolean didSomething = false;
-        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                if (stack.finishDisabledPackageActivitiesLocked(
-                        packageName, filterByClasses, doit, evenPersistent, userId)) {
-                    didSomething = true;
-                }
-            }
-        }
-        return didSomething;
+        return mFinishDisabledPackageActivitiesHelper.process(packageName, filterByClasses, doit,
+                evenPersistent, userId);
     }
 
     void updateActivityApplicationInfo(ApplicationInfo aInfo) {
-        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
-            final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                stack.updateActivityApplicationInfoLocked(aInfo);
-            }
+        final String packageName = aInfo.packageName;
+        final int userId = UserHandle.getUserId(aInfo.uid);
+        final PooledConsumer c = PooledLambda.obtainConsumer(
+                RootActivityContainer::updateActivityApplicationInfo,
+                PooledLambda.__(ActivityRecord.class), aInfo, userId, packageName);
+        mRootWindowContainer.forAllActivities(c);
+        c.recycle();
+    }
+
+    private static void updateActivityApplicationInfo(
+            ActivityRecord r, ApplicationInfo aInfo, int userId, String packageName) {
+        if (r.mUserId == userId && packageName.equals(r.packageName)) {
+            r.updateApplicationInfo(aInfo);
         }
     }
 
@@ -2063,7 +2269,7 @@
             // If the focused stack is not null or not empty, there should have some activities
             // resuming or resumed. Make sure these activities are idle.
             final ActivityStack stack = display.getFocusedStack();
-            if (stack == null || stack.numActivities() == 0) {
+            if (stack == null || !stack.hasActivity()) {
                 continue;
             }
             final ActivityRecord resumedActivity = stack.getResumedActivity();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 619b71c..88a38e0 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -67,7 +67,6 @@
 import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
 import static com.android.server.am.TaskRecordProto.STACK_ID;
 import static com.android.server.am.TaskRecordProto.TASK;
-import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
 import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -138,6 +137,10 @@
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.util.function.pooled.PooledConsumer;
+import com.android.internal.util.function.pooled.PooledFunction;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.util.function.pooled.PooledPredicate;
 import com.android.server.protolog.common.ProtoLog;
 import com.android.server.wm.ActivityStack.ActivityState;
 
@@ -152,8 +155,9 @@
 import java.util.ArrayList;
 import java.util.Objects;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
 
-class Task extends WindowContainer<ActivityRecord> implements ConfigurationContainerListener {
+class Task extends WindowContainer<WindowContainer> {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_ATM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
@@ -382,6 +386,44 @@
     /** @see #setCanAffectSystemUiFlags */
     private boolean mCanAffectSystemUiFlags = true;
 
+    private static Exception sTmpException;
+
+    private final FindRootHelper mFindRootHelper = new FindRootHelper();
+    private class FindRootHelper {
+        private ActivityRecord mRoot;
+
+        private void clear() {
+            mRoot = null;
+        }
+
+        ActivityRecord findRoot(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
+            final PooledFunction f = PooledLambda.obtainFunction(FindRootHelper::processActivity,
+                    this, PooledLambda.__(ActivityRecord.class), ignoreRelinquishIdentity,
+                    setToBottomIfNone);
+            clear();
+            forAllActivities(f, false /*traverseTopToBottom*/);
+            f.recycle();
+            return mRoot;
+        }
+
+        private boolean processActivity(ActivityRecord r,
+                boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
+            if (mRoot == null && setToBottomIfNone) {
+                // This is the first activity we are process. Set it as the candidate root in case
+                // we don't find a better one.
+                mRoot = r;
+            }
+
+            if (r.finishing) return false;
+
+            // Set this as the candidate root since it isn't finishing.
+            mRoot = r;
+
+            // Only end search if we are ignore relinquishing identity or we are not relinquishing.
+            return ignoreRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+        }
+    }
+
     /**
      * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
      * ActivityInfo, Intent, TaskDescription)} instead.
@@ -464,7 +506,7 @@
         mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
     }
 
-    void cleanUpResourcesForDestroy() {
+    private void cleanUpResourcesForDestroy() {
         if (hasChild()) {
             return;
         }
@@ -931,10 +973,11 @@
         super.onParentChanged(newParent, oldParent);
 
         if (oldStack != null) {
-            for (int i = getChildCount() - 1; i >= 0; --i) {
-                final ActivityRecord activity = getChildAt(i);
-                oldStack.onActivityRemovedFromStack(activity);
-            }
+            final PooledConsumer c = PooledLambda.obtainConsumer(
+                    ActivityStack::onActivityRemovedFromStack, oldStack,
+                    PooledLambda.__(ActivityRecord.class));
+            forAllActivities(c);
+            c.recycle();
 
             if (oldStack.inPinnedWindowingMode()
                     && (newStack == null || !newStack.inPinnedWindowingMode())) {
@@ -945,10 +988,11 @@
         }
 
         if (newStack != null) {
-            for (int i = getChildCount() - 1; i >= 0; --i) {
-                final ActivityRecord activity = getChildAt(i);
-                newStack.onActivityAddedToStack(activity);
-            }
+            final PooledConsumer c = PooledLambda.obtainConsumer(
+                    ActivityStack::onActivityAddedToStack, newStack,
+                    PooledLambda.__(ActivityRecord.class));
+            forAllActivities(c);
+            c.recycle();
 
             // TODO: Ensure that this is actually necessary here
             // Notify the voice session if required
@@ -1068,25 +1112,11 @@
     }
 
     ActivityRecord getRootActivity(boolean setToBottomIfNone) {
-        return getRootActivity(false /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
+        return getRootActivity(false /*ignoreRelinquishIdentity*/, setToBottomIfNone);
     }
 
     ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
-        ActivityRecord root;
-        if (ignoreRelinquishIdentity) {
-            root = getActivity((r) -> !r.finishing, false /*traverseTopToBottom*/);
-        } else {
-            root = getActivity((r) ->
-                            !r.finishing && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0,
-                    false /*traverseTopToBottom*/);
-        }
-
-        if (root == null && setToBottomIfNone) {
-            // All activities in the task are either finishing or relinquish task identity.
-            // But we still want to update the intent, so let's use the bottom activity.
-            root = getActivity((r) -> true, false /*traverseTopToBottom*/);
-        }
-        return root;
+        return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone);
     }
 
     ActivityRecord getTopNonFinishingActivity() {
@@ -1094,101 +1124,42 @@
     }
 
     ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityRecord r = getChildAt(i);
-            if (r.finishing || (!includeOverlays && r.mTaskOverlay)) {
-                continue;
-            }
-            return r;
-        }
-        return null;
+        return getTopActivity(false /*includeFinishing*/, includeOverlays);
     }
 
     ActivityRecord topRunningActivityLocked() {
-        if (mStack != null) {
-            for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                ActivityRecord r = getChildAt(activityNdx);
-                if (!r.finishing && r.okToShowLocked()) {
-                    return r;
-                }
-            }
+        if (getParent() == null) {
+            return null;
         }
-        return null;
+        return getActivity(ActivityRecord::canBeTopRunning);
     }
 
     /**
      * Return true if any activities in this task belongs to input uid.
      */
-    boolean containsAppUid(int uid) {
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityRecord r = getChildAt(i);
-            if (r.getUid() == uid) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
-        if (mStack != null) {
-            for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                ActivityRecord r = getChildAt(activityNdx);
-                if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
-                    outActivities.add(r);
-                }
-            }
-        }
+    boolean isUidPresent(int uid) {
+        final PooledPredicate p = PooledLambda.obtainPredicate(
+                ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
+        final boolean isUidPresent = getActivity(p) != null;
+        p.recycle();
+        return isUidPresent;
     }
 
     ActivityRecord topRunningActivityWithStartingWindowLocked() {
-        if (mStack != null) {
-            for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-                ActivityRecord r = getChildAt(activityNdx);
-                if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
-                        || r.finishing || !r.okToShowLocked()) {
-                    continue;
-                }
-                return r;
-            }
+        if (getParent() == null) {
+            return null;
         }
-        return null;
+        return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN
+                && r.canBeTopRunning());
     }
 
     /**
      * Return the number of running activities, and the number of non-finishing/initializing
      * activities in the provided {@param reportOut} respectively.
      */
-    void getNumRunningActivities(TaskActivitiesReport reportOut) {
+    private void getNumRunningActivities(TaskActivitiesReport reportOut) {
         reportOut.reset();
-        for (int i = getChildCount() - 1; i >= 0; --i) {
-            final ActivityRecord r = getChildAt(i);
-            if (r.finishing) {
-                continue;
-            }
-
-            reportOut.base = r;
-
-            // Increment the total number of non-finishing activities
-            reportOut.numActivities++;
-
-            if (reportOut.top == null || (reportOut.top.isState(ActivityState.INITIALIZING))) {
-                reportOut.top = r;
-                // Reset the number of running activities until we hit the first non-initializing
-                // activity
-                reportOut.numRunning = 0;
-            }
-            if (r.attachedToProcess()) {
-                // Increment the number of actually running activities
-                reportOut.numRunning++;
-            }
-        }
-    }
-
-    boolean okToShowLocked() {
-        // NOTE: If {@link Task#topRunningActivity} return is not null then it is
-        // okay to show the activity when locked.
-        return mAtmService.mStackSupervisor.isCurrentProfileLocked(mUserId)
-                || topRunningActivityLocked() != null;
+        forAllActivities(reportOut);
     }
 
     /**
@@ -1212,10 +1183,11 @@
     }
 
     @Override
-    void addChild(ActivityRecord r, int index) {
+    void addChild(WindowContainer child, int index) {
         // If this task had any child before we added this one.
         boolean hadChild = hasChild();
 
+        final ActivityRecord r = (ActivityRecord) child;
         index = getAdjustedAddPosition(r, index);
         super.addChild(r, index);
 
@@ -1244,9 +1216,6 @@
         }
 
         updateEffectiveIntent();
-        if (r.isPersistable()) {
-            mAtmService.notifyTaskPersisterLocked(this, false);
-        }
 
         // Make sure the list of display UID whitelists is updated
         // now that this record is in a new task.
@@ -1258,16 +1227,13 @@
     }
 
     @Override
-    void removeChild(ActivityRecord r) {
+    void removeChild(WindowContainer r) {
         if (!mChildren.contains(r)) {
             Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
             return;
         }
 
         super.removeChild(r);
-        if (r.isPersistable()) {
-            mAtmService.notifyTaskPersisterLocked(this, false);
-        }
 
         if (inPinnedWindowingMode()) {
             // We normally notify listeners of task stack changes on pause, however pinned stack
@@ -1283,7 +1249,7 @@
             // The following block can be executed multiple times if there is more than one overlay.
             // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
             // of the task by id and exiting early if not found.
-            if (onlyHasTaskOverlayActivities(false /* excludingFinishing */)) {
+            if (onlyHasTaskOverlayActivities(true /*includeFinishing*/)) {
                 // When destroying a task, tell the supervisor to remove it so that any activity it
                 // has can be cleaned up correctly. This is currently the only place where we remove
                 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
@@ -1305,25 +1271,20 @@
 
     /**
      * @return whether or not there are ONLY task overlay activities in the stack.
-     *         If {@param excludeFinishing} is set, then ignore finishing activities in the check.
-     *         If there are no task overlay activities, this call returns false.
+     *         If {@param includeFinishing} is set, then don't ignore finishing activities in the
+     *         check. If there are no task overlay activities, this call returns false.
      */
-    boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
-        int count = 0;
-        for (int i = getChildCount() - 1; i >= 0; i--) {
-            final ActivityRecord r = getChildAt(i);
-            if (excludeFinishing && r.finishing) {
-                continue;
-            }
-            if (!r.mTaskOverlay) {
-                return false;
-            }
-            count++;
+    boolean onlyHasTaskOverlayActivities(boolean includeFinishing) {
+        if (getChildCount() == 0) {
+            return false;
         }
-        return count > 0;
+        if (includeFinishing) {
+            return getActivity((r) -> r.mTaskOverlay) != null;
+        }
+        return getActivity((r) -> !r.finishing && r.mTaskOverlay) != null;
     }
 
-    boolean autoRemoveFromRecents() {
+    private boolean autoRemoveFromRecents() {
         // We will automatically remove the task either if it has explicitly asked for
         // this, or it is empty and has never contained an activity that got shown to
         // the user.
@@ -1335,24 +1296,21 @@
      * task starting at a specified index.
      */
     private void performClearTaskAtIndexLocked(String reason) {
-        int numActivities = getChildCount();
-        for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
-            final ActivityRecord r = getChildAt(activityNdx);
-            if (r.finishing) {
-                continue;
-            }
-            if (mStack == null) {
+        // Broken down into to cases to avoid object create due to capturing mStack.
+        if (mStack == null) {
+            forAllActivities((r) -> {
+                if (r.finishing) return;
                 // Task was restored from persistent storage.
                 r.takeFromHistory();
                 removeChild(r);
-                --activityNdx;
-                --numActivities;
-            } else if (r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
-                    false /* oomAdj */)
-                    == FINISH_RESULT_REMOVED) {
-                --activityNdx;
-                --numActivities;
-            }
+            });
+        } else {
+            forAllActivities((r) -> {
+                if (r.finishing) return;
+                // TODO: figure-out how to avoid object creation due to capture of reason variable.
+                r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
+                        false /* oomAdj */);
+            });
         }
     }
 
@@ -1383,50 +1341,43 @@
      * @return Returns the old activity that should be continued to be used,
      * or {@code null} if none was found.
      */
-    final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
-        int numActivities = getChildCount();
-        for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
-            ActivityRecord r = getChildAt(activityNdx);
-            if (r.finishing) {
-                continue;
-            }
-            if (r.mActivityComponent.equals(newR.mActivityComponent)) {
-                // Here it is!  Now finish everything in front...
-                final ActivityRecord ret = r;
+    private ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
+        final ActivityRecord r = findActivityInHistory(newR.mActivityComponent);
+        if (r == null) return null;
 
-                for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
-                    r = getChildAt(activityNdx);
-                    if (r.finishing) {
-                        continue;
-                    }
-                    ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
-                    if (opts != null) {
-                        ret.updateOptionsLocked(opts);
-                    }
-                    if (r.finishIfPossible("clear-task-stack", false /* oomAdj */)
-                            == FINISH_RESULT_REMOVED) {
-                        --activityNdx;
-                        --numActivities;
-                    }
-                }
+        final PooledFunction f = PooledLambda.obtainFunction(Task::finishActivityAbove,
+                PooledLambda.__(ActivityRecord.class), r);
+        forAllActivities(f);
+        f.recycle();
 
-                // Finally, if this is a normal launch mode (that is, not
-                // expecting onNewIntent()), then we will finish the current
-                // instance of the activity so a new fresh one can be started.
-                if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
-                        && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
-                        && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
-                    if (!ret.finishing) {
-                        ret.finishIfPossible("clear-task-top", false /* oomAdj */);
-                        return null;
-                    }
-                }
-
-                return ret;
+        // Finally, if this is a normal launch mode (that is, not expecting onNewIntent()), then we
+        // will finish the current instance of the activity so a new fresh one can be started.
+        if (r.launchMode == ActivityInfo.LAUNCH_MULTIPLE
+                && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
+                && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
+            if (!r.finishing) {
+                r.finishIfPossible("clear-task-top", false /* oomAdj */);
+                return null;
             }
         }
 
-        return null;
+        return r;
+    }
+
+    private static boolean finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity) {
+        // Stop operation once we reach the boundary activity.
+        if (r == boundaryActivity) return true;
+
+        if (!r.finishing) {
+            final ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
+            if (opts != null) {
+                // TODO: Why is this updating the boundary activity vs. the current activity???
+                boundaryActivity.updateOptionsLocked(opts);
+            }
+            r.finishIfPossible("clear-task-stack", false /* oomAdj */);
+        }
+
+        return false;
     }
 
     void removeTaskActivitiesLocked(String reason) {
@@ -1537,140 +1488,83 @@
      * Find the activity in the history stack within the given task.  Returns
      * the index within the history at which it's found, or < 0 if not found.
      */
-    final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
-        final ComponentName realActivity = r.mActivityComponent;
-        for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-            ActivityRecord candidate = getChildAt(activityNdx);
-            if (candidate.finishing) {
-                continue;
-            }
-            if (candidate.mActivityComponent.equals(realActivity)) {
-                return candidate;
-            }
-        }
-        return null;
+    ActivityRecord findActivityInHistory(ComponentName component) {
+        final PooledPredicate p = PooledLambda.obtainPredicate(Task::matchesActivityInHistory,
+                PooledLambda.__(ActivityRecord.class), component);
+        final ActivityRecord r = getActivity(p);
+        p.recycle();
+        return r;
+    }
+
+    private static boolean matchesActivityInHistory(
+            ActivityRecord r, ComponentName activityComponent) {
+        return !r.finishing && r.mActivityComponent.equals(activityComponent);
     }
 
     /** Updates the last task description values. */
     void updateTaskDescription() {
-        // TODO(AM refactor): Cleanup to use findRootIndex()
-        // Traverse upwards looking for any break between main task activities and
-        // utility activities.
-        int activityNdx;
-        final int numActivities = getChildCount();
-        final boolean relinquish = numActivities != 0
-                && (getChildAt(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
-        for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities; ++activityNdx) {
-            final ActivityRecord r = getChildAt(activityNdx);
-            if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
-                // This will be the top activity for determining taskDescription. Pre-inc to
-                // overcome initial decrement below.
-                ++activityNdx;
-                break;
-            }
-            if (r.intent != null
-                    && (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
-                break;
-            }
+        final ActivityRecord root = getRootActivity(true);
+        if (root == null) return;
+
+        final TaskDescription taskDescription = new TaskDescription();
+        final PooledFunction f = PooledLambda.obtainFunction(
+                Task::setTaskDescriptionFromActivityAboveRoot,
+                PooledLambda.__(ActivityRecord.class), root, taskDescription);
+        forAllActivities(f);
+        f.recycle();
+        taskDescription.setResizeMode(mResizeMode);
+        taskDescription.setMinWidth(mMinWidth);
+        taskDescription.setMinHeight(mMinHeight);
+        setTaskDescription(taskDescription);
+        // Update the task affiliation color if we are the parent of the group
+        if (mTaskId == mAffiliatedTaskId) {
+            mAffiliatedTaskColor = taskDescription.getPrimaryColor();
         }
-        if (activityNdx > 0) {
-            // Traverse downwards starting below break looking for set label, icon.
-            // Note that if there are activities in the task but none of them set the
-            // recent activity values, then we do not fall back to the last set
-            // values in the Task.
-            String label = null;
-            String iconFilename = null;
-            int iconResource = -1;
-            int colorPrimary = 0;
-            int colorBackground = 0;
-            int statusBarColor = 0;
-            int navigationBarColor = 0;
-            boolean statusBarContrastWhenTransparent = false;
-            boolean navigationBarContrastWhenTransparent = false;
-            boolean topActivity = true;
-            for (--activityNdx; activityNdx >= 0; --activityNdx) {
-                final ActivityRecord r = getChildAt(activityNdx);
-                if (r.mTaskOverlay) {
-                    continue;
-                }
-                if (r.taskDescription != null) {
-                    if (label == null) {
-                        label = r.taskDescription.getLabel();
-                    }
-                    if (iconResource == -1) {
-                        iconResource = r.taskDescription.getIconResource();
-                    }
-                    if (iconFilename == null) {
-                        iconFilename = r.taskDescription.getIconFilename();
-                    }
-                    if (colorPrimary == 0) {
-                        colorPrimary = r.taskDescription.getPrimaryColor();
-                    }
-                    if (topActivity) {
-                        colorBackground = r.taskDescription.getBackgroundColor();
-                        statusBarColor = r.taskDescription.getStatusBarColor();
-                        navigationBarColor = r.taskDescription.getNavigationBarColor();
-                        statusBarContrastWhenTransparent =
-                                r.taskDescription.getEnsureStatusBarContrastWhenTransparent();
-                        navigationBarContrastWhenTransparent =
-                                r.taskDescription.getEnsureNavigationBarContrastWhenTransparent();
-                    }
-                }
-                topActivity = false;
-            }
-            final TaskDescription taskDescription = new TaskDescription(label, null, iconResource,
-                    iconFilename, colorPrimary, colorBackground, statusBarColor, navigationBarColor,
-                    statusBarContrastWhenTransparent, navigationBarContrastWhenTransparent,
-                    mResizeMode, mMinWidth, mMinHeight);
-            setTaskDescription(taskDescription);
-            // Update the task affiliation color if we are the parent of the group
-            if (mTaskId == mAffiliatedTaskId) {
-                mAffiliatedTaskColor = taskDescription.getPrimaryColor();
-            }
-            mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged(
-                    getTaskInfo());
-        }
+        mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged(
+                getTaskInfo());
     }
 
-    /**
-     * Find the index of the root activity in the task. It will be the first activity from the
-     * bottom that is not finishing.
-     *
-     * @param effectiveRoot Flag indicating whether 'effective root' should be returned - an
-     *                      activity that defines the task identity (its base intent). It's the
-     *                      first one that does not have
-     *                      {@link ActivityInfo#FLAG_RELINQUISH_TASK_IDENTITY}.
-     * @return index of the 'root' or 'effective' root in the list of activities, -1 if no eligible
-     *         activity was found.
-     */
-    int findRootIndex(boolean effectiveRoot) {
-        int effectiveNdx = -1;
-        final int topActivityNdx = getChildCount() - 1;
-        for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
-            final ActivityRecord r = getChildAt(activityNdx);
-            if (r.finishing) {
-                continue;
+    private static boolean setTaskDescriptionFromActivityAboveRoot(
+            ActivityRecord r, ActivityRecord root, TaskDescription td) {
+        if (!r.mTaskOverlay && r.taskDescription != null) {
+            final TaskDescription atd = r.taskDescription;
+            if (td.getLabel() == null) {
+                td.setLabel(atd.getLabel());
             }
-            effectiveNdx = activityNdx;
-            if (!effectiveRoot || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
-                break;
+            if (td.getIconResource() == 0) {
+                td.setIcon(atd.getIconResource());
             }
+            if (td.getIconFilename() == null) {
+                td.setIconFilename(atd.getIconFilename());
+            }
+            if (td.getPrimaryColor() == 0) {
+                td.setPrimaryColor(atd.getPrimaryColor());
+            }
+            if (td.getBackgroundColor() == 0) {
+                td.setBackgroundColor(atd.getBackgroundColor());
+            }
+            if (td.getStatusBarColor() == 0) {
+                td.setStatusBarColor(atd.getStatusBarColor());
+                td.setEnsureStatusBarContrastWhenTransparent(
+                        atd.getEnsureStatusBarContrastWhenTransparent());
+            }
+            if (td.getNavigationBarColor() == 0) {
+                td.setNavigationBarColor(atd.getNavigationBarColor());
+                td.setEnsureNavigationBarContrastWhenTransparent(
+                        atd.getEnsureNavigationBarContrastWhenTransparent());
+            }
+
         }
-        return effectiveNdx;
+
+        // End search once we get to root.
+        return r == root;
     }
 
     // TODO (AM refactor): Invoke automatically when there is a change in children
     @VisibleForTesting
     void updateEffectiveIntent() {
-        int effectiveRootIndex = findRootIndex(true /* effectiveRoot */);
-        if (effectiveRootIndex == -1) {
-            // All activities in the task are either finishing or relinquish task identity.
-            // But we still want to update the intent, so let's use the bottom activity.
-            effectiveRootIndex = 0;
-        }
-        final ActivityRecord r = getChildAt(effectiveRootIndex);
-        setIntent(r);
-
+        final ActivityRecord root = getRootActivity(true /*setToBottomIfNone*/);
+        setIntent(root);
         // Update the task description when the activities change
         updateTaskDescription();
     }
@@ -2220,15 +2114,6 @@
         return mLastNonFullscreenBounds;
     }
 
-    void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
-        for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
-            final ActivityRecord r = getChildAt(activityNdx);
-            if (r.mVisibleRequested) {
-                r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
-            }
-        }
-    }
-
     void setRootProcess(WindowProcessController proc) {
         clearRootProcess();
         if (intent != null
@@ -2245,12 +2130,6 @@
         }
     }
 
-    void clearAllPendingOptions() {
-        for (int i = getChildCount() - 1; i >= 0; i--) {
-            getChildAt(i).clearOptionsLocked(false /* withAbort */);
-        }
-    }
-
     @Override
     DisplayContent getDisplayContent() {
         return getTaskStack() != null ? getTaskStack().getDisplayContent() : null;
@@ -2260,20 +2139,14 @@
         return (ActivityStack) getParent();
     }
 
+    // TODO(task-hierarchy): Needs to take a generic WindowManager when task contains other tasks.
     int getAdjustedAddPosition(ActivityRecord r, int suggestedPosition) {
         int maxPosition = mChildren.size();
         if (!r.mTaskOverlay) {
             // We want to place all non-overlay activities below overlays.
-            while (maxPosition > 0) {
-                final ActivityRecord current = mChildren.get(maxPosition - 1);
-                if (current.mTaskOverlay) {
-                    --maxPosition;
-                    continue;
-                }
-                break;
-            }
-            if (maxPosition < 0) {
-                maxPosition = 0;
+            final ActivityRecord bottomMostOverlay = getActivity((ar) -> ar.mTaskOverlay, false);
+            if (bottomMostOverlay != null) {
+                maxPosition = Math.max(mChildren.indexOf(bottomMostOverlay) - 1, 0);
             }
         }
 
@@ -2281,18 +2154,13 @@
     }
 
     @Override
-    void positionChildAt(int position, ActivityRecord child, boolean includingParents) {
-        position = getAdjustedAddPosition(child, position);
+    void positionChildAt(int position, WindowContainer child, boolean includingParents) {
+        position = getAdjustedAddPosition((ActivityRecord) child, position);
         super.positionChildAt(position, child, includingParents);
     }
 
     private boolean hasWindowsAlive() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            if (mChildren.get(i).hasWindowsAlive()) {
-                return true;
-            }
-        }
-        return false;
+        return getActivity(ActivityRecord::hasWindowsAlive) != null;
     }
 
     @VisibleForTesting
@@ -2522,26 +2390,21 @@
      * @param out Rect containing the max visible bounds.
      * @return true if the task has some visible app windows; false otherwise.
      */
-    private boolean getMaxVisibleBounds(Rect out) {
-        boolean foundTop = false;
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final ActivityRecord token = mChildren.get(i);
-            // skip hidden (or about to hide) apps
-            if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
-                continue;
-            }
-            final WindowState win = token.findMainWindow();
-            if (win == null) {
-                continue;
-            }
-            if (!foundTop) {
-                foundTop = true;
-                out.setEmpty();
-            }
-
-            win.getMaxVisibleBounds(out);
+    private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) {
+        // skip hidden (or about to hide) apps
+        if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
+            return;
         }
-        return foundTop;
+        final WindowState win = token.findMainWindow();
+        if (win == null) {
+            return;
+        }
+        if (!foundTop[0]) {
+            foundTop[0] = true;
+            out.setEmpty();
+        }
+
+        win.getMaxVisibleBounds(out);
     }
 
     /** Bounds of the task to be used for dimming, as well as touch related tests. */
@@ -2551,8 +2414,14 @@
         // a DimLayer anyway if we weren't visible.
         final boolean dockedResizing = displayContent != null
                 && displayContent.mDividerControllerLocked.isResizing();
-        if (inFreeformWindowingMode() && getMaxVisibleBounds(out)) {
-            return;
+        if (inFreeformWindowingMode()) {
+            boolean[] foundTop = { false };
+            final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
+                    PooledLambda.__(ActivityRecord.class), out, foundTop);
+            c.recycle();
+            if (foundTop[0]) {
+                return;
+            }
         }
 
         if (!matchParentBounds()) {
@@ -2658,8 +2527,9 @@
     }
 
     boolean showForAllUsers() {
-        final int tokensCount = mChildren.size();
-        return (tokensCount != 0) && mChildren.get(tokensCount - 1).mShowForAllUsers;
+        if (mChildren.isEmpty()) return false;
+        final ActivityRecord r = getTopNonFinishingActivity();
+        return r != null && r.mShowForAllUsers;
     }
 
     /**
@@ -2733,24 +2603,17 @@
     }
 
     ActivityRecord getTopFullscreenActivity() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final ActivityRecord activity = mChildren.get(i);
-            final WindowState win = activity.findMainWindow();
-            if (win != null && win.mAttrs.isFullscreen()) {
-                return activity;
-            }
-        }
-        return null;
+        return getActivity((r) -> {
+            final WindowState win = r.findMainWindow();
+            return (win != null && win.mAttrs.isFullscreen());
+        });
     }
 
     ActivityRecord getTopVisibleActivity() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final ActivityRecord activity = mChildren.get(i);
-            if (!activity.mIsExiting && activity.isClientVisible() && activity.mVisibleRequested) {
-                return activity;
-            }
-        }
-        return null;
+        return getActivity((r) -> {
+            // skip hidden (or about to hide) apps
+            return !r.mIsExiting && r.isClientVisible() && r.mVisibleRequested;
+        });
     }
 
     void positionChildAtTop(ActivityRecord child) {
@@ -2806,6 +2669,13 @@
         return callback.apply(this);
     }
 
+    @Override
+    Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
+        // I'm a task!
+        // TODO(task-hierarchy): Change to traverse children when tasks can contain other tasks.
+        return callback.test(this) ? this : null;
+    }
+
     /**
      * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
      *                               flags. See {@link WindowState#canAffectSystemUiFlags()}.
@@ -2861,10 +2731,9 @@
         final long token = proto.start(fieldId);
         super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
         proto.write(TaskProto.ID, mTaskId);
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final ActivityRecord activity = mChildren.get(i);
-            activity.writeToProto(proto, APP_WINDOW_TOKENS, logLevel);
-        }
+        forAllActivities((r) -> {
+            r.writeToProto(proto, APP_WINDOW_TOKENS, logLevel);
+        });
         proto.write(FILLS_PARENT, matchParentBounds());
         getBounds().writeToProto(proto, TaskProto.BOUNDS);
         mOverrideDisplayedBounds.writeToProto(proto, DISPLAYED_BOUNDS);
@@ -2888,11 +2757,11 @@
         final String triplePrefix = doublePrefix + "  ";
         final String quadruplePrefix = triplePrefix + "  ";
 
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final ActivityRecord activity = mChildren.get(i);
-            pw.println(triplePrefix + "Activity #" + i + " " + activity);
-            activity.dump(pw, quadruplePrefix, dumpAll);
-        }
+        int[] index = { 0 };
+        forAllActivities((r) -> {
+            pw.println(triplePrefix + "Activity #" + index[0]++ + " " + r);
+            r.dump(pw, quadruplePrefix, dumpAll);
+        });
     }
 
     /**
@@ -3071,10 +2940,10 @@
         final long token = proto.start(fieldId);
         writeToProtoInnerTaskOnly(proto, TASK, logLevel);
         proto.write(com.android.server.am.TaskRecordProto.ID, mTaskId);
-        for (int i = getChildCount() - 1; i >= 0; i--) {
-            final ActivityRecord activity = getChildAt(i);
-            activity.writeToProto(proto, ACTIVITIES);
-        }
+
+        forAllActivities((r) -> {
+            r.writeToProto(proto, ACTIVITIES);
+        });
         proto.write(STACK_ID, getStackId());
         if (mLastNonFullscreenBounds != null) {
             mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
@@ -3100,7 +2969,7 @@
     }
 
     /** @see #getNumRunningActivities(TaskActivitiesReport) */
-    static class TaskActivitiesReport {
+    static class TaskActivitiesReport implements Consumer<ActivityRecord> {
         int numRunning;
         int numActivities;
         ActivityRecord top;
@@ -3110,12 +2979,35 @@
             numRunning = numActivities = 0;
             top = base = null;
         }
+
+        @Override
+        public void accept(ActivityRecord r) {
+            if (r.finishing) {
+                return;
+            }
+
+            base = r;
+
+            // Increment the total number of non-finishing activities
+            numActivities++;
+
+            if (top == null || (top.isState(ActivityState.INITIALIZING))) {
+                top = r;
+                // Reset the number of running activities until we hit the first non-initializing
+                // activity
+                numRunning = 0;
+            }
+            if (r.attachedToProcess()) {
+                // Increment the number of actually running activities
+                numRunning++;
+            }
+        }
     }
 
     /**
      * Saves this {@link Task} to XML using given serializer.
      */
-    void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
+    void saveToXml(XmlSerializer out) throws Exception {
         if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
 
         out.attribute(null, ATTR_TASKID, String.valueOf(mTaskId));
@@ -3181,19 +3073,33 @@
             out.endTag(null, TAG_INTENT);
         }
 
-        final int numActivities = getChildCount();
-        for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
-            final ActivityRecord r = getChildAt(activityNdx);
-            if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable()
-                    || ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
-                            | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT)
-                    && activityNdx > 0) {
-                // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
-                break;
-            }
+        sTmpException = null;
+        final PooledFunction f = PooledLambda.obtainFunction(Task::saveActivityToXml,
+                PooledLambda.__(ActivityRecord.class), getBottomMostActivity(), out);
+        forAllActivities(f);
+        f.recycle();
+        if (sTmpException != null) {
+            throw sTmpException;
+        }
+    }
+
+    private static boolean saveActivityToXml(
+            ActivityRecord r, ActivityRecord first, XmlSerializer out) {
+        if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable()
+                || ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
+                | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT)
+                && r != first) {
+            // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
+            return true;
+        }
+        try {
             out.startTag(null, TAG_ACTIVITY);
             r.saveToXml(out);
             out.endTag(null, TAG_ACTIVITY);
+            return false;
+        } catch (Exception e) {
+            sTmpException = e;
+            return true;
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java
index 1e2f0d0..eb130a1 100644
--- a/services/core/java/com/android/server/wm/TaskPersister.java
+++ b/services/core/java/com/android/server/wm/TaskPersister.java
@@ -514,7 +514,7 @@
             mService = service;
         }
 
-        private StringWriter saveToXml(Task task) throws IOException, XmlPullParserException {
+        private StringWriter saveToXml(Task task) throws Exception {
             if (DEBUG) Slog.d(TAG, "saveToXml: task=" + task);
             final XmlSerializer xmlSerializer = new FastXmlSerializer();
             StringWriter stringWriter = new StringWriter();
@@ -550,8 +550,7 @@
                     try {
                         if (DEBUG) Slog.d(TAG, "Saving task=" + task);
                         stringWriter = saveToXml(task);
-                    } catch (IOException e) {
-                    } catch (XmlPullParserException e) {
+                    } catch (Exception e) {
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotCache.java b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
index d07516a..5cbab5d 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotCache.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
@@ -48,9 +48,9 @@
         if (entry != null) {
             mAppTaskMap.remove(entry.topApp);
         }
-        final ActivityRecord top = task.getTopChild();
+        final ActivityRecord top = task.getTopMostActivity();
         mAppTaskMap.put(top, task.mTaskId);
-        mRunningCache.put(task.mTaskId, new CacheEntry(snapshot, task.getTopChild()));
+        mRunningCache.put(task.mTaskId, new CacheEntry(snapshot, top));
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index f83ceb0..c1a36c4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -235,23 +235,18 @@
      * children, which should be ignored.
      */
     @Nullable private ActivityRecord findAppTokenForSnapshot(Task task) {
-        for (int i = task.getChildCount() - 1; i >= 0; --i) {
-            final ActivityRecord activity = task.getChildAt(i);
-            if (activity == null || !activity.isSurfaceShowing()
-                    || activity.findMainWindow() == null) {
-                continue;
+        return task.getActivity((r) -> {
+            if (r == null || !r.isSurfaceShowing() || r.findMainWindow() == null) {
+                return false;
             }
-            final boolean hasVisibleChild = activity.forAllWindows(
+            return r.forAllWindows(
                     // Ensure at least one window for the top app is visible before attempting to
                     // take a screenshot. Visible here means that the WSA surface is shown and has
                     // an alpha greater than 0.
                     ws -> ws.mWinAnimator != null && ws.mWinAnimator.getShown()
                             && ws.mWinAnimator.mLastAlpha > 0f, true  /* traverseTopToBottom */);
-            if (hasVisibleChild) {
-                return activity;
-            }
-        }
-        return null;
+
+        });
     }
 
     @Nullable
@@ -380,7 +375,7 @@
 
     @VisibleForTesting
     int getSnapshotMode(Task task) {
-        final ActivityRecord topChild = task.getTopChild();
+        final ActivityRecord topChild = task.getTopMostActivity();
         if (!task.isActivityTypeStandardOrUndefined() && !task.isActivityTypeAssistant()) {
             return SNAPSHOT_MODE_NONE;
         } else if (topChild != null && topChild.shouldUseAppThemeSnapshot()) {
@@ -395,7 +390,7 @@
      * as possible by using the theme's window background.
      */
     private TaskSnapshot drawAppThemeSnapshot(Task task) {
-        final ActivityRecord topChild = task.getTopChild();
+        final ActivityRecord topChild = task.getTopMostActivity();
         if (topChild == null) {
             return null;
         }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 453514b2..5c1491e 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -310,6 +310,10 @@
     final protected void setParent(WindowContainer<WindowContainer> parent) {
         final WindowContainer oldParent = mParent;
         mParent = parent;
+
+        if (mParent != null) {
+            mParent.onChildAdded(this);
+        }
         if (!mReparenting) {
             onParentChanged(mParent, oldParent);
         }
@@ -389,7 +393,6 @@
         } else {
             mChildren.add(positionToAdd, child);
         }
-        onChildAdded(child);
 
         // Set the parent after we've actually added a child in case a subclass depends on this.
         child.setParent(this);
@@ -418,7 +421,6 @@
         }
 
         mChildren.add(index, child);
-        onChildAdded(child);
 
         // Set the parent after we've actually added a child in case a subclass depends on this.
         child.setParent(this);
@@ -1096,11 +1098,22 @@
     }
 
     boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            if (mChildren.get(i).forAllActivities(callback)) {
-                return true;
+        return forAllActivities(callback, true /*traverseTopToBottom*/);
+    }
+
+    boolean forAllActivities(
+            Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
+        if (traverseTopToBottom) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
+            }
+        } else {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
             }
         }
+
         return false;
     }
 
@@ -1121,6 +1134,61 @@
         }
     }
 
+    /**
+     * Process all activities in this branch of the tree.
+     *
+     * @param callback Called for each activity found.
+     * @param boundary We don't return activities via {@param callback} until we get to this node in
+     *                 the tree.
+     * @param includeBoundary If the boundary from be processed to return activities.
+     * @param traverseTopToBottom direction to traverse the tree.
+     * @return {@code true} if we ended the search before reaching the end of the tree.
+     */
+    final boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
+            WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
+        return forAllActivities(
+                callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
+    }
+
+    private boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
+            WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
+            boolean[] boundaryFound) {
+        if (traverseTopToBottom) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
+                        traverseTopToBottom, boundaryFound, mChildren.get(i))) {
+                    return true;
+                }
+            }
+        } else {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
+                        traverseTopToBottom, boundaryFound, mChildren.get(i))) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private boolean processForAllActivitiesWithBoundary(Function<ActivityRecord, Boolean> callback,
+            WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
+            boolean[] boundaryFound, WindowContainer wc) {
+        if (wc == boundary) {
+            boundaryFound[0] = true;
+            if (!includeBoundary) return false;
+        }
+
+        if (boundaryFound[0]) {
+            return wc.forAllActivities(callback, traverseTopToBottom);
+        }
+
+        return wc.forAllActivities(
+                callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
+    }
+
     /** @return {@code true} if this node or any of its children contains an activity. */
     boolean hasActivity() {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
@@ -1156,6 +1224,81 @@
         return null;
     }
 
+    /**
+     * Gets an activity in a branch of the tree.
+     *
+     * @param callback called to test if this is the activity that should be returned.
+     * @param boundary We don't return activities via {@param callback} until we get to this node in
+     *                 the tree.
+     * @param includeBoundary If the boundary from be processed to return activities.
+     * @param traverseTopToBottom direction to traverse the tree.
+     * @return The activity if found or null.
+     */
+    final ActivityRecord getActivity(Predicate<ActivityRecord> callback,
+            WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
+        return getActivity(
+                callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
+    }
+
+    private ActivityRecord getActivity(Predicate<ActivityRecord> callback,
+            WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
+            boolean[] boundaryFound) {
+        if (traverseTopToBottom) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
+                        includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
+                if (r != null) {
+                    return r;
+                }
+            }
+        } else {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
+                        includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
+                if (r != null) {
+                    return r;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private ActivityRecord processGetActivityWithBoundary(Predicate<ActivityRecord> callback,
+            WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
+            boolean[] boundaryFound, WindowContainer wc) {
+        if (wc == boundary || boundary == null) {
+            boundaryFound[0] = true;
+            if (!includeBoundary) return null;
+        }
+
+        if (boundaryFound[0]) {
+            return wc.getActivity(callback, traverseTopToBottom);
+        }
+
+        return wc.getActivity(
+                callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
+    }
+
+    ActivityRecord getActivityAbove(ActivityRecord r) {
+        return getActivity((above) -> true, r,
+                false /*includeBoundary*/, false /*traverseTopToBottom*/);
+    }
+
+    ActivityRecord getActivityBelow(ActivityRecord r) {
+        return getActivity((below) -> true, r,
+                false /*includeBoundary*/, true /*traverseTopToBottom*/);
+    }
+
+    ActivityRecord getBottomMostActivity() {
+        return getActivity((r) -> true, false /*traverseTopToBottom*/);
+    }
+
+    ActivityRecord getTopMostActivity() {
+        return getActivity((r) -> true, true /*traverseTopToBottom*/);
+    }
+
     ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
         // Break down into 4 calls to avoid object creation due to capturing input params.
         if (includeFinishing) {
@@ -1187,6 +1330,31 @@
         }
     }
 
+    Task getTask(Predicate<Task> callback) {
+        return getTask(callback, true /*traverseTopToBottom*/);
+    }
+
+    Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
+        if (traverseTopToBottom) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
+                if (t != null) {
+                    return t;
+                }
+            }
+        } else {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
+                if (t != null) {
+                    return t;
+                }
+            }
+        }
+
+        return null;
+    }
+
     /**
      * For all tasks at or below this container call the callback.
      *
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index c1783ef..e169037 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -722,11 +722,10 @@
         return true;
     }
 
-    ArraySet<Task> getReleaseSomeActivitiesTasks() {
+    void releaseSomeActivities(String reason) {
         // Examine all activities currently running in the process.
-        Task firstTask = null;
-        // Tasks is non-null only if two or more tasks are found.
-        ArraySet<Task> tasks = null;
+        // Candidate activities that can be destroyed.
+        ArrayList<ActivityRecord> candidates = null;
         if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + this);
         for (int i = 0; i < mActivities.size(); i++) {
             final ActivityRecord r = mActivities.get(i);
@@ -735,33 +734,37 @@
             // down before we try to prune more activities.
             if (r.finishing || r.isState(DESTROYING, DESTROYED)) {
                 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Abort release; already destroying: " + r);
-                return null;
+                return;
             }
             // Don't consider any activities that are currently not in a state where they
             // can be destroyed.
-            if (r.mVisibleRequested || !r.stopped || !r.hasSavedState()
+            if (r.mVisibleRequested || !r.stopped || !r.hasSavedState() || !r.isDestroyable()
                     || r.isState(STARTED, RESUMED, PAUSING, PAUSED, STOPPING)) {
                 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
                 continue;
             }
 
-            final Task task = r.getTask();
-            if (task != null) {
-                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + task
-                        + " from " + r);
-                if (firstTask == null) {
-                    firstTask = task;
-                } else if (firstTask != task) {
-                    if (tasks == null) {
-                        tasks = new ArraySet<>();
-                        tasks.add(firstTask);
-                    }
-                    tasks.add(task);
+            if (r.getParent() != null) {
+                if (candidates == null) {
+                    candidates = new ArrayList<>();
                 }
+                candidates.add(r);
             }
         }
 
-        return tasks;
+        if (candidates != null) {
+            // Sort based on z-order in hierarchy.
+            candidates.sort(WindowContainer::compareTo);
+            // Release some older activities
+            int maxRelease = Math.max(candidates.size(), 1);
+            do {
+                final ActivityRecord r = candidates.remove(0);
+                if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + r
+                        + " in state " + r.getState() + " for reason " + reason);
+                r.destroyImmediately(true /*removeFromApp*/, reason);
+                --maxRelease;
+            } while (maxRelease > 0);
+        }
     }
 
     public interface ComputeOomAdjCallback {
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
index 495923d..a14197b 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
@@ -30,6 +30,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -109,7 +110,7 @@
                                                 /* isHashedValue= */ false))),
                         Rule.DENY);
 
-        List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
+        List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula.getBytes(StandardCharsets.UTF_8));
 
         assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
     }
@@ -154,7 +155,7 @@
                                                 "test_cert",
                                                 /* isHashedValue= */ false))),
                         Rule.DENY);
-        List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
+        List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula.getBytes(StandardCharsets.UTF_8));
 
         assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
     }
@@ -200,7 +201,7 @@
                                                 /* isHashedValue= */ false))),
                         Rule.DENY);
 
-        List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
+        List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula.getBytes(StandardCharsets.UTF_8));
 
         assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
     }
@@ -237,7 +238,7 @@
                                                 /* isHashedValue= */ false))),
                         Rule.DENY);
 
-        List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
+        List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula.getBytes(StandardCharsets.UTF_8));
 
         assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
     }
@@ -273,7 +274,7 @@
         assertExpectException(
                 RuleParseException.class,
                 /* expectedExceptionMessageRegex */ "Connector NOT must have 1 formula only",
-                () -> xmlParser.parse(ruleXmlCompoundFormula));
+                () -> xmlParser.parse(ruleXmlCompoundFormula.getBytes(StandardCharsets.UTF_8)));
     }
 
     @Test
@@ -302,7 +303,7 @@
         assertExpectException(
                 RuleParseException.class,
                 /* expectedExceptionMessageRegex */ "For input string: \"INVALID_OPERATOR\"",
-                () -> xmlParser.parse(ruleXmlCompoundFormula));
+                () -> xmlParser.parse(ruleXmlCompoundFormula.getBytes(StandardCharsets.UTF_8)));
     }
 
     @Test
@@ -330,7 +331,7 @@
         assertExpectException(
                 RuleParseException.class,
                 /* expectedExceptionMessageRegex */ "For input string: \"INVALID_EFFECT\"",
-                () -> xmlParser.parse(ruleXmlCompoundFormula));
+                () -> xmlParser.parse(ruleXmlCompoundFormula.getBytes(StandardCharsets.UTF_8)));
     }
 
     @Test
@@ -360,7 +361,7 @@
         assertExpectException(
                 RuleParseException.class,
                 /* expectedExceptionMessageRegex */ "Found unexpected tag: InvalidAtomicFormula",
-                () -> xmlParser.parse(ruleXmlCompoundFormula));
+                () -> xmlParser.parse(ruleXmlCompoundFormula.getBytes(StandardCharsets.UTF_8)));
     }
 
     @Test
@@ -387,7 +388,7 @@
                                 /* isHashedValue= */ false),
                         Rule.DENY);
 
-        List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
+        List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula.getBytes(StandardCharsets.UTF_8));
 
         assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
     }
@@ -415,7 +416,7 @@
                                 AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
                         Rule.DENY);
 
-        List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
+        List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula.getBytes(StandardCharsets.UTF_8));
 
         assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
     }
@@ -441,7 +442,7 @@
                         new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
                         Rule.DENY);
 
-        List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
+        List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula.getBytes(StandardCharsets.UTF_8));
 
         assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
     }
@@ -470,7 +471,7 @@
                                 /* isHashedValue= */ false),
                         Rule.DENY);
 
-        List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
+        List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula.getBytes(StandardCharsets.UTF_8));
 
         assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
     }
@@ -495,7 +496,7 @@
         assertExpectException(
                 RuleParseException.class,
                 /* expectedExceptionMessageRegex */ "Found unexpected key: -1",
-                () -> xmlParser.parse(ruleXmlAtomicFormula));
+                () -> xmlParser.parse(ruleXmlAtomicFormula.getBytes(StandardCharsets.UTF_8)));
     }
 
     @Test
@@ -517,7 +518,7 @@
         assertExpectException(
                 RuleParseException.class,
                 /* expectedExceptionMessageRegex */ "Unknown effect: -1",
-                () -> xmlParser.parse(ruleXmlAtomicFormula));
+                () -> xmlParser.parse(ruleXmlAtomicFormula.getBytes(StandardCharsets.UTF_8)));
     }
 
     @Test
@@ -545,7 +546,7 @@
         assertExpectException(
                 RuleParseException.class,
                 /* expectedExceptionMessageRegex */ "Unknown connector: -1",
-                () -> xmlParser.parse(ruleXmlCompoundFormula));
+                () -> xmlParser.parse(ruleXmlCompoundFormula.getBytes(StandardCharsets.UTF_8)));
     }
 
     @Test
@@ -569,7 +570,7 @@
         assertExpectException(
                 RuleParseException.class,
                 /* expectedExceptionMessageRegex */ "For input string: \"com.app.test\"",
-                () -> xmlParser.parse(ruleXmlAtomicFormula));
+                () -> xmlParser.parse(ruleXmlAtomicFormula.getBytes(StandardCharsets.UTF_8)));
     }
 
     @Test
@@ -595,7 +596,7 @@
         assertExpectException(
                 RuleParseException.class,
                 /* expectedExceptionMessageRegex */ "Rules must start with RuleList <RL> tag",
-                () -> xmlParser.parse(ruleXmlWithNoRuleList));
+                () -> xmlParser.parse(ruleXmlWithNoRuleList.getBytes(StandardCharsets.UTF_8)));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
new file mode 100644
index 0000000..4b7dd36
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.pm;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.PackageParser;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.compat.PlatformCompat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+
+/**
+ * {@link SELinuxMMAC} tests.
+ */
+@RunWith(MockitoJUnitRunner.class)
+@Presubmit
+public class SELinuxMMACTest {
+
+    private static final String PACKAGE_NAME = "my.package";
+    private static final int OPT_IN_VERSION = android.os.Build.VERSION_CODES.R;
+
+    @Mock
+    PlatformCompat mMockCompatibility;
+
+    PackageParser.Package mPkg;
+
+    @Before
+    public void setUp() {
+        mPkg = new PackageParser.Package(PACKAGE_NAME);
+        mPkg.applicationInfo.targetSdkVersion = 28;
+    }
+
+    @Test
+    public void getSeInfoOptInToLatest() {
+        when(mMockCompatibility.isChangeEnabled(SELinuxMMAC.SELINUX_LATEST_CHANGES,
+                mPkg.applicationInfo)).thenReturn(true);
+        assertThat(SELinuxMMAC.getSeInfo(mPkg, null, mMockCompatibility),
+                is("default:targetSdkVersion=" + OPT_IN_VERSION));
+    }
+
+    @Test
+    public void getSeInfoNoOptIn() {
+        when(mMockCompatibility.isChangeEnabled(SELinuxMMAC.SELINUX_LATEST_CHANGES,
+                mPkg.applicationInfo)).thenReturn(false);
+        assertThat(SELinuxMMAC.getSeInfo(mPkg, null, mMockCompatibility),
+                is("default:targetSdkVersion=28"));
+    }
+
+    @Test
+    public void getSeInfoNoOptInButAlreadyR() {
+        mPkg.applicationInfo.targetSdkVersion = OPT_IN_VERSION;
+        when(mMockCompatibility.isChangeEnabled(SELinuxMMAC.SELINUX_LATEST_CHANGES,
+                mPkg.applicationInfo)).thenReturn(false);
+        assertThat(SELinuxMMAC.getSeInfo(mPkg, null, mMockCompatibility),
+                is("default:targetSdkVersion=" + OPT_IN_VERSION));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index 3ea3b3c..74ef034 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -48,6 +48,8 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.Pair;
 
+import com.android.server.compat.PlatformCompat;
+
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
@@ -71,12 +73,15 @@
     @Mock
     UserManagerInternal mMockUserManager;
     @Mock
+    PlatformCompat mMockCompatibility;
+    @Mock
     PackageManagerService.Injector mMockInjector;
 
     @Before
     public void setupInjector() {
         when(mMockInjector.getAbiHelper()).thenReturn(mMockPackageAbiHelper);
         when(mMockInjector.getUserManagerInternal()).thenReturn(mMockUserManager);
+        when(mMockInjector.getCompatibility()).thenReturn(mMockCompatibility);
     }
 
     @Before
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index b1b386b..c2b8827 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -914,7 +914,7 @@
         // Add another stack to become focused and make the activity there visible. This way it
         // simulates finishing in non-focused stack in split-screen.
         final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
-        final ActivityRecord focusedActivity = stack.getChildAt(0).getChildAt(0);
+        final ActivityRecord focusedActivity = stack.getTopMostActivity();
         focusedActivity.nowVisible = true;
         focusedActivity.mVisibleRequested = true;
         focusedActivity.setState(RESUMED, "test");
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index ba54859..c8795ce 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -241,7 +241,7 @@
 
         final RootActivityContainer.FindTaskResult result =
                 new RootActivityContainer.FindTaskResult();
-        mStack.findTaskLocked(r, result);
+        result.process(r, mStack);
 
         assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */));
         assertEquals(taskOverlay, task.getTopNonFinishingActivity(true /* includeOverlays */));
@@ -266,14 +266,14 @@
         final ActivityRecord r1 = new ActivityBuilder(mService).setComponent(
                 target).setTargetActivity(targetActivity).build();
         RootActivityContainer.FindTaskResult result = new RootActivityContainer.FindTaskResult();
-        mStack.findTaskLocked(r1, result);
+        result.process(r1, mStack);
         assertThat(result.mRecord).isNotNull();
 
         // Using alias activity to find task.
         final ActivityRecord r2 = new ActivityBuilder(mService).setComponent(
                 alias).setTargetActivity(targetActivity).build();
         result = new RootActivityContainer.FindTaskResult();
-        mStack.findTaskLocked(r2, result);
+        result.process(r2, mStack);
         assertThat(result.mRecord).isNotNull();
     }
 
@@ -846,9 +846,9 @@
         mStack.mResumedActivity = secondActivity;
 
         // Note the activities have non-null ActivityRecord.app, so it won't remove directly.
-        mStack.finishDisabledPackageActivitiesLocked(firstActivity.packageName,
-                null /* filterByClasses */, true /* doit */, true /* evenPersistent */,
-                UserHandle.USER_ALL);
+        mRootActivityContainer.mFinishDisabledPackageActivitiesHelper.process(
+                firstActivity.packageName, null /* filterByClasses */, true /* doit */,
+                true /* evenPersistent */, UserHandle.USER_ALL);
 
         // If the activity is disabled with {@link android.content.pm.PackageManager#DONT_KILL_APP}
         // the activity should still follow the normal flow to finish and destroy.
@@ -875,9 +875,9 @@
 
         assertEquals(2, mTask.getChildCount());
 
-        mStack.finishDisabledPackageActivitiesLocked(activity.packageName,
-                null  /* filterByClasses */, true /* doit */, true /* evenPersistent */,
-                UserHandle.USER_ALL);
+        mRootActivityContainer.mFinishDisabledPackageActivitiesHelper.process(
+                activity.packageName, null  /* filterByClasses */, true /* doit */,
+                true /* evenPersistent */, UserHandle.USER_ALL);
 
         // Although the overlay activity is in another package, the non-overlay activities are
         // removed from the task. Since the overlay activity should be removed as well, the task
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 4165052..d78e3af 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -167,16 +167,8 @@
 
     @Test
     public void testSuspendedPackage() {
-        mAInfo.applicationInfo.flags = FLAG_SUSPENDED;
         final String suspendingPackage = "com.test.suspending.package";
-        final SuspendDialogInfo dialogInfo = new SuspendDialogInfo.Builder()
-                .setMessage("Test Message")
-                .setIcon(0x11110001)
-                .build();
-        when(mPackageManagerInternal.getSuspendingPackage(TEST_PACKAGE_NAME, TEST_USER_ID))
-                .thenReturn(suspendingPackage);
-        when(mPackageManagerInternal.getSuspendedDialogInfo(TEST_PACKAGE_NAME, suspendingPackage,
-                TEST_USER_ID)).thenReturn(dialogInfo);
+        final SuspendDialogInfo dialogInfo = suspendPackage(suspendingPackage);
         // THEN calling intercept returns true
         assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
 
@@ -190,6 +182,19 @@
         assertEquals(TEST_USER_ID, mInterceptor.mIntent.getIntExtra(Intent.EXTRA_USER_ID, -1000));
     }
 
+    private SuspendDialogInfo suspendPackage(String suspendingPackage) {
+        mAInfo.applicationInfo.flags = FLAG_SUSPENDED;
+        final SuspendDialogInfo dialogInfo = new SuspendDialogInfo.Builder()
+                .setMessage("Test Message")
+                .setIcon(0x11110001)
+                .build();
+        when(mPackageManagerInternal.getSuspendingPackage(TEST_PACKAGE_NAME, TEST_USER_ID))
+                .thenReturn(suspendingPackage);
+        when(mPackageManagerInternal.getSuspendedDialogInfo(TEST_PACKAGE_NAME, suspendingPackage,
+                TEST_USER_ID)).thenReturn(dialogInfo);
+        return dialogInfo;
+    }
+
     @Test
     public void testInterceptQuietProfile() {
         // GIVEN that the user the activity is starting as is currently in quiet mode
@@ -204,6 +209,20 @@
     }
 
     @Test
+    public void testInterceptQuietProfileWhenPackageSuspended() {
+        suspendPackage("com.test.suspending.package");
+        // GIVEN that the user the activity is starting as is currently in quiet mode
+        when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
+
+        // THEN calling intercept returns true
+        assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
+
+        // THEN the returned intent is the quiet mode intent
+        assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
+                .filterEquals(mInterceptor.mIntent));
+    }
+
+    @Test
     public void testWorkChallenge() {
         // GIVEN that the user the activity is starting as is currently locked
         when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index e2bdf87..4257249 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -73,6 +73,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.function.Consumer;
 
 /**
  * Tests for the {@link RootActivityContainer} class.
@@ -149,9 +150,7 @@
         final Task task = stack.getAllTasks().get(0);
         final ArrayList<ActivityRecord> stackActivities = new ArrayList<>();
 
-        for (int i = 0; i < task.getChildCount(); i++) {
-            stackActivities.add(task.getChildAt(i));
-        }
+        task.forAllActivities((Consumer<ActivityRecord>) stackActivities::add, false);
 
         assertEquals("Expecting " + Arrays.deepToString(activities) + " got " + stackActivities,
                 stackActivities.size(), activities != null ? activities.length : 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index c8f81f4..d756f9a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -471,8 +471,9 @@
         // Add an extra activity on top of the root one
         new ActivityBuilder(mService).setTask(task).build();
 
-        assertEquals("The root activity in the task must be reported.",
-                0, task.findRootIndex(false /* effectiveRoot*/));
+        assertEquals("The root activity in the task must be reported.", task.getChildAt(0),
+                task.getRootActivity(
+                        true /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
     }
 
     /**
@@ -483,14 +484,15 @@
     public void testFindRootIndex_finishing() {
         final Task task = getTestTask();
         // Add extra two activities and mark the two on the bottom as finishing.
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.finishing = true;
         final ActivityRecord activity1 = new ActivityBuilder(mService).setTask(task).build();
         activity1.finishing = true;
         new ActivityBuilder(mService).setTask(task).build();
 
         assertEquals("The first non-finishing activity in the task must be reported.",
-                2, task.findRootIndex(false /* effectiveRoot*/));
+                task.getChildAt(2), task.getRootActivity(
+                        true /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
     }
 
     /**
@@ -504,7 +506,8 @@
         new ActivityBuilder(mService).setTask(task).build();
 
         assertEquals("The root activity in the task must be reported.",
-                0, task.findRootIndex(true /* effectiveRoot*/));
+                task.getChildAt(0), task.getRootActivity(
+                        false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
     }
 
     /**
@@ -516,14 +519,15 @@
         final Task task = getTestTask();
         // Add extra two activities. Mark the one on the bottom with "relinquishTaskIdentity" and
         // one above as finishing.
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
         final ActivityRecord activity1 = new ActivityBuilder(mService).setTask(task).build();
         activity1.finishing = true;
         new ActivityBuilder(mService).setTask(task).build();
 
         assertEquals("The first non-finishing activity and non-relinquishing task identity "
-                        + "must be reported.", 2, task.findRootIndex(true /* effectiveRoot*/));
+                + "must be reported.", task.getChildAt(2), task.getRootActivity(
+                        false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
     }
 
     /**
@@ -534,10 +538,11 @@
     public void testFindRootIndex_effectiveRoot_relinquishingAndSingleActivity() {
         final Task task = getTestTask();
         // Set relinquishTaskIdentity for the only activity in the task
-        task.getChildAt(0).info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
+        task.getBottomMostActivity().info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
 
         assertEquals("The root activity in the task must be reported.",
-                0, task.findRootIndex(true /* effectiveRoot*/));
+                task.getChildAt(0), task.getRootActivity(
+                        false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
     }
 
     /**
@@ -548,13 +553,14 @@
     public void testFindRootIndex_effectiveRoot_relinquishingMultipleActivities() {
         final Task task = getTestTask();
         // Set relinquishTaskIdentity for all activities in the task
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
         final ActivityRecord activity1 = new ActivityBuilder(mService).setTask(task).build();
         activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
 
         assertEquals("The topmost activity in the task must be reported.",
-                task.getChildCount() - 1, task.findRootIndex(true /* effectiveRoot*/));
+                task.getChildAt(task.getChildCount() - 1), task.getRootActivity(
+                        false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
     }
 
     /** Test that bottom-most activity is reported in {@link Task#getRootActivity()}. */
@@ -565,7 +571,7 @@
         new ActivityBuilder(mService).setTask(task).build();
 
         assertEquals("The root activity in the task must be reported.",
-                task.getChildAt(0), task.getRootActivity());
+                task.getBottomMostActivity(), task.getRootActivity());
     }
 
     /**
@@ -577,7 +583,7 @@
         // Add an extra activity on top of the root one
         new ActivityBuilder(mService).setTask(task).build();
         // Mark the root as finishing
-        task.getChildAt(0).finishing = true;
+        task.getBottomMostActivity().finishing = true;
 
         assertEquals("The first non-finishing activity in the task must be reported.",
                 task.getChildAt(1), task.getRootActivity());
@@ -590,13 +596,13 @@
     public void testGetRootActivity_relinquishTaskIdentity() {
         final Task task = getTestTask();
         // Mark the bottom-most activity with FLAG_RELINQUISH_TASK_IDENTITY.
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
         // Add an extra activity on top of the root one.
         new ActivityBuilder(mService).setTask(task).build();
 
         assertEquals("The root activity in the task must be reported.",
-                task.getChildAt(0), task.getRootActivity());
+                task.getBottomMostActivity(), task.getRootActivity());
     }
 
     /**
@@ -607,7 +613,7 @@
     public void testGetRootActivity_allFinishing() {
         final Task task = getTestTask();
         // Mark the bottom-most activity as finishing.
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.finishing = true;
         // Add an extra activity on top of the root one and mark it as finishing
         final ActivityRecord activity1 = new ActivityBuilder(mService).setTask(task).build();
@@ -623,7 +629,7 @@
     public void testIsRootActivity() {
         final Task task = getTestTask();
         // Mark the bottom-most activity as finishing.
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.finishing = true;
         // Add an extra activity on top of the root one.
         final ActivityRecord activity1 = new ActivityBuilder(mService).setTask(task).build();
@@ -640,7 +646,7 @@
     public void testIsRootActivity_allFinishing() {
         final Task task = getTestTask();
         // Mark the bottom-most activity as finishing.
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.finishing = true;
         // Add an extra activity on top of the root one and mark it as finishing
         final ActivityRecord activity1 = new ActivityBuilder(mService).setTask(task).build();
@@ -657,10 +663,10 @@
     @Test
     public void testGetTaskForActivity() {
         final Task task0 = getTestTask();
-        final ActivityRecord activity0 = task0.getChildAt(0);
+        final ActivityRecord activity0 = task0.getBottomMostActivity();
 
         final Task task1 = getTestTask();
-        final ActivityRecord activity1 = task1.getChildAt(0);
+        final ActivityRecord activity1 = task1.getBottomMostActivity();
 
         assertEquals(task0.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity0.appToken, false /* onlyRoot */));
@@ -676,7 +682,7 @@
     public void testGetTaskForActivity_onlyRoot_finishing() {
         final Task task = getTestTask();
         // Make the current root activity finishing
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.finishing = true;
         // Add an extra activity on top - this will be the new root
         final ActivityRecord activity1 = new ActivityBuilder(mService).setTask(task).build();
@@ -699,7 +705,7 @@
     public void testGetTaskForActivity_onlyRoot_relinquishTaskIdentity() {
         final Task task = getTestTask();
         // Make the current root activity relinquish task identity
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
         // Add an extra activity on top - this will be the new root
         final ActivityRecord activity1 = new ActivityBuilder(mService).setTask(task).build();
@@ -722,7 +728,7 @@
     public void testGetTaskForActivity_notOnlyRoot() {
         final Task task = getTestTask();
         // Mark the bottom-most activity as finishing.
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.finishing = true;
 
         // Add an extra activity on top of the root one and make it relinquish task identity
@@ -747,7 +753,7 @@
     public void testUpdateEffectiveIntent() {
         // Test simple case with a single activity.
         final Task task = getTestTask();
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
 
         spyOn(task);
         task.updateEffectiveIntent();
@@ -762,7 +768,7 @@
     public void testUpdateEffectiveIntent_rootFinishing() {
         // Test simple case with a single activity.
         final Task task = getTestTask();
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         // Mark the bottom-most activity as finishing.
         activity0.finishing = true;
         // Add an extra activity on top of the root one
@@ -782,7 +788,7 @@
     public void testUpdateEffectiveIntent_allFinishing() {
         // Test simple case with a single activity.
         final Task task = getTestTask();
-        final ActivityRecord activity0 = task.getChildAt(0);
+        final ActivityRecord activity0 = task.getBottomMostActivity();
         // Mark the bottom-most activity as finishing.
         activity0.finishing = true;
         // Add an extra activity on top of the root one and make it relinquish task identity
@@ -818,7 +824,7 @@
                 task.getResolvedOverrideConfiguration().windowConfiguration.getAppBounds());
     }
 
-    private byte[] serializeToBytes(Task r) throws IOException, XmlPullParserException {
+    private byte[] serializeToBytes(Task r) throws Exception {
         try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
             final XmlSerializer serializer = Xml.newSerializer();
             serializer.setOutput(os, "UTF-8");
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index a0aa60b..0320f75 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -80,6 +80,7 @@
         public static final int EUTRAN = 3;
         public static final int CDMA2000 = 4;
         public static final int IWLAN = 5;
+        public static final int NGRAN = 6;
 
         /** @hide */
         private AccessNetworkType() {}
@@ -93,6 +94,7 @@
                 case EUTRAN: return "EUTRAN";
                 case CDMA2000: return "CDMA2000";
                 case IWLAN: return "IWLAN";
+                case NGRAN: return "NGRAN";
                 default: return Integer.toString(type);
             }
         }
@@ -247,6 +249,54 @@
         private CdmaBands() {};
     }
 
+    /**
+     * Frequency bands for NGRAN
+     */
+    public static final class NgranBands {
+        /** FR1 bands */
+        public static final int BAND_1 = 1;
+        public static final int BAND_2 = 2;
+        public static final int BAND_3 = 3;
+        public static final int BAND_5 = 5;
+        public static final int BAND_7 = 7;
+        public static final int BAND_8 = 8;
+        public static final int BAND_12 = 12;
+        public static final int BAND_20 = 20;
+        public static final int BAND_25 = 25;
+        public static final int BAND_28 = 28;
+        public static final int BAND_34 = 34;
+        public static final int BAND_38 = 38;
+        public static final int BAND_39 = 39;
+        public static final int BAND_40 = 40;
+        public static final int BAND_41 = 41;
+        public static final int BAND_50 = 50;
+        public static final int BAND_51 = 51;
+        public static final int BAND_66 = 66;
+        public static final int BAND_70 = 70;
+        public static final int BAND_71 = 71;
+        public static final int BAND_74 = 74;
+        public static final int BAND_75 = 75;
+        public static final int BAND_76 = 76;
+        public static final int BAND_77 = 77;
+        public static final int BAND_78 = 78;
+        public static final int BAND_79 = 79;
+        public static final int BAND_80 = 80;
+        public static final int BAND_81 = 81;
+        public static final int BAND_82 = 82;
+        public static final int BAND_83 = 83;
+        public static final int BAND_84 = 84;
+        public static final int BAND_86 = 86;
+
+        /** FR2 bands */
+        public static final int BAND_257 = 257;
+        public static final int BAND_258 = 258;
+        public static final int BAND_260 = 260;
+        public static final int BAND_261 = 261;
+
+        /** @hide */
+        private NgranBands() {};
+    }
+
     /** @hide */
     private AccessNetworkConstants() {};
 }
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
index e65b048ec..cb8fdf0 100644
--- a/telephony/java/android/telephony/CellSignalStrength.java
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -46,11 +46,6 @@
     protected static final int NUM_SIGNAL_STRENGTH_THRESHOLDS = NUM_SIGNAL_STRENGTH_BINS - 1;
 
     /** @hide */
-    public static final String[] SIGNAL_STRENGTH_NAMES = {
-        "none", "poor", "moderate", "good", "great"
-    };
-
-    /** @hide */
     protected CellSignalStrength() {
     }
 
@@ -157,4 +152,12 @@
         if ((value < rangeMin || value > rangeMax) && value != special) return CellInfo.UNAVAILABLE;
         return value;
     }
+
+    /**
+     * Returns the number of signal strength levels.
+     * @return Number of signal strength levels, enforced to be 5
+     */
+    public static final int getNumSignalStrengthLevels() {
+        return NUM_SIGNAL_STRENGTH_BINS;
+    }
 }
diff --git a/telephony/java/android/telephony/RadioAccessSpecifier.java b/telephony/java/android/telephony/RadioAccessSpecifier.java
index 690e44a..a403095 100644
--- a/telephony/java/android/telephony/RadioAccessSpecifier.java
+++ b/telephony/java/android/telephony/RadioAccessSpecifier.java
@@ -97,8 +97,9 @@
      * Returns the frequency bands that need to be scanned.
      *
      * The returned value is defined in either of {@link AccessNetworkConstants.GeranBand},
-     * {@link AccessNetworkConstants.UtranBand} and {@link AccessNetworkConstants.EutranBand}, and
-     * it depends on the returned value of {@link #getRadioAccessNetwork()}.
+     * {@link AccessNetworkConstants.UtranBand}, {@link AccessNetworkConstants.EutranBand},
+     * and {@link AccessNetworkConstants.NgranBands}, and it depends on
+     * the returned value of {@link #getRadioAccessNetwork()}.
      */
     public int[] getBands() {
         return mBands == null ? null : mBands.clone();
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 480c9d9..9aafc1b 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -60,12 +60,6 @@
     @UnsupportedAppUsage
     public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
 
-    /** SIGNAL_STRENGTH_NAMES is currently used by BatteryStats, but to-be-removed soon. */
-    /** @hide */
-    public static final String[] SIGNAL_STRENGTH_NAMES = {
-        "none", "poor", "moderate", "good", "great"
-    };
-
     /**
      * Indicates the invalid measures of signal strength.
      *
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index c7f9529..045d1eb 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -533,7 +533,8 @@
                 + ", priority=" + mPriority
                 + (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "")
                 + (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "")
-                + ", maximumWaitingTime = " + mMaximumWaitTimeSec
+                + ", maximumWaitingTime=" + mMaximumWaitTimeSec
+                + ", received time=" + mReceivedTimeMillis
                 + ", slotIndex = " + mSlotIndex
                 + ", geo=" + (mGeometries != null
                 ? CbGeoUtils.encodeGeometriesToString(mGeometries) : "null")
diff --git a/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
new file mode 100644
index 0000000..a28d65c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/util/TelephonyUtils.java
@@ -0,0 +1,74 @@
+/*
+ * 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.internal.telephony.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.ComponentInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+
+import java.io.PrintWriter;
+
+/**
+ * This class provides various util functions
+ */
+public final class TelephonyUtils {
+    public static boolean IS_USER = "user".equals(android.os.Build.TYPE);
+    public static boolean IS_DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
+
+    /**
+     * Verify that caller holds {@link android.Manifest.permission#DUMP}.
+     *
+     * @return true if access should be granted.
+     */
+    public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
+        if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump " + tag + " from from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+                    + " due to missing android.permission.DUMP permission");
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /** Returns an empty string if the input is {@code null}. */
+    public static String emptyIfNull(@Nullable String str) {
+        return str == null ? "" : str;
+    }
+
+    /** Throws a {@link RuntimeException} that wrapps the {@link RemoteException}. */
+    public static RuntimeException rethrowAsRuntimeException(RemoteException remoteException) {
+        throw new RuntimeException(remoteException);
+    }
+
+    /**
+     * Returns a {@link ComponentInfo} from the {@link ResolveInfo},
+     * or throws an {@link IllegalStateException} if not available.
+     */
+    public static ComponentInfo getComponentInfo(@NonNull ResolveInfo resolveInfo) {
+        if (resolveInfo.activityInfo != null) return resolveInfo.activityInfo;
+        if (resolveInfo.serviceInfo != null) return resolveInfo.serviceInfo;
+        if (resolveInfo.providerInfo != null) return resolveInfo.providerInfo;
+        throw new IllegalStateException("Missing ComponentInfo!");
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
index 0787d82..51bae3a 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
@@ -29,9 +29,13 @@
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
+import android.graphics.RuntimeShader;
 import android.os.Bundle;
 import android.view.View;
 
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
 @SuppressWarnings({"UnusedDeclaration"})
 public class ColorFiltersMutateActivity extends Activity {
     @Override
@@ -47,12 +51,21 @@
         private final Paint mColorMatrixPaint;
         private final Paint mLightingPaint;
         private final Paint mBlendPaint;
+        private final Paint mShaderPaint;
 
         private float mSaturation = 0.0f;
         private int mLightAdd = 0;
         private int mLightMul = 0;
         private int mPorterDuffColor = 0;
 
+        static final String sSkSL =
+                "uniform float param1;\n"
+                + "void main(float x, float y, inout half4 color) {\n"
+                + "color = half4(color.r, half(param1), color.b, 1.0);\n"
+                + "}\n";
+
+        private byte[] mUniforms = new byte[4];
+
         BitmapsView(Context c) {
             super(c);
 
@@ -70,6 +83,10 @@
             mBlendPaint = new Paint();
             mBlendPaint.setColorFilter(new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_OVER));
 
+            mShaderPaint = new Paint();
+            mShaderPaint.setShader(new RuntimeShader(sSkSL, mUniforms, true));
+            setShaderParam1(0.0f);
+
             ObjectAnimator sat = ObjectAnimator.ofFloat(this, "saturation", 1.0f);
             sat.setDuration(1000);
             sat.setRepeatCount(ObjectAnimator.INFINITE);
@@ -96,6 +113,12 @@
             color.setRepeatCount(ObjectAnimator.INFINITE);
             color.setRepeatMode(ObjectAnimator.REVERSE);
             color.start();
+
+            ObjectAnimator shaderUniform = ObjectAnimator.ofFloat(this, "shaderParam1", 1.0f);
+            shaderUniform.setDuration(1000);
+            shaderUniform.setRepeatCount(ObjectAnimator.INFINITE);
+            shaderUniform.setRepeatMode(ObjectAnimator.REVERSE);
+            shaderUniform.start();
         }
 
         public int getPorterDuffColor() {
@@ -148,6 +171,23 @@
             return mSaturation;
         }
 
+        public void setShaderParam1(float value) {
+            RuntimeShader shader = (RuntimeShader) mShaderPaint.getShader();
+            ByteBuffer buffer = ByteBuffer.wrap(mUniforms);
+            buffer.order(ByteOrder.LITTLE_ENDIAN);
+            buffer.putFloat(value);
+            shader.updateUniforms(mUniforms);
+            invalidate();
+        }
+
+        // If either valueFrom or valueTo is null, then a getter function will also be derived
+        // and called by the animator class.
+        public float getShaderParam1() {
+            ByteBuffer buffer = ByteBuffer.wrap(mUniforms);
+            buffer.order(ByteOrder.LITTLE_ENDIAN);
+            return buffer.getFloat();
+        }
+
         @Override
         protected void onDraw(Canvas canvas) {
             super.onDraw(canvas);
@@ -163,6 +203,10 @@
 
             canvas.translate(0.0f, 50.0f + mBitmap1.getHeight());
             canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mBlendPaint);
+
+            canvas.translate(0.0f, 50.0f + mBitmap1.getHeight());
+            canvas.drawRect(0.0f, 0.0f, mBitmap1.getWidth(), mBitmap1.getHeight(),
+                    mShaderPaint);
             canvas.restore();
 
             canvas.save();
@@ -174,6 +218,10 @@
 
             canvas.translate(0.0f, 50.0f + mBitmap2.getHeight());
             canvas.drawBitmap(mBitmap2, 0.0f, 0.0f, mBlendPaint);
+
+            canvas.translate(0.0f, 50.0f + mBitmap2.getHeight());
+            canvas.drawRoundRect(0.0f, 0.0f, mBitmap2.getWidth(), mBitmap2.getHeight(), 20, 20,
+                    mShaderPaint);
             canvas.restore();
         }
     }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index c4e353b..fd3ed7d 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -5644,6 +5644,7 @@
         mCm.unregisterNetworkCallback(defaultCallback);
     }
 
+    @Ignore // 40%+ flakiness : figure out why and re-enable.
     @Test
     public final void testBatteryStatsNetworkType() throws Exception {
         final LinkProperties cellLp = new LinkProperties();
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 4a89c66..032f66a 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -142,6 +142,8 @@
 
     boolean startSoftAp(in WifiConfiguration wifiConfig);
 
+    boolean startTetheredHotspot(in SoftApConfiguration softApConfig);
+
     boolean stopSoftAp();
 
     int startLocalOnlyHotspot(in ILocalOnlyHotspotCallback callback, String packageName,
@@ -159,8 +161,14 @@
     @UnsupportedAppUsage
     WifiConfiguration getWifiApConfiguration();
 
+    SoftApConfiguration getSoftApConfiguration();
+
     boolean setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
 
+    boolean setSoftApConfiguration(in SoftApConfiguration softApConfig, String packageName);
+
+    void notifyUserOfApBandConversion(String packageName);
+
     void enableTdls(String remoteIPAddress, boolean enable);
 
     void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable);
@@ -184,6 +192,10 @@
 
     void restoreBackupData(in byte[] data);
 
+    byte[] retrieveSoftApBackupData();
+
+    void restoreSoftApBackupData(in byte[] data);
+
     void restoreSupplicantBackupData(in byte[] supplicantData, in byte[] ipConfigData);
 
     void startSubscriptionProvisioning(in OsuProvider provider, in IProvisioningCallback callback);
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index 4cc8653..8030bd6 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -16,28 +16,34 @@
 
 package android.net.wifi;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.net.MacAddress;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.nio.charset.CharsetEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
- * WiFi configuration for a soft access point (a.k.a. Soft AP, SAP, Hotspot).
+ * Configuration for a soft access point (a.k.a. Soft AP, SAP, Hotspot).
  *
  * This is input for the framework provided by a client app, i.e. it exposes knobs to instruct the
- * framework how it should open a hotspot.  It is not meant to describe the network as it will be
- * seen by clients; this role is currently served by {@link WifiConfiguration} (see
- * {@link WifiManager.LocalOnlyHotspotReservation#getWifiConfiguration()}).
+ * framework how it should configure a hotspot.
  *
- * System apps can use this to configure a local-only hotspot using
+ * System apps can use this to configure a tethered hotspot using
+ * {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} and
+ * {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)}
+ * or local-only hotspot using
  * {@link WifiManager#startLocalOnlyHotspot(SoftApConfiguration, Executor,
  * WifiManager.LocalOnlyHotspotCallback)}.
  *
@@ -48,25 +54,106 @@
  */
 @SystemApi
 public final class SoftApConfiguration implements Parcelable {
+
+    /**
+     * 2GHz band.
+     * @hide
+     */
+    @SystemApi
+    public static final int BAND_2GHZ = 0;
+
+    /**
+     * 5GHz band.
+     * @hide
+     */
+    @SystemApi
+    public static final int BAND_5GHZ = 1;
+
+    /**
+     * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
+     * operating country code and current radio conditions.
+     * @hide
+     */
+    @SystemApi
+    public static final int BAND_ANY = -1;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "BAND_TYPE_" }, value = {
+            BAND_2GHZ,
+            BAND_5GHZ,
+            BAND_ANY,
+    })
+    public @interface BandType {}
+
     /**
      * SSID for the AP, or null for a framework-determined SSID.
      */
     private final @Nullable String mSsid;
+
     /**
      * BSSID for the AP, or null to use a framework-determined BSSID.
      */
     private final @Nullable MacAddress mBssid;
+
     /**
      * Pre-shared key for WPA2-PSK encryption (non-null enables WPA2-PSK).
      */
     private final @Nullable String mWpa2Passphrase;
 
+    /**
+     * This is a network that does not broadcast its SSID, so an
+     * SSID-specific probe request must be used for scans.
+     */
+    private final boolean mHiddenSsid;
+
+    /**
+     * The operating band of the AP.
+     * One of the band types from {@link @BandType}.
+     */
+    private final @BandType int mBand;
+
+    /**
+     * The operating channel of the AP.
+     */
+    private final int mChannel;
+
+    /**
+     * The operating security type of the AP.
+     * One of the security types from {@link @SecurityType}
+     */
+    private final @SecurityType int mSecurityType;
+
+    /**
+     * Security types we support.
+     */
+    /** @hide */
+    @SystemApi
+    public static final int SECURITY_TYPE_OPEN = 0;
+
+    /** @hide */
+    @SystemApi
+    public static final int SECURITY_TYPE_WPA2_PSK = 1;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "SECURITY_TYPE" }, value = {
+        SECURITY_TYPE_OPEN,
+        SECURITY_TYPE_WPA2_PSK,
+    })
+    public @interface SecurityType {}
+
     /** Private constructor for Builder and Parcelable implementation. */
-    private SoftApConfiguration(
-            @Nullable String ssid, @Nullable MacAddress bssid, String wpa2Passphrase) {
+    private SoftApConfiguration(@Nullable String ssid, @Nullable MacAddress bssid,
+            @Nullable String wpa2Passphrase, boolean hiddenSsid, @BandType int band, int channel,
+            @SecurityType int securityType) {
         mSsid = ssid;
         mBssid = bssid;
         mWpa2Passphrase = wpa2Passphrase;
+        mHiddenSsid = hiddenSsid;
+        mBand = band;
+        mChannel = channel;
+        mSecurityType = securityType;
     }
 
     @Override
@@ -80,12 +167,31 @@
         SoftApConfiguration other = (SoftApConfiguration) otherObj;
         return Objects.equals(mSsid, other.mSsid)
                 && Objects.equals(mBssid, other.mBssid)
-                && Objects.equals(mWpa2Passphrase, other.mWpa2Passphrase);
+                && Objects.equals(mWpa2Passphrase, other.mWpa2Passphrase)
+                && mHiddenSsid == other.mHiddenSsid
+                && mBand == other.mBand
+                && mChannel == other.mChannel
+                && mSecurityType == other.mSecurityType;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mSsid, mBssid, mWpa2Passphrase);
+        return Objects.hash(mSsid, mBssid, mWpa2Passphrase, mHiddenSsid,
+                mBand, mChannel, mSecurityType);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sbuf = new StringBuilder();
+        sbuf.append("ssid=").append(mSsid);
+        if (mBssid != null) sbuf.append(" \n bssid=").append(mBssid.toString());
+        sbuf.append(" \n Wpa2Passphrase =").append(
+                TextUtils.isEmpty(mWpa2Passphrase) ? "<empty>" : "<non-empty>");
+        sbuf.append(" \n HiddenSsid =").append(mHiddenSsid);
+        sbuf.append(" \n Band =").append(mBand);
+        sbuf.append(" \n Channel =").append(mChannel);
+        sbuf.append(" \n SecurityType=").append(getSecurityType());
+        return sbuf.toString();
     }
 
     @Override
@@ -93,6 +199,10 @@
         dest.writeString(mSsid);
         dest.writeParcelable(mBssid, flags);
         dest.writeString(mWpa2Passphrase);
+        dest.writeBoolean(mHiddenSsid);
+        dest.writeInt(mBand);
+        dest.writeInt(mChannel);
+        dest.writeInt(mSecurityType);
     }
 
     @Override
@@ -107,7 +217,7 @@
             return new SoftApConfiguration(
                     in.readString(),
                     in.readParcelable(MacAddress.class.getClassLoader()),
-                    in.readString());
+                    in.readString(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt());
         }
 
         @Override
@@ -116,22 +226,68 @@
         }
     };
 
+    /**
+     * Return String set to be the SSID for the AP.
+     * {@link #setSsid(String)}.
+     */
     @Nullable
     public String getSsid() {
         return mSsid;
     }
 
+    /**
+     * Returns MAC address set to be BSSID for the AP.
+     * {@link #setBssid(MacAddress)}.
+     */
     @Nullable
     public MacAddress getBssid() {
         return mBssid;
     }
 
+    /**
+     * Returns String set to be passphrase for the WPA2-PSK AP.
+     * {@link #setWpa2Passphrase(String)}.
+     */
     @Nullable
     public String getWpa2Passphrase() {
         return mWpa2Passphrase;
     }
 
     /**
+     * Returns Boolean set to be indicate hidden (true: doesn't broadcast its SSID) or
+     * not (false: broadcasts its SSID) for the AP.
+     * {@link #setHiddenSsid(boolean)}.
+     */
+    public boolean isHiddenSsid() {
+        return mHiddenSsid;
+    }
+
+    /**
+     * Returns {@link BandType} set to be the band for the AP.
+     * {@link #setBand(@BandType int)}.
+     */
+    public @BandType int getBand() {
+        return mBand;
+    }
+
+    /**
+     * Returns Integer set to be the channel for the AP.
+     * {@link #setChannel(int)}.
+     */
+    public int getChannel() {
+        return mChannel;
+    }
+
+    /**
+     * Get security type params which depends on which security passphrase to set.
+     *
+     * @return One of the security types from {@link SecurityType}.
+     */
+    public @SecurityType int getSecurityType() {
+        return mSecurityType;
+    }
+
+    /**
      * Builds a {@link SoftApConfiguration}, which allows an app to configure various aspects of a
      * Soft AP.
      *
@@ -142,6 +298,21 @@
         private String mSsid;
         private MacAddress mBssid;
         private String mWpa2Passphrase;
+        private boolean mHiddenSsid;
+        private int mBand;
+        private int mChannel;
+
+        private int setSecurityType() {
+            int securityType = SECURITY_TYPE_OPEN;
+            if (!TextUtils.isEmpty(mWpa2Passphrase)) { // WPA2-PSK network.
+                securityType = SECURITY_TYPE_WPA2_PSK;
+            }
+            return securityType;
+        }
+
+        private void clearAllPassphrase() {
+            mWpa2Passphrase = null;
+        }
 
         /**
          * Constructs a Builder with default values (see {@link Builder}).
@@ -150,6 +321,9 @@
             mSsid = null;
             mBssid = null;
             mWpa2Passphrase = null;
+            mHiddenSsid = false;
+            mBand = BAND_2GHZ;
+            mChannel = 0;
         }
 
         /**
@@ -161,6 +335,9 @@
             mSsid = other.mSsid;
             mBssid = other.mBssid;
             mWpa2Passphrase = other.mWpa2Passphrase;
+            mHiddenSsid = other.mHiddenSsid;
+            mBand = other.mBand;
+            mChannel = other.mChannel;
         }
 
         /**
@@ -170,11 +347,16 @@
          */
         @NonNull
         public SoftApConfiguration build() {
-            return new SoftApConfiguration(mSsid, mBssid, mWpa2Passphrase);
+            return new SoftApConfiguration(mSsid, mBssid, mWpa2Passphrase,
+                mHiddenSsid, mBand, mChannel, setSecurityType());
         }
 
         /**
          * Specifies an SSID for the AP.
+         * <p>
+         * Null SSID only support when configure a local-only hotspot.
+         * <p>
+         * <li>If not set, defaults to null.</li>
          *
          * @param ssid SSID of valid Unicode characters, or null to have the SSID automatically
          *             chosen by the framework.
@@ -193,7 +375,10 @@
 
         /**
          * Specifies a BSSID for the AP.
-         *
+         * <p>
+         * Only supported when configuring a local-only hotspot.
+         * <p>
+         * <li>If not set, defaults to null.</li>
          * @param bssid BSSID, or null to have the BSSID chosen by the framework. The caller is
          *              responsible for avoiding collisions.
          * @return Builder for chaining.
@@ -211,8 +396,9 @@
         }
 
         /**
-         * Specifies that this AP should use WPA2-PSK with the given passphrase.  When set to null
-         * and no other encryption method is configured, an open network is created.
+         * Specifies that this AP should use WPA2-PSK with the given ASCII WPA2 passphrase.
+         * When set to null, an open network is created.
+         * <p>
          *
          * @param passphrase The passphrase to use, or null to unset a previously-set WPA2-PSK
          *                   configuration.
@@ -222,10 +408,72 @@
         @NonNull
         public Builder setWpa2Passphrase(@Nullable String passphrase) {
             if (passphrase != null) {
+                final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
+                if (!asciiEncoder.canEncode(passphrase)) {
+                    throw new IllegalArgumentException("passphrase not ASCII encodable");
+                }
                 Preconditions.checkStringNotEmpty(passphrase);
             }
+            clearAllPassphrase();
             mWpa2Passphrase = passphrase;
             return this;
         }
+
+        /**
+         * Specifies whether the AP is hidden (doesn't broadcast its SSID) or
+         * not (broadcasts its SSID).
+         * <p>
+         * <li>If not set, defaults to false (i.e not a hidden network).</li>
+         *
+         * @param hiddenSsid true for a hidden SSID, false otherwise.
+         * @return Builder for chaining.
+         */
+        @NonNull
+        public Builder setHiddenSsid(boolean hiddenSsid) {
+            mHiddenSsid = hiddenSsid;
+            return this;
+        }
+
+        /**
+         * Specifies the band for the AP.
+         * <p>
+         * <li>If not set, defaults to BAND_2GHZ {@link @BandType}.</li>
+         *
+         * @param band One of the band types from {@link @BandType}.
+         * @return Builder for chaining.
+         */
+        @NonNull
+        public Builder setBand(@BandType int band) {
+            switch (band) {
+                case BAND_2GHZ:
+                    break;
+                case BAND_5GHZ:
+                    break;
+                case BAND_ANY:
+                    break;
+                default:
+                    throw new IllegalArgumentException("Invalid band type");
+            }
+            mBand = band;
+            return this;
+        }
+
+        /**
+         * Specifies the channel for the AP.
+         *
+         * The channel which AP resides on. Valid channels are country dependent.
+         * Use the special channel value 0 to have the framework auto-select a valid channel
+         * from the band configured with {@link #setBand(@BandType int)}.
+         *
+         * <p>
+         * <li>If not set, defaults to 0.</li>
+         * @param channel operating channel of the AP.
+         * @return Builder for chaining.
+         */
+        @NonNull
+        public Builder setChannel(int channel) {
+            mChannel = channel;
+            return this;
+        }
     }
 }
diff --git a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
index 0f7fc2d..f0f31fa 100644
--- a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
+++ b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
@@ -16,10 +16,14 @@
 
 package android.net.wifi;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.util.Arrays;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * Record of energy and activity information from controller and
@@ -27,179 +31,197 @@
  * real-time.
  * @hide
  */
+@SystemApi
 public final class WifiActivityEnergyInfo implements Parcelable {
-    /**
-     * @hide
-     */
-    public long mTimestamp;
+    private long mTimeSinceBootMillis;
+    @StackState
+    private int mStackState;
+    private long mControllerTxDurationMillis;
+    private long mControllerRxDurationMillis;
+    private long mControllerScanDurationMillis;
+    private long mControllerIdleDurationMillis;
+    private long mControllerEnergyUsedMicroJoules;
 
-    /**
-     * @hide
-     */
-    public int mStackState;
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"STACK_STATE_"}, value = {
+            STACK_STATE_INVALID,
+            STACK_STATE_STATE_ACTIVE,
+            STACK_STATE_STATE_SCANNING,
+            STACK_STATE_STATE_IDLE})
+    public @interface StackState {}
 
-    /**
-     * @hide
-     */
-    public long mControllerTxTimeMs;
-
-    /**
-     * @hide
-     */
-    public long[] mControllerTxTimePerLevelMs;
-
-    /**
-     * @hide
-     */
-    public long mControllerRxTimeMs;
-
-    /**
-     * @hide
-     */
-    public long mControllerScanTimeMs;
-
-    /**
-     * @hide
-     */
-    public long mControllerIdleTimeMs;
-
-    /**
-     * @hide
-     */
-    public long mControllerEnergyUsed;
-
+    /** Invalid Wifi stack state. */
     public static final int STACK_STATE_INVALID = 0;
+    /** Wifi stack is active. */
     public static final int STACK_STATE_STATE_ACTIVE = 1;
+    /** Wifi stack is scanning. */
     public static final int STACK_STATE_STATE_SCANNING = 2;
+    /** Wifi stack is idle. */
     public static final int STACK_STATE_STATE_IDLE = 3;
 
-    public WifiActivityEnergyInfo(long timestamp, int stackState,
-                                  long txTime, long[] txTimePerLevel, long rxTime, long scanTime,
-                                  long idleTime, long energyUsed) {
-        mTimestamp = timestamp;
+    /**
+     * Constructor.
+     *
+     * @param timeSinceBootMillis the time since boot, in milliseconds.
+     * @param stackState The current state of the Wifi Stack. One of {@link #STACK_STATE_INVALID},
+     *                   {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
+     *                   or {@link #STACK_STATE_STATE_IDLE}.
+     * @param txDurationMillis Cumulative milliseconds of active transmission.
+     * @param rxDurationMillis Cumulative milliseconds of active receive.
+     * @param scanDurationMillis Cumulative milliseconds when radio is awake due to scan.
+     * @param idleDurationMillis Cumulative milliseconds when radio is awake but not transmitting or
+     *                       receiving.
+     * @param energyUsedMicroJoules Cumulative energy consumed by Wifi, in microjoules.
+     */
+    public WifiActivityEnergyInfo(
+            long timeSinceBootMillis,
+            @StackState int stackState,
+            long txDurationMillis,
+            long rxDurationMillis,
+            long scanDurationMillis,
+            long idleDurationMillis,
+            long energyUsedMicroJoules) {
+        mTimeSinceBootMillis = timeSinceBootMillis;
         mStackState = stackState;
-        mControllerTxTimeMs = txTime;
-        mControllerTxTimePerLevelMs = txTimePerLevel;
-        mControllerRxTimeMs = rxTime;
-        mControllerScanTimeMs = scanTime;
-        mControllerIdleTimeMs = idleTime;
-        mControllerEnergyUsed = energyUsed;
+        mControllerTxDurationMillis = txDurationMillis;
+        mControllerRxDurationMillis = rxDurationMillis;
+        mControllerScanDurationMillis = scanDurationMillis;
+        mControllerIdleDurationMillis = idleDurationMillis;
+        mControllerEnergyUsedMicroJoules = energyUsedMicroJoules;
     }
 
     @Override
     public String toString() {
         return "WifiActivityEnergyInfo{"
-            + " timestamp=" + mTimestamp
-            + " mStackState=" + mStackState
-            + " mControllerTxTimeMs=" + mControllerTxTimeMs
-            + " mControllerTxTimePerLevelMs=" + Arrays.toString(mControllerTxTimePerLevelMs)
-            + " mControllerRxTimeMs=" + mControllerRxTimeMs
-            + " mControllerScanTimeMs=" + mControllerScanTimeMs
-            + " mControllerIdleTimeMs=" + mControllerIdleTimeMs
-            + " mControllerEnergyUsed=" + mControllerEnergyUsed
-            + " }";
+                + " mTimeSinceBootMillis=" + mTimeSinceBootMillis
+                + " mStackState=" + mStackState
+                + " mControllerTxDurationMillis=" + mControllerTxDurationMillis
+                + " mControllerRxDurationMillis=" + mControllerRxDurationMillis
+                + " mControllerScanDurationMillis=" + mControllerScanDurationMillis
+                + " mControllerIdleDurationMillis=" + mControllerIdleDurationMillis
+                + " mControllerEnergyUsedMicroJoules=" + mControllerEnergyUsedMicroJoules
+                + " }";
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<WifiActivityEnergyInfo> CREATOR =
+    public static final @NonNull Parcelable.Creator<WifiActivityEnergyInfo> CREATOR =
             new Parcelable.Creator<WifiActivityEnergyInfo>() {
         public WifiActivityEnergyInfo createFromParcel(Parcel in) {
             long timestamp = in.readLong();
             int stackState = in.readInt();
             long txTime = in.readLong();
-            long[] txTimePerLevel = in.createLongArray();
             long rxTime = in.readLong();
             long scanTime = in.readLong();
             long idleTime = in.readLong();
             long energyUsed = in.readLong();
             return new WifiActivityEnergyInfo(timestamp, stackState,
-                    txTime, txTimePerLevel, rxTime, scanTime, idleTime, energyUsed);
+                    txTime, rxTime, scanTime, idleTime, energyUsed);
         }
         public WifiActivityEnergyInfo[] newArray(int size) {
             return new WifiActivityEnergyInfo[size];
         }
     };
 
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeLong(mTimestamp);
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeLong(mTimeSinceBootMillis);
         out.writeInt(mStackState);
-        out.writeLong(mControllerTxTimeMs);
-        out.writeLongArray(mControllerTxTimePerLevelMs);
-        out.writeLong(mControllerRxTimeMs);
-        out.writeLong(mControllerScanTimeMs);
-        out.writeLong(mControllerIdleTimeMs);
-        out.writeLong(mControllerEnergyUsed);
+        out.writeLong(mControllerTxDurationMillis);
+        out.writeLong(mControllerRxDurationMillis);
+        out.writeLong(mControllerScanDurationMillis);
+        out.writeLong(mControllerIdleDurationMillis);
+        out.writeLong(mControllerEnergyUsedMicroJoules);
     }
 
+    @Override
     public int describeContents() {
         return 0;
     }
 
+    /** Get the timestamp (milliseconds since boot) of record creation. */
+    public long getTimeSinceBootMillis() {
+        return mTimeSinceBootMillis;
+    }
+
+    /** Set the timestamp (milliseconds since boot) of record creation. */
+    public void setTimeSinceBootMillis(long timeSinceBootMillis) {
+        mTimeSinceBootMillis = timeSinceBootMillis;
+    }
+
     /**
-     * @return bt stack reported state
+     * Get the Wifi stack reported state. One of {@link #STACK_STATE_INVALID},
+     * {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
+     * {@link #STACK_STATE_STATE_IDLE}.
      */
+    @StackState
     public int getStackState() {
         return mStackState;
     }
 
     /**
-     * @return tx time in ms
+     * Set the Wifi stack reported state. One of {@link #STACK_STATE_INVALID},
+     * {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
+     * {@link #STACK_STATE_STATE_IDLE}.
      */
-    public long getControllerTxTimeMillis() {
-        return mControllerTxTimeMs;
+    public void setStackState(@StackState int stackState) {
+        mStackState = stackState;
     }
 
-    /**
-     * @return tx time at power level provided in ms
-     */
-    public long getControllerTxTimeMillisAtLevel(int level) {
-        if (level < mControllerTxTimePerLevelMs.length) {
-            return mControllerTxTimePerLevelMs[level];
-        }
-        return 0;
+    /** Get the Wifi transmission duration, in milliseconds. */
+    public long getControllerTxDurationMillis() {
+        return mControllerTxDurationMillis;
     }
 
-    /**
-     * @return rx time in ms
-     */
-    public long getControllerRxTimeMillis() {
-        return mControllerRxTimeMs;
+    /** Set the Wifi transmission duration, in milliseconds. */
+    public void setControllerTxDurationMillis(long controllerTxDurationMillis) {
+        mControllerTxDurationMillis = controllerTxDurationMillis;
     }
 
-    /**
-     * @return scan time in ms
-     */
-    public long getControllerScanTimeMillis() {
-        return mControllerScanTimeMs;
+    /** Get the Wifi receive duration, in milliseconds. */
+    public long getControllerRxDurationMillis() {
+        return mControllerRxDurationMillis;
     }
 
-    /**
-     * @return idle time in ms
-     */
-    public long getControllerIdleTimeMillis() {
-        return mControllerIdleTimeMs;
+    /** Set the Wifi receive duration, in milliseconds. */
+    public void setControllerRxDurationMillis(long controllerRxDurationMillis) {
+        mControllerRxDurationMillis = controllerRxDurationMillis;
     }
 
-    /**
-     * product of current(mA), voltage(V) and time(ms)
-     * @return energy used
-     */
-    public long getControllerEnergyUsed() {
-        return mControllerEnergyUsed;
-    }
-    /**
-     * @return timestamp(wall clock) of record creation
-     */
-    public long getTimeStamp() {
-        return mTimestamp;
+    /** Get the Wifi scan duration, in milliseconds. */
+    public long getControllerScanDurationMillis() {
+        return mControllerScanDurationMillis;
     }
 
-    /**
-     * @return if the record is valid
-     */
+    /** Set the Wifi scan duration, in milliseconds. */
+    public void setControllerScanDurationMillis(long controllerScanDurationMillis) {
+        mControllerScanDurationMillis = controllerScanDurationMillis;
+    }
+
+    /** Get the Wifi idle duration, in milliseconds. */
+    public long getControllerIdleDurationMillis() {
+        return mControllerIdleDurationMillis;
+    }
+
+    /** Set the Wifi idle duration, in milliseconds. */
+    public void setControllerIdleDurationMillis(long controllerIdleDurationMillis) {
+        mControllerIdleDurationMillis = controllerIdleDurationMillis;
+    }
+
+    /** Get the energy consumed by Wifi, in microjoules. */
+    public long getControllerEnergyUsedMicroJoules() {
+        return mControllerEnergyUsedMicroJoules;
+    }
+
+    /** Set the energy consumed by Wifi, in microjoules. */
+    public void setControllerEnergyUsedMicroJoules(long controllerEnergyUsedMicroJoules) {
+        mControllerEnergyUsedMicroJoules = controllerEnergyUsedMicroJoules;
+    }
+
+    /** Returns true if the record is valid, false otherwise. */
     public boolean isValid() {
-        return ((mControllerTxTimeMs >=0) &&
-                (mControllerRxTimeMs >=0) &&
-                (mControllerScanTimeMs >=0) &&
-                (mControllerIdleTimeMs >=0));
+        return mControllerTxDurationMillis >= 0
+                && mControllerRxDurationMillis >= 0
+                && mControllerScanDurationMillis >= 0
+                && mControllerIdleDurationMillis >= 0;
     }
-}
\ No newline at end of file
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index bf609d7..e2e6728 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2739,7 +2739,6 @@
      *
      * @hide
      */
-    @SystemApi
     @RequiresPermission(anyOf = {
             android.Manifest.permission.NETWORK_STACK,
             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
@@ -2753,6 +2752,31 @@
     }
 
     /**
+     * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration.
+     * Note that starting Soft AP mode may disable station mode operation if the device does not
+     * support concurrency.
+     * @param softApConfig A valid SoftApConfiguration specifying the configuration of the SAP,
+     *                     or null to use the persisted Soft AP configuration that was previously
+     *                     set using {@link #setSoftApConfiguration(softApConfiguration)}.
+     * @return {@code true} if the operation succeeded, {@code false} otherwise
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_STACK,
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+    })
+    public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig) {
+        try {
+            return mService.startTetheredHotspot(softApConfig);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+
+    /**
      * Stop SoftAp mode.
      * Note that stopping softap mode will restore the previous wifi mode.
      * @return {@code true} if the operation succeeds, {@code false} otherwise
@@ -3036,10 +3060,12 @@
      * Gets the Wi-Fi AP Configuration.
      * @return AP details in WifiConfiguration
      *
+     * @deprecated This API is deprecated. Use {@link #getSoftApConfiguration()} instead.
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
+    @Deprecated
     public WifiConfiguration getWifiApConfiguration() {
         try {
             return mService.getWifiApConfiguration();
@@ -3049,17 +3075,56 @@
     }
 
     /**
-     * Sets the Wi-Fi AP Configuration.  The AP configuration must either be open or
-     * WPA2 PSK networks.
+     * Gets the Wi-Fi AP Configuration.
+     * @return AP details in {@link SoftApConfiguration}
+     *
+     * @hide
+     */
+    @NonNull
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
+    public SoftApConfiguration getSoftApConfiguration() {
+        try {
+            return mService.getSoftApConfiguration();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets the Wi-Fi AP Configuration.
+     * @return {@code true} if the operation succeeded, {@code false} otherwise
+     *
+     * @deprecated This API is deprecated. Use {@link #setSoftApConfiguration(SoftApConfiguration)}
+     * instead.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
+    @Deprecated
+    public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
+        try {
+            return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets the Wi-Fi AP Configuration.
+     *
+     * @param softApConfig  A valid SoftApConfiguration specifying the configuration of the SAP.
+
      * @return {@code true} if the operation succeeded, {@code false} otherwise
      *
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
-    public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public boolean setSoftApConfiguration(@NonNull SoftApConfiguration softApConfig) {
         try {
-            return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
+            return mService.setSoftApConfiguration(
+                    softApConfig, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -4548,6 +4613,36 @@
     }
 
     /**
+     * Retrieve the soft ap config data to be backed to save current config data.
+     * @hide
+     */
+    @Nullable
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public byte[] retrieveSoftApBackupData() {
+        try {
+            return mService.retrieveSoftApBackupData();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Restore soft ap config from the backed up data.
+     * @hide
+     */
+    @Nullable
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void restoreSoftApBackupData(@NonNull byte[] data) {
+        try {
+            mService.restoreSoftApBackupData(data);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Restore state from the older version of back up data.
      * The old backup data was essentially a backup of wpa_supplicant.conf
      * and ipconfig.txt file.
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 77f7b9e..b293077 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -59,6 +59,60 @@
 public class WifiScanner {
 
     /** @hide */
+    public static final int WIFI_BAND_INDEX_24_GHZ = 0;
+    /** @hide */
+    public static final int WIFI_BAND_INDEX_5_GHZ = 1;
+    /** @hide */
+    public static final int WIFI_BAND_INDEX_5_GHZ_DFS_ONLY = 2;
+    /** @hide */
+    public static final int WIFI_BAND_COUNT = 3;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"WIFI_BAND_INDEX_"}, value = {
+            WIFI_BAND_INDEX_24_GHZ,
+            WIFI_BAND_INDEX_5_GHZ,
+            WIFI_BAND_INDEX_5_GHZ_DFS_ONLY})
+    public @interface WifiBandIndex {}
+
+    /** no band specified; use channel list instead */
+    public static final int WIFI_BAND_UNSPECIFIED = 0;
+    /** 2.4 GHz band */
+    public static final int WIFI_BAND_24_GHZ = 1 << WIFI_BAND_INDEX_24_GHZ;
+    /** 5 GHz band excluding DFS channels */
+    public static final int WIFI_BAND_5_GHZ = 1 << WIFI_BAND_INDEX_5_GHZ;
+    /** DFS channels from 5 GHz band only */
+    public static final int WIFI_BAND_5_GHZ_DFS_ONLY  = 1 << WIFI_BAND_INDEX_5_GHZ_DFS_ONLY;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"WIFI_BAND_"}, value = {
+            WIFI_BAND_UNSPECIFIED,
+            WIFI_BAND_24_GHZ,
+            WIFI_BAND_5_GHZ,
+            WIFI_BAND_5_GHZ_DFS_ONLY})
+    public @interface WifiBandBasic {}
+
+    /**
+     * Combination of bands
+     * Note that those are only the common band combinations,
+     * other combinations can be created by combining any of the basic bands above
+     */
+    /** Both 2.4 GHz band and 5 GHz band; no DFS channels */
+    public static final int WIFI_BAND_BOTH = WIFI_BAND_24_GHZ | WIFI_BAND_5_GHZ;
+    /**
+     * 2.4Ghz band + DFS channels from 5 GHz band only
+     * @hide
+     */
+    public static final int WIFI_BAND_24_GHZ_WITH_5GHZ_DFS  =
+            WIFI_BAND_24_GHZ | WIFI_BAND_5_GHZ_DFS_ONLY;
+    /** 5 GHz band including DFS channels */
+    public static final int WIFI_BAND_5_GHZ_WITH_DFS  = WIFI_BAND_5_GHZ | WIFI_BAND_5_GHZ_DFS_ONLY;
+    /** Both 2.4 GHz band and 5 GHz band; with DFS channels */
+    public static final int WIFI_BAND_BOTH_WITH_DFS =
+            WIFI_BAND_24_GHZ | WIFI_BAND_5_GHZ | WIFI_BAND_5_GHZ_DFS_ONLY;
+
+    /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"WIFI_BAND_"}, value = {
             WIFI_BAND_UNSPECIFIED,
@@ -71,25 +125,6 @@
             WIFI_BAND_BOTH_WITH_DFS})
     public @interface WifiBand {}
 
-    /** no band specified; use channel list instead */
-    public static final int WIFI_BAND_UNSPECIFIED = 0;
-    /** 2.4 GHz band */
-    public static final int WIFI_BAND_24_GHZ = 1;
-    /** 5 GHz band excluding DFS channels */
-    public static final int WIFI_BAND_5_GHZ = 2;
-    /** Both 2.4 GHz band and 5 GHz band; no DFS channels */
-    public static final int WIFI_BAND_BOTH = 3;
-    /** DFS channels from 5 GHz band only */
-    public static final int WIFI_BAND_5_GHZ_DFS_ONLY  = 4;
-    /**
-     * 2.4Ghz band + DFS channels from 5 GHz band only
-     * @hide
-     */
-    public static final int WIFI_BAND_24_GHZ_WITH_5GHZ_DFS  = 5;
-    /** 5 GHz band including DFS channels */
-    public static final int WIFI_BAND_5_GHZ_WITH_DFS  = 6;
-    /** Both 2.4 GHz band and 5 GHz band; with DFS channels */
-    public static final int WIFI_BAND_BOTH_WITH_DFS = 7;
     /**
      * Max band value
      * @hide
@@ -398,7 +433,6 @@
                         return new ScanSettings[size];
                     }
                 };
-
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
index 3bef502..f0a0607 100644
--- a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
+++ b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.net.wifi.WifiSsid;
 import android.os.Bundle;
@@ -86,23 +85,16 @@
      */
     private final List<Integer> mMethodList;
 
-    /**
-     * Icon data for the OSU (Online Sign-Up) provider.
-     */
-    private final Icon mIcon;
-
     /** @hide */
     public OsuProvider(String osuSsid, Map<String, String> friendlyNames,
-            String serviceDescription, Uri serverUri, String nai, List<Integer> methodList,
-            Icon icon) {
+            String serviceDescription, Uri serverUri, String nai, List<Integer> methodList) {
         this(WifiSsid.createFromByteArray(osuSsid.getBytes(StandardCharsets.UTF_8)),
-                friendlyNames, serviceDescription, serverUri, nai, methodList, icon);
+                friendlyNames, serviceDescription, serverUri, nai, methodList);
     }
 
     /** @hide */
     public OsuProvider(WifiSsid osuSsid, Map<String, String> friendlyNames,
-            String serviceDescription, Uri serverUri, String nai, List<Integer> methodList,
-            Icon icon) {
+            String serviceDescription, Uri serverUri, String nai, List<Integer> methodList) {
         mOsuSsid = osuSsid;
         mFriendlyNames = friendlyNames;
         mServiceDescription = serviceDescription;
@@ -113,7 +105,6 @@
         } else {
             mMethodList = new ArrayList<>(methodList);
         }
-        mIcon = icon;
     }
 
     /**
@@ -130,7 +121,6 @@
             mServerUri = null;
             mNetworkAccessIdentifier = null;
             mMethodList = new ArrayList<>();
-            mIcon = null;
             return;
         }
 
@@ -144,7 +134,6 @@
         } else {
             mMethodList = new ArrayList<>(source.mMethodList);
         }
-        mIcon = source.mIcon;
     }
 
     /** @hide */
@@ -205,11 +194,6 @@
         return mMethodList;
     }
 
-    /** @hide */
-    public Icon getIcon() {
-        return mIcon;
-    }
-
     @Override
     public int describeContents() {
         return 0;
@@ -222,7 +206,6 @@
         dest.writeParcelable(mServerUri, flags);
         dest.writeString(mNetworkAccessIdentifier);
         dest.writeList(mMethodList);
-        dest.writeParcelable(mIcon, flags);
         Bundle bundle = new Bundle();
         bundle.putSerializable("friendlyNameMap", (HashMap<String, String>) mFriendlyNames);
         dest.writeBundle(bundle);
@@ -237,21 +220,16 @@
             return false;
         }
         OsuProvider that = (OsuProvider) thatObject;
-        return (mOsuSsid == null ? that.mOsuSsid == null : mOsuSsid.equals(that.mOsuSsid))
-                && (mFriendlyNames == null) ? that.mFriendlyNames == null
-                            : mFriendlyNames.equals(that.mFriendlyNames)
+        return Objects.equals(mOsuSsid, that.mOsuSsid)
+                && Objects.equals(mFriendlyNames, that.mFriendlyNames)
                 && TextUtils.equals(mServiceDescription, that.mServiceDescription)
-                && (mServerUri == null ? that.mServerUri == null
-                            : mServerUri.equals(that.mServerUri))
+                && Objects.equals(mServerUri, that.mServerUri)
                 && TextUtils.equals(mNetworkAccessIdentifier, that.mNetworkAccessIdentifier)
-                && (mMethodList == null ? that.mMethodList == null
-                            : mMethodList.equals(that.mMethodList))
-                && (mIcon == null ? that.mIcon == null : mIcon.sameAs(that.mIcon));
+                && Objects.equals(mMethodList, that.mMethodList);
     }
 
     @Override
     public int hashCode() {
-        // mIcon is not hashable, skip the variable.
         return Objects.hash(mOsuSsid, mServiceDescription, mFriendlyNames,
                 mServerUri, mNetworkAccessIdentifier, mMethodList);
     }
@@ -264,8 +242,7 @@
                 + " mServiceDescription=" + mServiceDescription
                 + " mServerUri=" + mServerUri
                 + " mNetworkAccessIdentifier=" + mNetworkAccessIdentifier
-                + " mMethodList=" + mMethodList
-                + " mIcon=" + mIcon;
+                + " mMethodList=" + mMethodList;
     }
 
     public static final @android.annotation.NonNull Creator<OsuProvider> CREATOR =
@@ -278,12 +255,11 @@
                     String nai = in.readString();
                     List<Integer> methodList = new ArrayList<>();
                     in.readList(methodList, null);
-                    Icon icon = in.readParcelable(null);
                     Bundle bundle = in.readBundle();
                     Map<String, String> friendlyNamesMap = (HashMap) bundle.getSerializable(
                             "friendlyNameMap");
                     return new OsuProvider(osuSsid, friendlyNamesMap, serviceDescription,
-                            serverUri, nai, methodList, icon);
+                            serverUri, nai, methodList);
                 }
 
             @Override
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index 534e609..bc86839 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -285,6 +285,11 @@
     }
 
     @Override
+    public boolean startTetheredHotspot(SoftApConfiguration softApConfig) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public boolean stopSoftAp() {
         throw new UnsupportedOperationException();
     }
@@ -321,10 +326,21 @@
     }
 
     @Override
+    public SoftApConfiguration getSoftApConfiguration() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) {
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public boolean setSoftApConfiguration(SoftApConfiguration softApConfig, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void notifyUserOfApBandConversion(String packageName) {
         throw new UnsupportedOperationException();
     }
@@ -385,6 +401,16 @@
     }
 
     @Override
+    public byte[] retrieveSoftApBackupData() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void restoreSoftApBackupData(byte[] data) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) {
         throw new UnsupportedOperationException();
     }
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
index 949b479..b8d3e41 100644
--- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -46,6 +46,10 @@
         assertThat(original.getSsid()).isEqualTo("ssid");
         assertThat(original.getBssid()).isEqualTo(MacAddress.fromString("11:22:33:44:55:66"));
         assertThat(original.getWpa2Passphrase()).isNull();
+        assertThat(original.getSecurityType()).isEqualTo(SoftApConfiguration.SECURITY_TYPE_OPEN);
+        assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_2GHZ);
+        assertThat(original.getChannel()).isEqualTo(0);
+        assertThat(original.isHiddenSsid()).isEqualTo(false);
 
         SoftApConfiguration unparceled = parcelUnparcel(original);
         assertThat(unparceled).isNotSameAs(original);
@@ -64,6 +68,39 @@
                 .setWpa2Passphrase("secretsecret")
                 .build();
         assertThat(original.getWpa2Passphrase()).isEqualTo("secretsecret");
+        assertThat(original.getSecurityType()).isEqualTo(
+                SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+        assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_2GHZ);
+        assertThat(original.getChannel()).isEqualTo(0);
+        assertThat(original.isHiddenSsid()).isEqualTo(false);
+
+
+        SoftApConfiguration unparceled = parcelUnparcel(original);
+        assertThat(unparceled).isNotSameAs(original);
+        assertThat(unparceled).isEqualTo(original);
+        assertThat(unparceled.hashCode()).isEqualTo(original.hashCode());
+
+        SoftApConfiguration copy = new SoftApConfiguration.Builder(original).build();
+        assertThat(copy).isNotSameAs(original);
+        assertThat(copy).isEqualTo(original);
+        assertThat(copy.hashCode()).isEqualTo(original.hashCode());
+    }
+
+    @Test
+    public void testWpa2WithBandAndChannelAndHiddenNetwork() {
+        SoftApConfiguration original = new SoftApConfiguration.Builder()
+                .setWpa2Passphrase("secretsecret")
+                .setBand(SoftApConfiguration.BAND_ANY)
+                .setChannel(149)
+                .setHiddenSsid(true)
+                .build();
+        assertThat(original.getWpa2Passphrase()).isEqualTo("secretsecret");
+        assertThat(original.getSecurityType()).isEqualTo(
+                SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+        assertThat(original.getBand()).isEqualTo(SoftApConfiguration.BAND_ANY);
+        assertThat(original.getChannel()).isEqualTo(149);
+        assertThat(original.isHiddenSsid()).isEqualTo(true);
+
 
         SoftApConfiguration unparceled = parcelUnparcel(original);
         assertThat(unparceled).isNotSameAs(original);
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index d326201..d22dbd3 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -181,6 +181,33 @@
     }
 
     /**
+     * Check the call to startSoftAp calls WifiService to startSoftAp with the provided
+     * WifiConfiguration.  Verify that the return value is propagated to the caller.
+     */
+    @Test
+    public void testStartTetheredHotspotCallsServiceWithSoftApConfig() throws Exception {
+        SoftApConfiguration mSoftApConfig = new SoftApConfiguration.Builder().build();
+        when(mWifiService.startTetheredHotspot(eq(mSoftApConfig))).thenReturn(true);
+        assertTrue(mWifiManager.startTetheredHotspot(mSoftApConfig));
+
+        when(mWifiService.startTetheredHotspot(eq(mSoftApConfig))).thenReturn(false);
+        assertFalse(mWifiManager.startTetheredHotspot(mSoftApConfig));
+    }
+
+    /**
+     * Check the call to startSoftAp calls WifiService to startSoftAp with a null config.  Verify
+     * that the return value is propagated to the caller.
+     */
+    @Test
+    public void testStartTetheredHotspotCallsServiceWithNullConfig() throws Exception {
+        when(mWifiService.startTetheredHotspot(eq(null))).thenReturn(true);
+        assertTrue(mWifiManager.startTetheredHotspot(null));
+
+        when(mWifiService.startTetheredHotspot(eq(null))).thenReturn(false);
+        assertFalse(mWifiManager.startTetheredHotspot(null));
+    }
+
+    /**
      * Test creation of a LocalOnlyHotspotReservation and verify that close properly calls
      * WifiService.stopLocalOnlyHotspot.
      */
@@ -1148,6 +1175,43 @@
     }
 
     /**
+     * Verify that a successful call properly returns true.
+     */
+    @Test
+    public void testSetSoftApConfigurationSuccessReturnsTrue() throws Exception {
+        SoftApConfiguration apConfig = new SoftApConfiguration.Builder().build();
+
+        when(mWifiService.setSoftApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
+                .thenReturn(true);
+        assertTrue(mWifiManager.setSoftApConfiguration(apConfig));
+    }
+
+    /**
+     * Verify that a failed call properly returns false.
+     */
+    @Test
+    public void testSetSoftApConfigurationFailureReturnsFalse() throws Exception {
+        SoftApConfiguration apConfig = new SoftApConfiguration.Builder().build();
+
+        when(mWifiService.setSoftApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
+                .thenReturn(false);
+        assertFalse(mWifiManager.setSoftApConfiguration(apConfig));
+    }
+
+    /**
+     * Verify Exceptions are rethrown when underlying calls to WifiService throw exceptions.
+     */
+    @Test
+    public void testSetSoftApConfigurationRethrowsException() throws Exception {
+        doThrow(new SecurityException()).when(mWifiService).setSoftApConfiguration(any(), any());
+
+        try {
+            mWifiManager.setSoftApConfiguration(new SoftApConfiguration.Builder().build());
+            fail("setWifiApConfiguration should rethrow Exceptions from WifiService");
+        } catch (SecurityException e) { }
+    }
+
+    /**
      * Check the call to startScan calls WifiService.
      */
     @Test
@@ -1620,7 +1684,7 @@
     @Test
     public void testGetControllerActivityEnergyInfo() throws Exception {
         WifiActivityEnergyInfo activityEnergyInfo =
-                new WifiActivityEnergyInfo(5, 3, 3, new long[]{5L, 5L, 5L}, 5, 5, 5, 5);
+                new WifiActivityEnergyInfo(5, 3, 3, 5, 5, 5, 5);
         when(mWifiService.reportActivityInfo()).thenReturn(activityEnergyInfo);
 
         assertEquals(activityEnergyInfo, mWifiManager.getControllerActivityEnergyInfo());
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java b/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
index 43ee249..2ded849 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/OsuProviderTest.java
@@ -19,7 +19,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.net.wifi.WifiSsid;
 import android.os.Parcel;
@@ -56,7 +55,6 @@
     private static final String TEST_NAI = "test.access.com";
     private static final List<Integer> TEST_METHOD_LIST =
             Arrays.asList(OsuProvider.METHOD_SOAP_XML_SPP);
-    private static final Icon TEST_ICON = Icon.createWithData(new byte[10], 0, 10);
 
     /**
      * Verify parcel write and read consistency for the given {@link OsuProvider}.
@@ -82,7 +80,7 @@
      */
     @Test
     public void verifyParcelWithEmptyProviderInfo() throws Exception {
-        verifyParcel(new OsuProvider((WifiSsid) null, null, null, null, null, null, null));
+        verifyParcel(new OsuProvider((WifiSsid) null, null, null, null, null, null));
     }
 
     /**
@@ -93,7 +91,7 @@
     @Test
     public void verifyParcelWithFullProviderInfo() throws Exception {
         verifyParcel(new OsuProvider(TEST_SSID, TEST_FRIENDLY_NAMES,
-                TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST, TEST_ICON));
+                TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST));
     }
 
     /**
@@ -102,7 +100,7 @@
      */
     @Test
     public void verifyCopyConstructorWithNullSource() throws Exception {
-        OsuProvider expected = new OsuProvider((WifiSsid) null, null, null, null, null, null, null);
+        OsuProvider expected = new OsuProvider((WifiSsid) null, null, null, null, null, null);
         assertEquals(expected, new OsuProvider(null));
     }
 
@@ -114,7 +112,7 @@
     @Test
     public void verifyCopyConstructorWithValidSource() throws Exception {
         OsuProvider source = new OsuProvider(TEST_SSID, TEST_FRIENDLY_NAMES,
-                TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST, TEST_ICON);
+                TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST);
         assertEquals(source, new OsuProvider(source));
     }
 
@@ -126,7 +124,7 @@
     @Test
     public void verifyGetters() throws Exception {
         OsuProvider provider = new OsuProvider(TEST_SSID, TEST_FRIENDLY_NAMES,
-                TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST, TEST_ICON);
+                TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI, TEST_METHOD_LIST);
 
         assertTrue(TEST_SSID.equals(provider.getOsuSsid()));
         assertTrue(TEST_FRIENDLY_NAME.equals(provider.getFriendlyName()));
@@ -135,6 +133,5 @@
         assertTrue(TEST_SERVER_URI.equals(provider.getServerUri()));
         assertTrue(TEST_NAI.equals(provider.getNetworkAccessIdentifier()));
         assertTrue(TEST_METHOD_LIST.equals(provider.getMethodList()));
-        assertTrue(TEST_ICON.sameAs(provider.getIcon()));
     }
 }