Merge "Remove old workaround for display issues" into pi-dev
diff --git a/Android.bp b/Android.bp
index 037c29c..be83210 100644
--- a/Android.bp
+++ b/Android.bp
@@ -169,8 +169,6 @@
         "core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl",
         "core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl",
         "core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl",
-        "core/java/android/hardware/location/IFusedLocationHardware.aidl",
-        "core/java/android/hardware/location/IFusedLocationHardwareSink.aidl",
         "core/java/android/hardware/location/IGeofenceHardware.aidl",
         "core/java/android/hardware/location/IGeofenceHardwareCallback.aidl",
         "core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl",
@@ -409,7 +407,6 @@
         "location/java/android/location/IBatchedLocationCallback.aidl",
         "location/java/android/location/ICountryDetector.aidl",
         "location/java/android/location/ICountryListener.aidl",
-        "location/java/android/location/IFusedProvider.aidl",
         "location/java/android/location/IGeocodeProvider.aidl",
         "location/java/android/location/IGeofenceProvider.aidl",
         "location/java/android/location/IGnssStatusListener.aidl",
diff --git a/Android.mk b/Android.mk
index ee8fbe0..e2f88e8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -861,42 +861,39 @@
 
 # ==== hiddenapi lists =======================================
 
-# Copy light and dark greylist over into the build folder.
+# Copy blacklist and light greylist over into the build folder.
 # This is for ART buildbots which need to mock these lists and have alternative
 # rules for building them. Other rules in the build system should depend on the
 # files in the build folder.
 
+$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-blacklist.txt,\
+                            $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)))
+
 # Temporarily merge light greylist from two files. Vendor list will become dark
 # grey once we remove the UI toast.
 $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): frameworks/base/config/hiddenapi-light-greylist.txt \
                                                frameworks/base/config/hiddenapi-vendor-list.txt
 	sort $^ > $@
 
-$(eval $(call copy-one-file,frameworks/base/config/hiddenapi-dark-greylist.txt,\
-                            $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)))
-
 # Generate dark greylist as private API minus (blacklist plus light greylist).
 
-$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
-$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): LIGHT_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST)
-$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): DARK_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)
-$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST): $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
-                                          $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
-                                          $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST)
-	if [ ! -z "`comm -12 <(sort $(LIGHT_GREYLIST)) <(sort $(DARK_GREYLIST))`" ]; then \
-		echo "There should be no overlap between $(LIGHT_GREYLIST) and $(DARK_GREYLIST)" 1>&2; \
-		comm -12 <(sort $(LIGHT_GREYLIST)) <(sort $(DARK_GREYLIST)) 1>&2; \
+$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
+$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): BLACKLIST := $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
+$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): LIGHT_GREYLIST := $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST)
+$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST): $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE) \
+                                              $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST) \
+                                              $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST)
+	if [ ! -z "`comm -12 <(sort $(BLACKLIST)) <(sort $(LIGHT_GREYLIST))`" ]; then \
+		echo "There should be no overlap between $(BLACKLIST) and $(LIGHT_GREYLIST)" 1>&2; \
 		exit 1; \
+	elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST))`" ]; then \
+		echo "$(BLACKLIST) must be a subset of $(PRIVATE_API)" 1>&2; \
+		exit 2; \
 	elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(LIGHT_GREYLIST))`" ]; then \
 		echo "$(LIGHT_GREYLIST) must be a subset of $(PRIVATE_API)" 1>&2; \
-		comm -13 <(sort $(PRIVATE_API)) <(sort $(LIGHT_GREYLIST)) 1>&2; \
-		exit 2; \
-	elif [ ! -z "`comm -13 <(sort $(PRIVATE_API)) <(sort $(DARK_GREYLIST))`" ]; then \
-		echo "$(DARK_GREYLIST) must be a subset of $(PRIVATE_API)" 1>&2; \
-		comm -13 <(sort $(PRIVATE_API)) <(sort $(DARK_GREYLIST)) 1>&2; \
 		exit 3; \
 	fi
-	comm -23 <(sort $(PRIVATE_API)) <(sort $(LIGHT_GREYLIST) $(DARK_GREYLIST)) > $@
+	comm -23 <(sort $(PRIVATE_API)) <(sort $(BLACKLIST) $(LIGHT_GREYLIST)) > $@
 
 # Include subdirectory makefiles
 # ============================================================
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
new file mode 100644
index 0000000..28d4096
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 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.os;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.BinderCallsStats;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertNull;
+
+
+/**
+ * Performance tests for {@link BinderCallsStats}
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class BinderCallsStatsPerfTest {
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+    private BinderCallsStats mBinderCallsStats;
+
+    @Before
+    public void setUp() {
+        mBinderCallsStats = new BinderCallsStats(true);
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    @Test
+    public void timeCallSession() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Binder b = new Binder();
+        int i = 0;
+        while (state.keepRunning()) {
+            BinderCallsStats.CallSession s = mBinderCallsStats.callStarted(b, i % 100);
+            mBinderCallsStats.callEnded(s);
+            i++;
+        }
+    }
+
+    @Test
+    public void timeCallSessionTrackingDisabled() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Binder b = new Binder();
+        mBinderCallsStats = new BinderCallsStats(false);
+        assertNull(mBinderCallsStats.callStarted(b, 0));
+        while (state.keepRunning()) {
+            BinderCallsStats.CallSession s = mBinderCallsStats.callStarted(b, 0);
+            mBinderCallsStats.callEnded(s);
+        }
+    }
+
+}
diff --git a/api/current.txt b/api/current.txt
index a0b887a..999a6fb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6559,7 +6559,7 @@
     method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
     method public void setLogoutEnabled(android.content.ComponentName, boolean);
     method public void setLongSupportMessage(android.content.ComponentName, java.lang.CharSequence);
-    method public void setMandatoryBackupTransport(android.content.ComponentName, android.content.ComponentName);
+    method public boolean setMandatoryBackupTransport(android.content.ComponentName, android.content.ComponentName);
     method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
@@ -7193,6 +7193,7 @@
     field public static final deprecated java.lang.String EXTRA_SLIDER_VALUE = "android.app.slice.extra.SLIDER_VALUE";
     field public static final java.lang.String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE";
     field public static final java.lang.String HINT_ACTIONS = "actions";
+    field public static final java.lang.String HINT_ERROR = "error";
     field public static final java.lang.String HINT_HORIZONTAL = "horizontal";
     field public static final java.lang.String HINT_KEY_WORDS = "key_words";
     field public static final java.lang.String HINT_LARGE = "large";
@@ -7218,29 +7219,22 @@
   }
 
   public static class Slice.Builder {
-    ctor public Slice.Builder(android.net.Uri);
+    ctor public deprecated Slice.Builder(android.net.Uri);
+    ctor public Slice.Builder(android.net.Uri, android.app.slice.SliceSpec);
     ctor public Slice.Builder(android.app.slice.Slice.Builder);
-    method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice);
     method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice, java.lang.String);
-    method public android.app.slice.Slice.Builder addBundle(android.os.Bundle, java.lang.String, java.lang.String...);
     method public android.app.slice.Slice.Builder addBundle(android.os.Bundle, java.lang.String, java.util.List<java.lang.String>);
-    method public android.app.slice.Slice.Builder addHints(java.lang.String...);
     method public android.app.slice.Slice.Builder addHints(java.util.List<java.lang.String>);
-    method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.lang.String...);
     method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.util.List<java.lang.String>);
-    method public android.app.slice.Slice.Builder addInt(int, java.lang.String, java.lang.String...);
     method public android.app.slice.Slice.Builder addInt(int, java.lang.String, java.util.List<java.lang.String>);
+    method public android.app.slice.Slice.Builder addLong(long, java.lang.String, java.util.List<java.lang.String>);
     method public android.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.util.List<java.lang.String>);
-    method public android.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.lang.String...);
-    method public android.app.slice.Slice.Builder addSubSlice(android.app.slice.Slice);
     method public android.app.slice.Slice.Builder addSubSlice(android.app.slice.Slice, java.lang.String);
-    method public android.app.slice.Slice.Builder addText(java.lang.CharSequence, java.lang.String, java.lang.String...);
     method public android.app.slice.Slice.Builder addText(java.lang.CharSequence, java.lang.String, java.util.List<java.lang.String>);
-    method public android.app.slice.Slice.Builder addTimestamp(long, java.lang.String, java.lang.String...);
-    method public android.app.slice.Slice.Builder addTimestamp(long, java.lang.String, java.util.List<java.lang.String>);
+    method public deprecated android.app.slice.Slice.Builder addTimestamp(long, java.lang.String, java.util.List<java.lang.String>);
     method public android.app.slice.Slice build();
     method public android.app.slice.Slice.Builder setCallerNeeded(boolean);
-    method public android.app.slice.Slice.Builder setSpec(android.app.slice.SliceSpec);
+    method public deprecated android.app.slice.Slice.Builder setSpec(android.app.slice.SliceSpec);
   }
 
   public final class SliceItem implements android.os.Parcelable {
@@ -7263,10 +7257,11 @@
     field public static final java.lang.String FORMAT_BUNDLE = "bundle";
     field public static final java.lang.String FORMAT_IMAGE = "image";
     field public static final java.lang.String FORMAT_INT = "int";
+    field public static final java.lang.String FORMAT_LONG = "long";
     field public static final java.lang.String FORMAT_REMOTE_INPUT = "input";
     field public static final java.lang.String FORMAT_SLICE = "slice";
     field public static final java.lang.String FORMAT_TEXT = "text";
-    field public static final java.lang.String FORMAT_TIMESTAMP = "timestamp";
+    field public static final deprecated java.lang.String FORMAT_TIMESTAMP = "long";
   }
 
   public class SliceManager {
@@ -21823,7 +21818,6 @@
     method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback);
-    field public static final java.lang.String GNSS_HARDWARE_MODEL_NAME_UNKNOWN = "Model Name Unknown";
     field public static final java.lang.String GPS_PROVIDER = "gps";
     field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
     field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -41427,7 +41421,7 @@
     method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
     field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
     field public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2; // 0x2
-    field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4; // 0x4
+    field public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4; // 0x4
     field public static final int HANDOVER_FAILURE_UNKNOWN = 5; // 0x5
     field public static final int HANDOVER_FAILURE_USER_REJECTED = 3; // 0x3
   }
@@ -51597,7 +51591,6 @@
     field public static final int CATEGORIES_WEB_DEVELOPER = 4; // 0x4
     field public static final int RECORD_CONTINUOUSLY = 1; // 0x1
     field public static final int RECORD_UNTIL_FULL = 0; // 0x0
-    field public static final int RECORD_UNTIL_FULL_LARGE_BUFFER = 2; // 0x2
   }
 
   public static class TracingConfig.Builder {
diff --git a/api/system-current.txt b/api/system-current.txt
index 1e2fe3d..04d78a1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -283,6 +283,7 @@
     field public static final java.lang.String OPSTR_GET_ACCOUNTS = "android:get_accounts";
     field public static final java.lang.String OPSTR_GPS = "android:gps";
     field public static final java.lang.String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
+    field public static final java.lang.String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
     field public static final java.lang.String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
     field public static final java.lang.String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
     field public static final java.lang.String OPSTR_PLAY_AUDIO = "android:play_audio";
@@ -3067,8 +3068,10 @@
   }
 
   public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable {
+    method public void addAddress(android.net.LinkAddress) throws java.io.IOException;
     method public void close();
     method public java.lang.String getInterfaceName();
+    method public void removeAddress(android.net.LinkAddress) throws java.io.IOException;
   }
 
   public final class IpSecTransform implements java.lang.AutoCloseable {
@@ -4234,7 +4237,7 @@
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     method public static boolean putString(android.content.ContentResolver, java.lang.String, java.lang.String, java.lang.String, boolean);
     method public static void resetToDefaults(android.content.ContentResolver, java.lang.String);
-    field public static final java.lang.String AUTOFILL_COMPAT_ALLOWED_PACKAGES = "autofill_compat_allowed_packages";
+    field public static final java.lang.String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
     field public static final java.lang.String CARRIER_APP_NAMES = "carrier_app_names";
     field public static final java.lang.String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
     field public static final java.lang.String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
@@ -4369,6 +4372,7 @@
     method public int[] getRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException;
     method public deprecated int getRecoveryStatus(java.lang.String, java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
     method public int getRecoveryStatus(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public java.util.Map<java.lang.String, java.security.cert.X509Certificate> getRootCertificates();
     method public java.security.Key importKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
     method public deprecated void initRecoveryService(java.lang.String, byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
     method public void initRecoveryService(java.lang.String, byte[], byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
@@ -4386,9 +4390,11 @@
 
   public class RecoverySession implements java.lang.AutoCloseable {
     method public void close();
-    method public java.util.Map<java.lang.String, byte[]> recoverKeys(byte[], java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
+    method public java.util.Map<java.lang.String, java.security.Key> recoverKeyChainSnapshot(byte[], java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
+    method public deprecated java.util.Map<java.lang.String, byte[]> recoverKeys(byte[], java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
     method public deprecated byte[] start(byte[], byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
-    method public byte[] start(java.security.cert.CertPath, byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public deprecated byte[] start(java.security.cert.CertPath, byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
+    method public byte[] start(java.lang.String, java.security.cert.CertPath, byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
   }
 
   public class SessionExpiredException extends java.security.GeneralSecurityException {
diff --git a/api/test-current.txt b/api/test-current.txt
index 70e3cf3..852bebf 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -79,6 +79,7 @@
     field public static final java.lang.String OPSTR_GET_ACCOUNTS = "android:get_accounts";
     field public static final java.lang.String OPSTR_GPS = "android:gps";
     field public static final java.lang.String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
+    field public static final java.lang.String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
     field public static final java.lang.String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
     field public static final java.lang.String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
     field public static final java.lang.String OPSTR_PLAY_AUDIO = "android:play_audio";
@@ -570,7 +571,7 @@
   }
 
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
-    field public static final java.lang.String AUTOFILL_COMPAT_ALLOWED_PACKAGES = "autofill_compat_allowed_packages";
+    field public static final java.lang.String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
     field public static final java.lang.String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
     field public static final java.lang.String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
     field public static final java.lang.String LOW_POWER_MODE = "low_power";
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index ca0611b..79c0d71 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -135,6 +135,12 @@
 
 LOCAL_MODULE_CLASS := EXECUTABLES
 
+# Enable sanitizer on eng builds
+ifeq ($(TARGET_BUILD_VARIANT),eng)
+    LOCAL_CLANG := true
+    LOCAL_SANITIZE := address
+endif
+
 LOCAL_INIT_RC := statsd.rc
 
 include $(BUILD_EXECUTABLE)
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 40eff4c..99611f4 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -23,6 +23,7 @@
 
 import "frameworks/base/cmds/statsd/src/atom_field_options.proto";
 import "frameworks/base/core/proto/android/app/enums.proto";
+import "frameworks/base/core/proto/android/app/job/enums.proto";
 import "frameworks/base/core/proto/android/bluetooth/enums.proto";
 import "frameworks/base/core/proto/android/os/enums.proto";
 import "frameworks/base/core/proto/android/server/enums.proto";
@@ -362,7 +363,10 @@
     }
     optional State state = 3;
 
-    // TODO: Consider adding the stopReason (int)
+    // The reason a job has stopped.
+    // This is only applicable when the state is FINISHED.
+    // The default value is CANCELED.
+    optional android.app.job.StopReasonEnum stop_reason = 4;
 }
 
 /**
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 40b266f..87fb998 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -3375,8 +3375,6 @@
 HPLandroid/location/ICountryListener$Stub;->asBinder()Landroid/os/IBinder;
 HPLandroid/location/ICountryListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryListener;
 HPLandroid/location/ICountryListener;->onCountryDetected(Landroid/location/Country;)V
-HPLandroid/location/IFusedProvider$Stub;-><init>()V
-HPLandroid/location/IFusedProvider;->onFusedLocationHardwareChange(Landroid/hardware/location/IFusedLocationHardware;)V
 HPLandroid/location/IGeocodeProvider$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 HPLandroid/location/IGeocodeProvider$Stub$Proxy;->getFromLocation(DDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String;
 HPLandroid/location/IGeocodeProvider$Stub;-><init>()V
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index da386d7..e4df85b 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -26,6 +26,7 @@
 Landroid/app/ActivityManager$RecentTaskInfo;->userId:I
 Landroid/app/ActivityManager$RunningAppProcessInfo;->flags:I
 Landroid/app/ActivityManager$RunningAppProcessInfo;->processState:I
+Landroid/app/ActivityManager;->setPersistentVrThread(I)V
 Landroid/app/ActivityManager$TaskDescription;->getBackgroundColor()I
 Landroid/app/ActivityManager$TaskDescription;->getInMemoryIcon()Landroid/graphics/Bitmap;
 Landroid/app/ActivityManager$TaskSnapshot;->getContentInsets()Landroid/graphics/Rect;
@@ -329,6 +330,13 @@
 Landroid/app/usage/UsageStatsManager;->mService:Landroid/app/usage/IUsageStatsManager;
 Landroid/app/usage/UsageStats;->mLastEvent:I
 Landroid/app/usage/UsageStats;->mTotalTimeInForeground:J
+Landroid/app/Vr2dDisplayProperties$Builder;->build()Landroid/app/Vr2dDisplayProperties;
+Landroid/app/Vr2dDisplayProperties$Builder;-><init>()V
+Landroid/app/Vr2dDisplayProperties$Builder;->setEnabled(Z)Landroid/app/Vr2dDisplayProperties$Builder;
+Landroid/app/Vr2dDisplayProperties;-><init>(III)V
+Landroid/app/VrManager;->getPersistentVrModeEnabled()Z
+Landroid/app/VrManager;->registerVrStateCallback(Landroid/app/VrStateCallback;Landroid/os/Handler;)V
+Landroid/app/VrManager;->setVr2dDisplayProperties(Landroid/app/Vr2dDisplayProperties;)V
 Landroid/app/WallpaperColors;->getColorHints()I
 Landroid/app/WallpaperManager;->getBitmap()Landroid/graphics/Bitmap;
 Landroid/app/WallpaperManager;->getBitmap(Z)Landroid/graphics/Bitmap;
@@ -686,8 +694,13 @@
 Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V
 Landroid/graphics/Typeface;->sSystemFontMap:Ljava/util/Map;
 Landroid/hardware/camera2/CameraCharacteristics$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
+Landroid/hardware/camera2/CameraCharacteristics$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
 Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
 Landroid/hardware/camera2/CaptureResult$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;J)V
+Landroid/hardware/camera2/CaptureResult$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
+Landroid/hardware/camera2/CaptureResult;->STATISTICS_OIS_TIMESTAMPS:Landroid/hardware/camera2/CaptureResult$Key;
+Landroid/hardware/camera2/CaptureResult;->STATISTICS_OIS_X_SHIFTS:Landroid/hardware/camera2/CaptureResult$Key;
+Landroid/hardware/camera2/CaptureResult;->STATISTICS_OIS_Y_SHIFTS:Landroid/hardware/camera2/CaptureResult$Key;
 Landroid/hardware/camera2/impl/CameraMetadataNative;->mMetadataPtr:J
 Landroid/hardware/Camera;->addCallbackBuffer([BI)V
 Landroid/hardware/Camera;->mNativeContext:J
@@ -810,7 +823,6 @@
 Landroid/location/Country;->getSource()I
 Landroid/location/GeocoderParams;->getClientPackage()Ljava/lang/String;
 Landroid/location/GeocoderParams;->getLocale()Ljava/util/Locale;
-Landroid/location/IFusedProvider$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;-><init>()V
 Landroid/location/IGeofenceProvider$Stub;-><init>()V
 Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
@@ -1695,6 +1707,7 @@
 Landroid/service/notification/NotificationListenerService;->unregisterAsSystemService()V
 Landroid/service/voice/AlwaysOnHotwordDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer;
 Landroid/service/voice/VoiceInteractionService;->isKeyphraseAndLocaleSupportedForHotword(Ljava/lang/String;Ljava/util/Locale;)Z
+Landroid/service/vr/IVrManager;->getVr2dDisplayId()I
 Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V
 Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String;
 Landroid/system/Int32Ref;->value:I
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index fe9a5db..0230ad9 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -113,7 +113,6 @@
 Landroid/hardware/display/DisplayManagerGlobal;->getRealDisplay(I)Landroid/view/Display;
 Landroid/hardware/location/GeofenceHardware;-><init>(Landroid/hardware/location/IGeofenceHardware;)V
 Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V
-Landroid/location/IFusedProvider;->onFusedLocationHardwareChange(Landroid/hardware/location/IFusedLocationHardware;)V
 Landroid/location/IGeocodeProvider;->getFromLocation(DDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String;
 Landroid/location/IGeocodeProvider;->getFromLocationName(Ljava/lang/String;DDDDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String;
 Landroid/location/IGeofenceProvider;->setGeofenceHardware(Landroid/hardware/location/IGeofenceHardware;)V
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1d069bc..baf2d60 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -147,7 +147,7 @@
 import com.android.internal.util.FastPrintWriter;
 import com.android.org.conscrypt.OpenSSLSocketImpl;
 import com.android.org.conscrypt.TrustedCertificateStore;
-import com.android.server.am.proto.MemInfoDumpProto;
+import com.android.server.am.MemInfoDumpProto;
 
 import dalvik.system.BaseDexClassLoader;
 import dalvik.system.CloseGuard;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4690211..ea8c71c 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -270,8 +270,10 @@
     public static final int OP_BIND_ACCESSIBILITY_SERVICE = 73;
     /** @hide Continue handover of a call from another app */
     public static final int OP_ACCEPT_HANDOVER = 74;
+    /** @hide Create and Manage IPsec Tunnels */
+    public static final int OP_MANAGE_IPSEC_TUNNELS = 75;
     /** @hide */
-    public static final int _NUM_OP = 75;
+    public static final int _NUM_OP = 76;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -507,6 +509,9 @@
     @SystemApi @TestApi
     public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE =
             "android:bind_accessibility_service";
+    /** @hide */
+    @SystemApi @TestApi
+    public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
 
     // Warning: If an permission is added here it also has to be added to
     // com.android.packageinstaller.permission.utils.EventLogger
@@ -641,6 +646,7 @@
             OP_REQUEST_DELETE_PACKAGES,
             OP_BIND_ACCESSIBILITY_SERVICE,
             OP_ACCEPT_HANDOVER,
+            OP_MANAGE_IPSEC_TUNNELS,
     };
 
     /**
@@ -722,6 +728,7 @@
             OPSTR_REQUEST_DELETE_PACKAGES,
             OPSTR_BIND_ACCESSIBILITY_SERVICE,
             OPSTR_ACCEPT_HANDOVER,
+            OPSTR_MANAGE_IPSEC_TUNNELS,
     };
 
     /**
@@ -804,6 +811,7 @@
             "REQUEST_DELETE_PACKAGES",
             "BIND_ACCESSIBILITY_SERVICE",
             "ACCEPT_HANDOVER",
+            "MANAGE_IPSEC_TUNNELS",
     };
 
     /**
@@ -886,6 +894,7 @@
             Manifest.permission.REQUEST_DELETE_PACKAGES,
             Manifest.permission.BIND_ACCESSIBILITY_SERVICE,
             Manifest.permission.ACCEPT_HANDOVER,
+            null, // no permission for OP_MANAGE_IPSEC_TUNNELS
     };
 
     /**
@@ -969,6 +978,7 @@
             null, // REQUEST_DELETE_PACKAGES
             null, // OP_BIND_ACCESSIBILITY_SERVICE
             null, // ACCEPT_HANDOVER
+            null, // MANAGE_IPSEC_TUNNELS
     };
 
     /**
@@ -1051,6 +1061,7 @@
             false, // OP_REQUEST_DELETE_PACKAGES
             false, // OP_BIND_ACCESSIBILITY_SERVICE
             false, // ACCEPT_HANDOVER
+            false, // MANAGE_IPSEC_HANDOVERS
     };
 
     /**
@@ -1132,6 +1143,7 @@
             AppOpsManager.MODE_ALLOWED,  // REQUEST_DELETE_PACKAGES
             AppOpsManager.MODE_ALLOWED,  // OP_BIND_ACCESSIBILITY_SERVICE
             AppOpsManager.MODE_ALLOWED,  // ACCEPT_HANDOVER
+            AppOpsManager.MODE_ERRORED,  // MANAGE_IPSEC_TUNNELS
     };
 
     /**
@@ -1217,6 +1229,7 @@
             false, // OP_REQUEST_DELETE_PACKAGES
             false, // OP_BIND_ACCESSIBILITY_SERVICE
             false, // ACCEPT_HANDOVER
+            false, // MANAGE_IPSEC_TUNNELS
     };
 
     /**
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index c6568e1..5d21be5 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2631,8 +2631,8 @@
                     if (!Objects.equals(firstRs[j].getLabel(), secondRs[j].getLabel())) {
                         return true;
                     }
-                    CharSequence[] firstCs = firstRs[i].getChoices();
-                    CharSequence[] secondCs = secondRs[i].getChoices();
+                    CharSequence[] firstCs = firstRs[j].getChoices();
+                    CharSequence[] secondCs = secondRs[j].getChoices();
                     if (firstCs == null) {
                         firstCs = new CharSequence[0];
                     }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 02e77df..4cb7f89 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8877,15 +8877,20 @@
      * <p>If backups were disabled and a non-null backup transport {@link ComponentName} is
      * specified, backups will be enabled.
      *
+     * <p>NOTE: The method shouldn't be called on the main thread.
+     *
      * @param admin admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param backupTransportComponent The backup transport layer to be used for mandatory backups.
+     * @return {@code true} if the backup transport was successfully set; {@code false} otherwise.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public void setMandatoryBackupTransport(
-            @NonNull ComponentName admin, @Nullable ComponentName backupTransportComponent) {
+    @WorkerThread
+    public boolean setMandatoryBackupTransport(
+            @NonNull ComponentName admin,
+            @Nullable ComponentName backupTransportComponent) {
         throwIfParentInstance("setMandatoryBackupTransport");
         try {
-            mService.setMandatoryBackupTransport(admin, backupTransportComponent);
+            return mService.setMandatoryBackupTransport(admin, backupTransportComponent);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c29369f..c46402f 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -364,7 +364,7 @@
 
     void setBackupServiceEnabled(in ComponentName admin, boolean enabled);
     boolean isBackupServiceEnabled(in ComponentName admin);
-    void setMandatoryBackupTransport(in ComponentName admin, in ComponentName backupTransportComponent);
+    boolean setMandatoryBackupTransport(in ComponentName admin, in ComponentName backupTransportComponent);
     ComponentName getMandatoryBackupTransport();
 
     void setNetworkLoggingEnabled(in ComponentName admin, boolean enabled);
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index c71bf2e..d67f11b 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -36,15 +36,16 @@
 public class JobParameters implements Parcelable {
 
     /** @hide */
-    public static final int REASON_CANCELED = 0;
+    public static final int REASON_CANCELED = JobProtoEnums.STOP_REASON_CANCELLED; // 0.
     /** @hide */
-    public static final int REASON_CONSTRAINTS_NOT_SATISFIED = 1;
+    public static final int REASON_CONSTRAINTS_NOT_SATISFIED =
+            JobProtoEnums.STOP_REASON_CONSTRAINTS_NOT_SATISFIED; //1.
     /** @hide */
-    public static final int REASON_PREEMPT = 2;
+    public static final int REASON_PREEMPT = JobProtoEnums.STOP_REASON_PREEMPT; // 2.
     /** @hide */
-    public static final int REASON_TIMEOUT = 3;
+    public static final int REASON_TIMEOUT = JobProtoEnums.STOP_REASON_TIMEOUT; // 3.
     /** @hide */
-    public static final int REASON_DEVICE_IDLE = 4;
+    public static final int REASON_DEVICE_IDLE = JobProtoEnums.STOP_REASON_DEVICE_IDLE; // 4.
 
     /** @hide */
     public static String getReasonName(int reason) {
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index d6f2352..61679cb 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -66,10 +66,27 @@
             HINT_HORIZONTAL,
             HINT_PARTIAL,
             HINT_SEE_MORE,
-            HINT_KEY_WORDS
+            HINT_KEY_WORDS,
+            HINT_ERROR,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SliceHint {}
+    /**
+     * @hide
+     */
+    @StringDef(prefix = { "SUBTYPE_" }, value = {
+            SUBTYPE_COLOR,
+            SUBTYPE_CONTENT_DESCRIPTION,
+            SUBTYPE_MAX,
+            SUBTYPE_MESSAGE,
+            SUBTYPE_PRIORITY,
+            SUBTYPE_RANGE,
+            SUBTYPE_SOURCE,
+            SUBTYPE_TOGGLE,
+            SUBTYPE_VALUE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SliceSubtype {}
 
     /**
      * Hint that this content is a title of other content in the slice. This can also indicate that
@@ -149,9 +166,14 @@
     /**
      * A hint to indicate that the contents of this subslice represent a list of keywords
      * related to the parent slice.
+     * Expected to be on an item of format {@link SliceItem#FORMAT_SLICE}.
      */
     public static final String HINT_KEY_WORDS = "key_words";
     /**
+     * A hint to indicate that this slice represents an error.
+     */
+    public static final String HINT_ERROR = "error";
+    /**
      * Key to retrieve an extra added to an intent when a control is changed.
      */
     public static final String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE";
@@ -168,14 +190,18 @@
     /**
      * Subtype to indicate that this is a message as part of a communication
      * sequence in this slice.
+     * Expected to be on an item of format {@link SliceItem#FORMAT_SLICE}.
      */
     public static final String SUBTYPE_MESSAGE = "message";
     /**
      * Subtype to tag the source (i.e. sender) of a {@link #SUBTYPE_MESSAGE}.
+     * Expected to be on an item of format {@link SliceItem#FORMAT_TEXT},
+     * {@link SliceItem#FORMAT_IMAGE} or an {@link SliceItem#FORMAT_SLICE} containing them.
      */
     public static final String SUBTYPE_SOURCE = "source";
     /**
      * Subtype to tag an item as representing a color.
+     * Expected to be on an item of format {@link SliceItem#FORMAT_INT}.
      */
     public static final String SUBTYPE_COLOR = "color";
     /**
@@ -186,14 +212,18 @@
     public static final String SUBTYPE_SLIDER = "slider";
     /**
      * Subtype to tag an item as representing a range.
+     * Expected to be on an item of format {@link SliceItem#FORMAT_SLICE} containing
+     * a {@link #SUBTYPE_VALUE} and possibly a {@link #SUBTYPE_MAX}.
      */
     public static final String SUBTYPE_RANGE = "range";
     /**
      * Subtype to tag an item as representing the max int value for a {@link #SUBTYPE_RANGE}.
+     * Expected to be on an item of format {@link SliceItem#FORMAT_INT}.
      */
     public static final String SUBTYPE_MAX = "max";
     /**
      * Subtype to tag an item as representing the current int value for a {@link #SUBTYPE_RANGE}.
+     * Expected to be on an item of format {@link SliceItem#FORMAT_INT}.
      */
     public static final String SUBTYPE_VALUE = "value";
     /**
@@ -205,10 +235,12 @@
     public static final String SUBTYPE_TOGGLE = "toggle";
     /**
      * Subtype to tag an item representing priority.
+     * Expected to be on an item of format {@link SliceItem#FORMAT_INT}.
      */
     public static final String SUBTYPE_PRIORITY = "priority";
     /**
      * Subtype to tag an item to use as a content description.
+     * Expected to be on an item of format {@link SliceItem#FORMAT_TEXT}.
      */
     public static final String SUBTYPE_CONTENT_DESCRIPTION = "content_description";
 
@@ -305,14 +337,24 @@
         private SliceSpec mSpec;
 
         /**
-         * Create a builder which will construct a {@link Slice} for the Given Uri.
-         * @param uri Uri to tag for this slice.
+         * @deprecated TO BE REMOVED
          */
+        @Deprecated
         public Builder(@NonNull Uri uri) {
             mUri = uri;
         }
 
         /**
+         * Create a builder which will construct a {@link Slice} for the given Uri.
+         * @param uri Uri to tag for this slice.
+         * @param spec the spec for this slice.
+         */
+        public Builder(@NonNull Uri uri, SliceSpec spec) {
+            mUri = uri;
+            mSpec = spec;
+        }
+
+        /**
          * Create a builder for a {@link Slice} that is a sub-slice of the slice
          * being constructed by the provided builder.
          * @param parent The builder constructing the parent slice
@@ -340,20 +382,13 @@
         /**
          * Add hints to the Slice being constructed
          */
-        public Builder addHints(@SliceHint String... hints) {
-            mHints.addAll(Arrays.asList(hints));
+        public Builder addHints(@SliceHint List<String> hints) {
+            mHints.addAll(hints);
             return this;
         }
 
         /**
-         * Add hints to the Slice being constructed
-         */
-        public Builder addHints(@SliceHint List<String> hints) {
-            return addHints(hints.toArray(new String[hints.size()]));
-        }
-
-        /**
-         * Add the spec for this slice.
+         * @deprecated TO BE REMOVED
          */
         public Builder setSpec(SliceSpec spec) {
             mSpec = spec;
@@ -362,17 +397,10 @@
 
         /**
          * Add a sub-slice to the slice being constructed
-         */
-        public Builder addSubSlice(@NonNull Slice slice) {
-            return addSubSlice(slice, null);
-        }
-
-        /**
-         * Add a sub-slice to the slice being constructed
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
-        public Builder addSubSlice(@NonNull Slice slice, @Nullable String subType) {
+        public Builder addSubSlice(@NonNull Slice slice, @Nullable @SliceSubtype String subType) {
             mItems.add(new SliceItem(slice, SliceItem.FORMAT_SLICE, subType,
                     slice.getHints().toArray(new String[slice.getHints().size()])));
             return this;
@@ -380,18 +408,11 @@
 
         /**
          * Add an action to the slice being constructed
-         */
-        public Slice.Builder addAction(@NonNull PendingIntent action, @NonNull Slice s) {
-            return addAction(action, s, null);
-        }
-
-        /**
-         * Add an action to the slice being constructed
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
         public Slice.Builder addAction(@NonNull PendingIntent action, @NonNull Slice s,
-                @Nullable String subType) {
+                @Nullable @SliceSubtype String subType) {
             List<String> hints = s.getHints();
             s.mSpec = null;
             mItems.add(new SliceItem(action, s, SliceItem.FORMAT_ACTION, subType, hints.toArray(
@@ -404,58 +425,31 @@
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
-        public Builder addText(CharSequence text, @Nullable String subType,
-                @SliceHint String... hints) {
+        public Builder addText(CharSequence text, @Nullable @SliceSubtype String subType,
+                @SliceHint List<String> hints) {
             mItems.add(new SliceItem(text, SliceItem.FORMAT_TEXT, subType, hints));
             return this;
         }
 
         /**
-         * Add text to the slice being constructed
-         * @param subType Optional template-specific type information
-         * @see {@link SliceItem#getSubType()}
-         */
-        public Builder addText(CharSequence text, @Nullable String subType,
-                @SliceHint List<String> hints) {
-            return addText(text, subType, hints.toArray(new String[hints.size()]));
-        }
-
-        /**
          * Add an image to the slice being constructed
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
-        public Builder addIcon(Icon icon, @Nullable String subType, @SliceHint String... hints) {
+        public Builder addIcon(Icon icon, @Nullable @SliceSubtype String subType,
+                @SliceHint List<String> hints) {
             mItems.add(new SliceItem(icon, SliceItem.FORMAT_IMAGE, subType, hints));
             return this;
         }
 
         /**
-         * Add an image to the slice being constructed
-         * @param subType Optional template-specific type information
-         * @see {@link SliceItem#getSubType()}
-         */
-        public Builder addIcon(Icon icon, @Nullable String subType, @SliceHint List<String> hints) {
-            return addIcon(icon, subType, hints.toArray(new String[hints.size()]));
-        }
-
-        /**
          * Add remote input to the slice being constructed
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
-        public Slice.Builder addRemoteInput(RemoteInput remoteInput, @Nullable String subType,
+        public Slice.Builder addRemoteInput(RemoteInput remoteInput,
+                @Nullable @SliceSubtype String subType,
                 @SliceHint List<String> hints) {
-            return addRemoteInput(remoteInput, subType, hints.toArray(new String[hints.size()]));
-        }
-
-        /**
-         * Add remote input to the slice being constructed
-         * @param subType Optional template-specific type information
-         * @see {@link SliceItem#getSubType()}
-         */
-        public Slice.Builder addRemoteInput(RemoteInput remoteInput, @Nullable String subType,
-                @SliceHint String... hints) {
             mItems.add(new SliceItem(remoteInput, SliceItem.FORMAT_REMOTE_INPUT,
                     subType, hints));
             return this;
@@ -466,70 +460,48 @@
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
-        public Builder addInt(int value, @Nullable String subType, @SliceHint String... hints) {
+        public Builder addInt(int value, @Nullable @SliceSubtype String subType,
+                @SliceHint List<String> hints) {
             mItems.add(new SliceItem(value, SliceItem.FORMAT_INT, subType, hints));
             return this;
         }
 
         /**
-         * Add an integer to the slice being constructed
-         * @param subType Optional template-specific type information
-         * @see {@link SliceItem#getSubType()}
+         * @deprecated TO BE REMOVED.
          */
-        public Builder addInt(int value, @Nullable String subType,
+        @Deprecated
+        public Slice.Builder addTimestamp(long time, @Nullable @SliceSubtype String subType,
                 @SliceHint List<String> hints) {
-            return addInt(value, subType, hints.toArray(new String[hints.size()]));
+            return addLong(time, subType, hints);
         }
 
         /**
-         * Add a timestamp to the slice being constructed
+         * Add a long to the slice being constructed
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
-        public Slice.Builder addTimestamp(long time, @Nullable String subType,
-                @SliceHint String... hints) {
-            mItems.add(new SliceItem(time, SliceItem.FORMAT_TIMESTAMP, subType,
-                    hints));
+        public Slice.Builder addLong(long value, @Nullable @SliceSubtype String subType,
+                @SliceHint List<String> hints) {
+            mItems.add(new SliceItem(value, SliceItem.FORMAT_LONG, subType,
+                    hints.toArray(new String[hints.size()])));
             return this;
         }
 
         /**
-         * Add a timestamp to the slice being constructed
-         * @param subType Optional template-specific type information
-         * @see {@link SliceItem#getSubType()}
-         */
-        public Slice.Builder addTimestamp(long time, @Nullable String subType,
-                @SliceHint List<String> hints) {
-            return addTimestamp(time, subType, hints.toArray(new String[hints.size()]));
-        }
-
-        /**
          * Add a bundle to the slice being constructed.
          * <p>Expected to be used for support library extension, should not be used for general
          * development
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
-        public Slice.Builder addBundle(Bundle bundle, @Nullable String subType,
-                @SliceHint String... hints) {
+        public Slice.Builder addBundle(Bundle bundle, @Nullable @SliceSubtype String subType,
+                @SliceHint List<String> hints) {
             mItems.add(new SliceItem(bundle, SliceItem.FORMAT_BUNDLE, subType,
                     hints));
             return this;
         }
 
         /**
-         * Add a bundle to the slice being constructed.
-         * <p>Expected to be used for support library extension, should not be used for general
-         * development
-         * @param subType Optional template-specific type information
-         * @see {@link SliceItem#getSubType()}
-         */
-        public Slice.Builder addBundle(Bundle bundle, @Nullable String subType,
-                @SliceHint List<String> hints) {
-            return addBundle(bundle, subType, hints.toArray(new String[hints.size()]));
-        }
-
-        /**
          * Construct the slice.
          */
         public Slice build() {
diff --git a/core/java/android/app/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java
index 9eb2bb8..019ae49 100644
--- a/core/java/android/app/slice/SliceItem.java
+++ b/core/java/android/app/slice/SliceItem.java
@@ -67,7 +67,7 @@
             FORMAT_IMAGE,
             FORMAT_ACTION,
             FORMAT_INT,
-            FORMAT_TIMESTAMP,
+            FORMAT_LONG,
             FORMAT_REMOTE_INPUT,
             FORMAT_BUNDLE,
     })
@@ -98,9 +98,14 @@
      */
     public static final String FORMAT_INT = "int";
     /**
-     * A {@link SliceItem} that contains a timestamp.
+     * A {@link SliceItem} that contains a long.
      */
-    public static final String FORMAT_TIMESTAMP = "timestamp";
+    public static final String FORMAT_LONG = "long";
+    /**
+     * @deprecated TO BE REMOVED
+     */
+    @Deprecated
+    public static final String FORMAT_TIMESTAMP = FORMAT_LONG;
     /**
      * A {@link SliceItem} that contains a {@link RemoteInput}.
      */
@@ -123,6 +128,14 @@
      * @hide
      */
     public SliceItem(Object obj, @SliceType String format, String subType,
+            List<String> hints) {
+        this(obj, format, subType, hints.toArray(new String[hints.size()]));
+    }
+
+    /**
+     * @hide
+     */
+    public SliceItem(Object obj, @SliceType String format, String subType,
             @Slice.SliceHint String[] hints) {
         mHints = hints;
         mFormat = format;
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index aa2cf46..dd89293 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -41,6 +41,7 @@
 import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -430,9 +431,11 @@
         return new Slice.Builder(sliceUri)
                 .addAction(createPermissionIntent(context, sliceUri, callingPackage),
                         new Slice.Builder(sliceUri.buildUpon().appendPath("permission").build())
-                                .addText(getPermissionString(context, callingPackage), null)
-                                .build())
-                .addHints(Slice.HINT_LIST_ITEM)
+                                .addText(getPermissionString(context, callingPackage), null,
+                                        Collections.emptyList())
+                                .build(),
+                        null)
+                .addHints(Arrays.asList(Slice.HINT_LIST_ITEM))
                 .build();
     }
 
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index ce7d3af..440103a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -2464,8 +2464,9 @@
      * @param account the account to specify in the sync
      * @param authority the provider to specify in the sync request
      * @param extras extra parameters to go along with the sync request
-     * @param pollFrequency how frequently the sync should be performed, in seconds. A minimum value
-     *                      of 1 hour is enforced.
+     * @param pollFrequency how frequently the sync should be performed, in seconds.
+     * On Android API level 24 and above, a minmam interval of 15 minutes is enforced.
+     * On previous versions, the minimum interval is 1 hour.
      * @throws IllegalArgumentException if an illegal extra was set or if any of the parameters
      * are null.
      */
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 2a791ec..316c796 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -293,9 +293,7 @@
                     (mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0;
             // Use compatibility WAL unless an app explicitly set journal/synchronous mode
             // or DISABLE_COMPATIBILITY_WAL flag is set
-            final boolean useCompatibilityWal = mConfiguration.journalMode == null
-                    && mConfiguration.syncMode == null
-                    && (mConfiguration.openFlags & SQLiteDatabase.DISABLE_COMPATIBILITY_WAL) == 0;
+            final boolean useCompatibilityWal = mConfiguration.useCompatibilityWal();
             if (walEnabled || useCompatibilityWal) {
                 setJournalMode("WAL");
                 if (useCompatibilityWal && SQLiteCompatibilityWalFlags.areFlagsSet()) {
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index dadb95b..e519302 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -23,6 +23,7 @@
 import android.os.Message;
 import android.os.OperationCanceledException;
 import android.os.SystemClock;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.PrefixPrinter;
 import android.util.Printer;
@@ -1111,6 +1112,11 @@
             printer.println("  Open: " + mIsOpen);
             printer.println("  Max connections: " + mMaxConnectionPoolSize);
             printer.println("  Total execution time: " + mTotalExecutionTimeCounter);
+            printer.println("  Configuration: openFlags=" + mConfiguration.openFlags
+                    + ", useCompatibilityWal=" + mConfiguration.useCompatibilityWal()
+                    + ", journalMode=" + TextUtils.emptyIfNull(mConfiguration.journalMode)
+                    + ", syncMode=" + TextUtils.emptyIfNull(mConfiguration.syncMode));
+
             if (SQLiteCompatibilityWalFlags.areFlagsSet()) {
                 printer.println("  Compatibility WAL settings: compatibility_wal_supported="
                         + SQLiteCompatibilityWalFlags
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index 275043f..8b9dfcf 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -194,6 +194,11 @@
         return path.equalsIgnoreCase(MEMORY_DB_PATH);
     }
 
+    boolean useCompatibilityWal() {
+        return journalMode == null && syncMode == null
+                && (openFlags & SQLiteDatabase.DISABLE_COMPATIBILITY_WAL) == 0;
+    }
+
     private static String stripPathForLogs(String path) {
         if (path.indexOf('@') == -1) {
             return path;
diff --git a/core/java/android/hardware/location/IFusedLocationHardware.aidl b/core/java/android/hardware/location/IFusedLocationHardware.aidl
deleted file mode 100644
index 2ea4d23..0000000
--- a/core/java/android/hardware/location/IFusedLocationHardware.aidl
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2013, 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/license/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.hardware.location;
-
-import android.hardware.location.IFusedLocationHardwareSink;
-import android.location.FusedBatchOptions;
-
-/**
- * Fused Location hardware interface.
- * This interface is the basic set of supported functionality by Fused Hardware
- * modules that offer Location batching capabilities.
- *
- * @hide
- */
-interface IFusedLocationHardware {
-    /**
-     * Registers a sink with the Location Hardware object.
-     *
-     * @param eventSink     The sink to register.
-     */
-    void registerSink(in IFusedLocationHardwareSink eventSink) = 0;
-
-    /**
-     * Unregisters a sink with the Location Hardware object.
-     *
-     * @param eventSink     The sink to unregister.
-     */
-    void unregisterSink(in IFusedLocationHardwareSink eventSink) = 1;
-
-    /**
-     * Provides access to the batch size available in Hardware.
-     *
-     * @return The batch size the hardware supports.
-     */
-    int getSupportedBatchSize() = 2;
-
-    /**
-     * Requests the Hardware to start batching locations.
-     *
-     * @param id            An Id associated with the request.
-     * @param batchOptions  The options required for batching.
-     *
-     * @throws RuntimeException if the request Id exists.
-     */
-    void startBatching(in int id, in FusedBatchOptions batchOptions) = 3;
-
-    /**
-     * Requests the Hardware to stop batching for the given Id.
-     *
-     * @param id    The request that needs to be stopped.
-     * @throws RuntimeException if the request Id is unknown.
-     */
-    void stopBatching(in int id) = 4;
-
-    /**
-     * Updates a batching operation in progress.
-     *
-     * @param id                The Id of the operation to update.
-     * @param batchOptions     The options to apply to the given operation.
-     *
-     * @throws RuntimeException if the Id of the request is unknown.
-     */
-    void updateBatchingOptions(in int id, in FusedBatchOptions batchOptions) = 5;
-
-    /**
-     * Requests the most recent locations available in Hardware.
-     * This operation does not dequeue the locations, so still other batching
-     * events will continue working.
-     *
-     * @param batchSizeRequested    The number of locations requested.
-     */
-    void requestBatchOfLocations(in int batchSizeRequested) = 6;
-
-    /**
-     * Flags if the Hardware supports injection of diagnostic data.
-     *
-     * @return True if data injection is supported, false otherwise.
-     */
-    boolean supportsDiagnosticDataInjection() = 7;
-
-    /**
-     * Injects diagnostic data into the Hardware subsystem.
-     *
-     * @param data  The data to inject.
-     * @throws RuntimeException if injection is not supported.
-     */
-    void injectDiagnosticData(in String data) = 8;
-
-    /**
-     * Flags if the Hardware supports injection of device context information.
-     *
-     * @return True if device context injection is supported, false otherwise.
-     */
-    boolean supportsDeviceContextInjection() = 9;
-
-    /**
-     * Injects device context information into the Hardware subsystem.
-     *
-     * @param deviceEnabledContext  The context to inject.
-     * @throws RuntimeException if injection is not supported.
-     */
-    void injectDeviceContext(in int deviceEnabledContext) = 10;
-
-    /**
-     * Requests all batched locations currently available in Hardware
-     * and clears the buffer.  Any subsequent calls will not return any
-     * of the locations returned in this call.
-     */
-    void flushBatchedLocations() = 11;
-
-    /**
-     * Returns the version of this FLP HAL implementation.
-     */
-    int getVersion() = 12;
-}
diff --git a/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl b/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
deleted file mode 100644
index a7dd035..0000000
--- a/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2013, 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/license/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.hardware.location;
-
-import android.location.Location;
-
-/**
- * Fused Location hardware event sink interface.
- * This interface defines the set of events that the FusedLocationHardware provides.
- *
- * @hide
- */
-oneway interface IFusedLocationHardwareSink {
-    /**
-     * Event generated when a batch of location information is available.
-     *
-     * @param locations     The batch of location information available.
-     */
-    void onLocationAvailable(in Location[] locations) = 0;
-
-    /**
-     * Event generated from FLP HAL to provide diagnostic data to the platform.
-     *
-     * @param data      The diagnostic data provided by FLP HAL.
-     */
-    void onDiagnosticDataAvailable(in String data) = 1;
-
-    /**
-     * Event generated from FLP HAL to provide a mask of supported
-     * capabilities.  Should be called immediatly after init.
-     */
-    void onCapabilities(int capabilities) = 2;
-
-    /**
-     * Event generated from FLP HAL when the status of location batching
-     * changes (location is successful/unsuccessful).
-     */
-    void onStatusChanged(int status) = 3;
-}
diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl
index 3ce0283..3a3ddcc 100644
--- a/core/java/android/net/IIpSecService.aidl
+++ b/core/java/android/net/IIpSecService.aidl
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.net.LinkAddress;
 import android.net.Network;
 import android.net.IpSecConfig;
 import android.net.IpSecUdpEncapResponse;
@@ -48,11 +49,11 @@
 
     void addAddressToTunnelInterface(
             int tunnelResourceId,
-            String localAddr);
+            in LinkAddress localAddr);
 
     void removeAddressFromTunnelInterface(
             int tunnelResourceId,
-            String localAddr);
+            in LinkAddress localAddr);
 
     void deleteTunnelInterface(int resourceId);
 
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index c69a4d4..57f0588 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -38,6 +38,13 @@
     private static final String TAG = "IpSecAlgorithm";
 
     /**
+     * Null cipher.
+     *
+     * @hide
+     */
+    public static final String CRYPT_NULL = "ecb(cipher_null)";
+
+    /**
      * AES-CBC Encryption/Ciphering Algorithm.
      *
      * <p>Valid lengths for this key are {128, 192, 256}.
@@ -122,7 +129,7 @@
      * @param algorithm name of the algorithm.
      * @param key key padded to a multiple of 8 bits.
      */
-    public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key) {
+    public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) {
         this(algorithm, key, key.length * 8);
     }
 
@@ -137,7 +144,8 @@
      * @param key key padded to a multiple of 8 bits.
      * @param truncLenBits number of bits of output hash to use.
      */
-    public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
+    public IpSecAlgorithm(
+            @NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
         mName = algorithm;
         mKey = key.clone();
         mTruncLenBits = truncLenBits;
@@ -145,11 +153,13 @@
     }
 
     /** Get the algorithm name */
+    @NonNull
     public String getName() {
         return mName;
     }
 
     /** Get the key for this algorithm */
+    @NonNull
     public byte[] getKey() {
         return mKey.clone();
     }
@@ -263,6 +273,7 @@
     }
 
     @Override
+    @NonNull
     public String toString() {
         return new StringBuilder()
                 .append("{mName=")
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index fbf3056..4157845 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -253,8 +253,9 @@
      * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
      *     currently allocated for this user
      */
-    public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress)
-            throws ResourceUnavailableException {
+    @NonNull
+    public SecurityParameterIndex allocateSecurityParameterIndex(
+                @NonNull InetAddress destinationAddress) throws ResourceUnavailableException {
         try {
             return new SecurityParameterIndex(
                     mService,
@@ -280,8 +281,9 @@
      * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be
      *     reserved
      */
+    @NonNull
     public SecurityParameterIndex allocateSecurityParameterIndex(
-            InetAddress destinationAddress, int requestedSpi)
+            @NonNull InetAddress destinationAddress, int requestedSpi)
             throws SpiUnavailableException, ResourceUnavailableException {
         if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
             throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
@@ -318,9 +320,8 @@
      * @param transform a transport mode {@code IpSecTransform}
      * @throws IOException indicating that the transform could not be applied
      */
-    public void applyTransportModeTransform(
-            Socket socket, @PolicyDirection int direction, IpSecTransform transform)
-            throws IOException {
+    public void applyTransportModeTransform(@NonNull Socket socket,
+            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
         applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
     }
 
@@ -353,9 +354,8 @@
      * @param transform a transport mode {@code IpSecTransform}
      * @throws IOException indicating that the transform could not be applied
      */
-    public void applyTransportModeTransform(
-            DatagramSocket socket, @PolicyDirection int direction, IpSecTransform transform)
-            throws IOException {
+    public void applyTransportModeTransform(@NonNull DatagramSocket socket,
+            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
         applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
     }
 
@@ -388,9 +388,8 @@
      * @param transform a transport mode {@code IpSecTransform}
      * @throws IOException indicating that the transform could not be applied
      */
-    public void applyTransportModeTransform(
-            FileDescriptor socket, @PolicyDirection int direction, IpSecTransform transform)
-            throws IOException {
+    public void applyTransportModeTransform(@NonNull FileDescriptor socket,
+            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
         // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
         // constructor takes control and closes the user's FD when we exit the method.
         try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
@@ -413,8 +412,7 @@
      * @param socket a socket that previously had a transform applied to it
      * @throws IOException indicating that the transform could not be removed from the socket
      */
-    public void removeTransportModeTransforms(Socket socket)
-            throws IOException {
+    public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException {
         removeTransportModeTransforms(socket.getFileDescriptor$());
     }
 
@@ -431,8 +429,7 @@
      * @param socket a socket that previously had a transform applied to it
      * @throws IOException indicating that the transform could not be removed from the socket
      */
-    public void removeTransportModeTransforms(DatagramSocket socket)
-            throws IOException {
+    public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException {
         removeTransportModeTransforms(socket.getFileDescriptor$());
     }
 
@@ -449,8 +446,7 @@
      * @param socket a socket that previously had a transform applied to it
      * @throws IOException indicating that the transform could not be removed from the socket
      */
-    public void removeTransportModeTransforms(FileDescriptor socket)
-            throws IOException {
+    public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException {
         try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
             mService.removeTransportModeTransforms(pfd);
         } catch (RemoteException e) {
@@ -588,6 +584,7 @@
     // safely usable for Encapsulation without allowing a user to possibly unbind from/close
     // the port, which could potentially impact the traffic of the next user who binds to that
     // socket.
+    @NonNull
     public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
             throws IOException, ResourceUnavailableException {
         /*
@@ -617,6 +614,7 @@
     // safely usable for Encapsulation without allowing a user to possibly unbind from/close
     // the port, which could potentially impact the traffic of the next user who binds to that
     // socket.
+    @NonNull
     public UdpEncapsulationSocket openUdpEncapsulationSocket()
             throws IOException, ResourceUnavailableException {
         return new UdpEncapsulationSocket(mService, 0);
@@ -645,6 +643,7 @@
         private int mResourceId = INVALID_RESOURCE_ID;
 
         /** Get the underlying SPI held by this object. */
+        @NonNull
         public String getInterfaceName() {
             return mInterfaceName;
         }
@@ -656,10 +655,15 @@
          * tunneled traffic.
          *
          * @param address the local address for traffic inside the tunnel
-         * @throws IOException if the address could not be added
          * @hide
          */
-        public void addAddress(LinkAddress address) throws IOException {
+        @SystemApi
+        public void addAddress(@NonNull LinkAddress address) throws IOException {
+            try {
+                mService.addAddressToTunnelInterface(mResourceId, address);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         }
 
         /**
@@ -668,10 +672,15 @@
          * <p>Remove an address which was previously added to the IpSecTunnelInterface
          *
          * @param address to be removed
-         * @throws IOException if the address could not be removed
          * @hide
          */
-        public void removeAddress(LinkAddress address) throws IOException {
+        @SystemApi
+        public void removeAddress(@NonNull LinkAddress address) throws IOException {
+            try {
+                mService.removeAddressFromTunnelInterface(mResourceId, address);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         }
 
         private IpSecTunnelInterface(@NonNull IIpSecService service,
@@ -758,6 +767,7 @@
      * @hide
      */
     @SystemApi
+    @NonNull
     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
     public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
             @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
@@ -784,8 +794,8 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
-    public void applyTunnelModeTransform(IpSecTunnelInterface tunnel,
-            @PolicyDirection int direction, IpSecTransform transform) throws IOException {
+    public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel,
+            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
         try {
             mService.applyTunnelModeTransform(
                     tunnel.getResourceId(), direction, transform.getResourceId());
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 60e96f9..cf58647 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -350,6 +350,7 @@
          *
          * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
          */
+        @NonNull
         public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
             // TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
             Preconditions.checkNotNull(algo);
@@ -364,6 +365,7 @@
          *
          * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
          */
+        @NonNull
         public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
             // TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
             Preconditions.checkNotNull(algo);
@@ -384,6 +386,7 @@
          * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
          *     be applied.
          */
+        @NonNull
         public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
             Preconditions.checkNotNull(algo);
             mConfig.setAuthenticatedEncryption(algo);
@@ -403,6 +406,7 @@
          * @param remotePort the UDP port number of the remote host that will send and receive
          *     encapsulated traffic. In the case of IKEv2, this should be port 4500.
          */
+        @NonNull
         public IpSecTransform.Builder setIpv4Encapsulation(
                 @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
             Preconditions.checkNotNull(localSocket);
@@ -436,6 +440,7 @@
          *     collides with an existing transform
          * @throws IOException indicating other errors
          */
+        @NonNull
         public IpSecTransform buildTransportModeTransform(
                 @NonNull InetAddress sourceAddress,
                 @NonNull IpSecManager.SecurityParameterIndex spi)
@@ -472,6 +477,7 @@
          * @hide
          */
         @SystemApi
+        @NonNull
         @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
         public IpSecTransform buildTunnelModeTransform(
                 @NonNull InetAddress sourceAddress,
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 44bd35a..0ae5394 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -23,6 +23,7 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 
+import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
@@ -712,6 +713,8 @@
     // Entry point from android_util_Binder.cpp's onTransact
     private boolean execTransact(int code, long dataObj, long replyObj,
             int flags) {
+        BinderCallsStats binderCallsStats = BinderCallsStats.getInstance();
+        BinderCallsStats.CallSession callSession = binderCallsStats.callStarted(this, code);
         Parcel data = Parcel.obtain(dataObj);
         Parcel reply = Parcel.obtain(replyObj);
         // theoretically, we should call transact, which will call onTransact,
@@ -756,6 +759,7 @@
         // to the main transaction loop to wait for another incoming transaction.  Either
         // way, strict mode begone!
         StrictMode.clearGatheredViolations();
+        binderCallsStats.callEnded(callSession);
 
         return res;
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b9aad11..87babc0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7762,6 +7762,22 @@
         public static final String BLUETOOTH_ON_WHILE_DRIVING = "bluetooth_on_while_driving";
 
         /**
+         * The number of times (integer) the user has manually enabled battery saver.
+         * @hide
+         */
+        public static final String LOW_POWER_MANUAL_ACTIVATION_COUNT =
+                "low_power_manual_activation_count";
+
+        /**
+         * Whether the "first time battery saver warning" dialog needs to be shown (0: default)
+         * or not (1).
+         *
+         * @hide
+         */
+        public static final String LOW_POWER_WARNING_ACKNOWLEDGED =
+                "low_power_warning_acknowledged";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -9634,6 +9650,21 @@
         public static final String WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED =
                 "wifi_connected_mac_randomization_enabled";
 
+        /**
+         * Parameters to adjust the performance of framework wifi scoring methods.
+         * <p>
+         * Encoded as a comma-separated key=value list, for example:
+         *   "rssi5=-80:-77:-70:-57,rssi2=-83:-80:-73:-60,horizon=15"
+         * This is intended for experimenting with new parameter values,
+         * and is normally unset or empty. The example does not include all
+         * parameters that may be honored.
+         * Default values are provided by code or device configurations.
+         * Errors in the parameters will cause the entire setting to be ignored.
+         * @hide
+         */
+        public static final String WIFI_SCORE_PARAMS =
+                "wifi_score_params";
+
        /**
         * The maximum number of times we will retry a connection to an access
         * point for which we have failed in acquiring an IP address from DHCP.
@@ -11594,8 +11625,8 @@
          */
         @SystemApi
         @TestApi
-        public static final String AUTOFILL_COMPAT_ALLOWED_PACKAGES =
-                "autofill_compat_allowed_packages";
+        public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES =
+                "autofill_compat_mode_allowed_packages";
 
         /**
          * Exemptions to the hidden API blacklist.
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index 10c1c9e..503387a 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -35,6 +35,7 @@
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertPath;
 import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -578,7 +579,7 @@
             if (grantAlias == null) {
                 throw new InternalRecoveryServiceException("Null grant alias");
             }
-            return getKeyFromGrant(alias);
+            return getKeyFromGrant(grantAlias);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (UnrecoverableKeyException e) {
@@ -654,6 +655,11 @@
         return RecoverySession.newInstance(this);
     }
 
+    @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
+    public Map<String, X509Certificate> getRootCertificates() {
+        return TrustedRootCertificates.getRootCertificates();
+    }
+
     InternalRecoveryServiceException wrapUnexpectedServiceSpecificException(
             ServiceSpecificException e) {
         if (e.errorCode == ERROR_SERVICE_INTERNAL_ERROR) {
diff --git a/core/java/android/security/keystore/recovery/RecoverySession.java b/core/java/android/security/keystore/recovery/RecoverySession.java
index 744bfa3..208b9b2 100644
--- a/core/java/android/security/keystore/recovery/RecoverySession.java
+++ b/core/java/android/security/keystore/recovery/RecoverySession.java
@@ -77,7 +77,7 @@
     }
 
     /**
-     * @deprecated Use {@link #start(CertPath, byte[], byte[], List)} instead.
+     * @deprecated Use {@link #start(String, CertPath, byte[], byte[], List)} instead.
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
@@ -108,25 +108,9 @@
     }
 
     /**
-     * Starts a recovery session and returns a blob with proof of recovery secret possession.
-     * The method generates a symmetric key for a session, which trusted remote device can use to
-     * return recovery key.
-     *
-     * @param verifierCertPath The certificate path used to create the recovery blob on the source
-     *     device. Keystore will verify the certificate path by using the root of trust.
-     * @param vaultParams Must match the parameters in the corresponding field in the recovery blob.
-     *     Used to limit number of guesses.
-     * @param vaultChallenge Data passed from server for this recovery session and used to prevent
-     *     replay attacks.
-     * @param secrets Secrets provided by user, the method only uses type and secret fields.
-     * @return The recovery claim. Claim provides a b binary blob with recovery claim. It is
-     *     encrypted with verifierPublicKey and contains a proof of user secrets, session symmetric
-     *     key and parameters necessary to identify the counter with the number of failed recovery
-     *     attempts.
-     * @throws CertificateException if the {@code verifierCertPath} is invalid.
-     * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
-     *     service.
+     * @deprecated Use {@link #start(String, CertPath, byte[], byte[], List)} instead.
      */
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
     @NonNull public byte[] start(
             @NonNull CertPath verifierCertPath,
@@ -179,8 +163,6 @@
      * @throws CertificateException if the {@code verifierCertPath} is invalid.
      * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
      *     service.
-     *
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
     @NonNull public byte[] start(
@@ -215,17 +197,9 @@
     }
 
     /**
-     * Imports keys.
-     *
-     * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session.
-     * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob
-     *     and session. KeyStore only uses package names from the application info in {@link
-     *     WrappedApplicationKey}. Caller is responsibility to perform certificates check.
-     * @return Map from alias to raw key material.
-     * @throws SessionExpiredException if {@code session} has since been closed.
-     * @throws DecryptionFailedException if unable to decrypt the snapshot.
-     * @throws InternalRecoveryServiceException if an error occurs internal to the recovery service.
+     * @deprecated Use {@link #recoverKeyChainSnapshot(byte[], List)} instead.
      */
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
     public Map<String, byte[]> recoverKeys(
             @NonNull byte[] recoveryKeyBlob,
@@ -257,8 +231,6 @@
      * @throws SessionExpiredException if {@code session} has since been closed.
      * @throws DecryptionFailedException if unable to decrypt the snapshot.
      * @throws InternalRecoveryServiceException if an error occurs internal to the recovery service.
-     *
-     * @hide
      */
     @RequiresPermission(Manifest.permission.RECOVER_KEYSTORE)
     public Map<String, Key> recoverKeyChainSnapshot(
diff --git a/core/java/android/security/keystore/recovery/TrustedRootCertificates.java b/core/java/android/security/keystore/recovery/TrustedRootCertificates.java
index 4bdde8a..a65b40f 100644
--- a/core/java/android/security/keystore/recovery/TrustedRootCertificates.java
+++ b/core/java/android/security/keystore/recovery/TrustedRootCertificates.java
@@ -32,7 +32,7 @@
  *
  * @hide
  */
-public class TrustedRootCertificates {
+public final class TrustedRootCertificates {
 
     public static final String GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_ALIAS =
             "GoogleCloudKeyVaultServiceV1";
@@ -83,7 +83,7 @@
     /**
      * Returns all available root certificates, keyed by alias.
      */
-    public static Map<String, X509Certificate> listRootCertificates() {
+    public static Map<String, X509Certificate> getRootCertificates() {
         return new ArrayMap(ALL_ROOT_CERTIFICATES);
     }
 
@@ -114,4 +114,7 @@
             throw new RuntimeException(e);
         }
     }
+
+    // Statics only
+    private TrustedRootCertificates() {}
 }
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 41e4181..0f7cea2 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -518,7 +518,7 @@
  *     &lt;intent-filter&gt;
  *         &lt;action android:name="android.service.autofill.AutofillService" /&gt;
  *     &lt;/intent-filter&gt;
- *     &lt;meta-data android:name="android.autofillservice" android:resource="@xml/autofillservice" /&gt;
+ *     &lt;meta-data android:name="android.autofill" android:resource="@xml/autofillservice" /&gt;
  * &lt;/service&gt;</pre>
  *
  * <P>In the XML file you can specify one or more packages for which to enable compatibility
diff --git a/core/java/android/service/autofill/AutofillServiceHelper.java b/core/java/android/service/autofill/AutofillServiceHelper.java
new file mode 100644
index 0000000..bbaebff
--- /dev/null
+++ b/core/java/android/service/autofill/AutofillServiceHelper.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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.service.autofill;
+
+import android.annotation.Nullable;
+import android.view.autofill.AutofillId;
+
+import com.android.internal.util.Preconditions;
+
+/** @hide */
+final class AutofillServiceHelper {
+
+    static AutofillId[] assertValid(@Nullable AutofillId[] ids) {
+        Preconditions.checkArgument(ids != null && ids.length > 0, "must have at least one id");
+        return Preconditions.checkArrayElementsNotNull(ids, "ids");
+    }
+
+    private AutofillServiceHelper() {
+        throw new UnsupportedOperationException("contains static members only");
+    }
+}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 3a4b6bb..be84ba9 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -16,6 +16,7 @@
 
 package android.service.autofill;
 
+import static android.service.autofill.AutofillServiceHelper.assertValid;
 import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
 import static android.view.autofill.Helper.sDebug;
 
@@ -245,10 +246,15 @@
          * @param ids id of Views that when focused will display the authentication UI.
          *
          * @return This builder.
-
-         * @throws IllegalArgumentException if {@code ids} is {@code null} or empty, or if
-         * both {@code authentication} and {@code presentation} are {@code null}, or if
-         * both {@code authentication} and {@code presentation} are non-{@code null}
+         *
+         * @throws IllegalArgumentException if any of the following occurs:
+         * <ul>
+         *   <li>{@code ids} is {@code null}</li>
+         *   <li>{@code ids} is empty</li>
+         *   <li>{@code ids} contains a {@code null} element</li>
+         *   <li>both {@code authentication} and {@code presentation} are {@code null}</li>
+         *   <li>both {@code authentication} and {@code presentation} are non-{@code null}</li>
+         * </ul>
          *
          * @throws IllegalStateException if a {@link #setHeader(RemoteViews) header} or a
          * {@link #setFooter(RemoteViews) footer} are already set for this builder.
@@ -263,16 +269,13 @@
                 throw new IllegalStateException("Already called #setHeader() or #setFooter()");
             }
 
-            if (ids == null || ids.length == 0) {
-                throw new IllegalArgumentException("ids cannot be null or empry");
-            }
             if (authentication == null ^ presentation == null) {
                 throw new IllegalArgumentException("authentication and presentation"
                         + " must be both non-null or null");
             }
             mAuthentication = authentication;
             mPresentation = presentation;
-            mAuthenticationIds = ids;
+            mAuthenticationIds = assertValid(ids);
             return this;
         }
 
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index a5a6177..1be1be6 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -16,6 +16,7 @@
 
 package android.service.autofill;
 
+import static android.service.autofill.AutofillServiceHelper.assertValid;
 import static android.view.autofill.Helper.sDebug;
 
 import android.annotation.IntDef;
@@ -405,17 +406,6 @@
             mRequiredIds = null;
         }
 
-        private AutofillId[] assertValid(AutofillId[] ids) {
-            Preconditions.checkArgument(ids != null && ids.length > 0,
-                    "must have at least one id: " + Arrays.toString(ids));
-            for (int i = 0; i < ids.length; i++) {
-                final AutofillId id = ids[i];
-                Preconditions.checkArgument(id != null,
-                        "cannot have null id: " + Arrays.toString(ids));
-            }
-            return ids;
-        }
-
         /**
          * Sets flags changing the save behavior.
          *
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 38ab6f2..9687009 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -42,7 +42,7 @@
         DEFAULT_FLAGS.put("settings_zone_picker_v2", "true");
         DEFAULT_FLAGS.put("settings_about_phone_v2", "true");
         DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
-        DEFAULT_FLAGS.put("settings_data_usage_v2", "false");
+        DEFAULT_FLAGS.put("settings_data_usage_v2", "true");
         DEFAULT_FLAGS.put("settings_audio_switcher", "false");
     }
 
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index a099820..89e6262 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -355,12 +355,10 @@
         final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(languages);
 
         ModelFile bestModel = null;
-        int bestModelVersion = -1;
         for (ModelFile model : listAllModelsLocked()) {
             if (model.isAnyLanguageSupported(languageRangeList)) {
-                if (model.getVersion() >= bestModelVersion) {
+                if (model.isPreferredTo(bestModel)) {
                     bestModel = model;
-                    bestModelVersion = model.getVersion();
                 }
             }
         }
@@ -482,6 +480,7 @@
         private final String mName;
         private final int mVersion;
         private final List<Locale> mSupportedLocales;
+        private final boolean mLanguageIndependent;
 
         /** Returns null if the path did not point to a compatible model. */
         static @Nullable ModelFile fromPath(String path) {
@@ -496,12 +495,14 @@
                     Log.d(DEFAULT_LOG_TAG, "Ignoring " + file.getAbsolutePath());
                     return null;
                 }
+                final boolean languageIndependent = supportedLocalesStr.equals("*");
                 final List<Locale> supportedLocales = new ArrayList<>();
                 for (String langTag : supportedLocalesStr.split(",")) {
                     supportedLocales.add(Locale.forLanguageTag(langTag));
                 }
                 closeAndLogError(modelFd);
-                return new ModelFile(path, file.getName(), version, supportedLocales);
+                return new ModelFile(path, file.getName(), version, supportedLocales,
+                                     languageIndependent);
             } catch (FileNotFoundException e) {
                 Log.e(DEFAULT_LOG_TAG, "Failed to peek " + file.getAbsolutePath(), e);
                 return null;
@@ -525,7 +526,7 @@
 
         /** Returns whether the language supports any language in the given ranges. */
         boolean isAnyLanguageSupported(List<Locale.LanguageRange> languageRanges) {
-            return Locale.lookup(languageRanges, mSupportedLocales) != null;
+            return mLanguageIndependent || Locale.lookup(languageRanges, mSupportedLocales) != null;
         }
 
         /** All locales supported by the model. */
@@ -533,6 +534,25 @@
             return Collections.unmodifiableList(mSupportedLocales);
         }
 
+        public boolean isPreferredTo(ModelFile model) {
+            // A model is preferred to no model.
+            if (model == null) {
+                return true;
+            }
+
+            // A language-specific model is preferred to a language independent
+            // model.
+            if (!mLanguageIndependent && model.mLanguageIndependent) {
+                return true;
+            }
+
+            // A higher-version model is preferred.
+            if (getVersion() > model.getVersion()) {
+                return true;
+            }
+            return false;
+        }
+
         @Override
         public boolean equals(Object other) {
             if (this == other) {
@@ -555,11 +575,13 @@
                     mPath, mName, mVersion, localesJoiner.toString());
         }
 
-        private ModelFile(String path, String name, int version, List<Locale> supportedLocales) {
+        private ModelFile(String path, String name, int version, List<Locale> supportedLocales,
+                          boolean languageIndependent) {
             mPath = path;
             mName = name;
             mVersion = version;
             mSupportedLocales = supportedLocales;
+            mLanguageIndependent = languageIndependent;
         }
     }
 
diff --git a/core/java/android/webkit/TracingConfig.java b/core/java/android/webkit/TracingConfig.java
index 68badec..d95ca61 100644
--- a/core/java/android/webkit/TracingConfig.java
+++ b/core/java/android/webkit/TracingConfig.java
@@ -35,9 +35,9 @@
     private @TracingMode int mTracingMode;
 
     /** @hide */
-    @IntDef(flag = true, value = {CATEGORIES_NONE, CATEGORIES_WEB_DEVELOPER,
-            CATEGORIES_INPUT_LATENCY, CATEGORIES_RENDERING, CATEGORIES_JAVASCRIPT_AND_RENDERING,
-            CATEGORIES_FRAME_VIEWER})
+    @IntDef(flag = true, value = {CATEGORIES_NONE, CATEGORIES_ALL, CATEGORIES_ANDROID_WEBVIEW,
+            CATEGORIES_WEB_DEVELOPER, CATEGORIES_INPUT_LATENCY, CATEGORIES_RENDERING,
+            CATEGORIES_JAVASCRIPT_AND_RENDERING, CATEGORIES_FRAME_VIEWER})
     @Retention(RetentionPolicy.SOURCE)
     public @interface PredefinedCategories {}
 
@@ -90,34 +90,28 @@
     public static final int CATEGORIES_FRAME_VIEWER = 1 << 6;
 
     /** @hide */
-    @IntDef({RECORD_UNTIL_FULL, RECORD_CONTINUOUSLY, RECORD_UNTIL_FULL_LARGE_BUFFER})
+    @IntDef({RECORD_UNTIL_FULL, RECORD_CONTINUOUSLY})
     @Retention(RetentionPolicy.SOURCE)
     public @interface TracingMode {}
 
     /**
-     * Record trace events until the internal tracing buffer is full. Default tracing mode.
-     * Typically the buffer memory usage is between {@link #RECORD_CONTINUOUSLY} and the
-     * {@link #RECORD_UNTIL_FULL_LARGE_BUFFER}. Depending on the implementation typically allows
-     * up to 256k events to be stored.
+     * Record trace events until the internal tracing buffer is full.
+     *
+     * Typically the buffer memory usage is larger than {@link #RECORD_CONTINUOUSLY}.
+     * Depending on the implementation typically allows up to 256k events to be stored.
      */
     public static final int RECORD_UNTIL_FULL = 0;
 
     /**
-     * Record trace events continuously using an internal ring buffer. Overwrites
-     * old events if they exceed buffer capacity. Uses less memory than both
-     * {@link #RECORD_UNTIL_FULL} and {@link #RECORD_UNTIL_FULL_LARGE_BUFFER} modes.
-     * Depending on the implementation typically allows up to 64k events to be stored.
+     * Record trace events continuously using an internal ring buffer. Default tracing mode.
+     *
+     * Overwrites old events if they exceed buffer capacity. Uses less memory than the
+     * {@link #RECORD_UNTIL_FULL} mode. Depending on the implementation typically allows
+     * up to 64k events to be stored.
      */
     public static final int RECORD_CONTINUOUSLY = 1;
 
     /**
-     * Record trace events using a larger internal tracing buffer until it is full.
-     * Uses significantly more memory than {@link #RECORD_UNTIL_FULL} and may not be
-     * suitable on devices with smaller RAM.
-     */
-    public static final int RECORD_UNTIL_FULL_LARGE_BUFFER = 2;
-
-    /**
      * @hide
      */
     public TracingConfig(@PredefinedCategories int predefinedCategories,
@@ -182,7 +176,7 @@
     public static class Builder {
         private @PredefinedCategories int mPredefinedCategories = CATEGORIES_NONE;
         private final List<String> mCustomIncludedCategories = new ArrayList<String>();
-        private @TracingMode int mTracingMode = RECORD_UNTIL_FULL;
+        private @TracingMode int mTracingMode = RECORD_CONTINUOUSLY;
 
         /**
          * Default constructor for Builder.
@@ -202,7 +196,9 @@
          *
          * @param predefinedCategories list or bitmask of predefined category sets to use:
          *                    {@link #CATEGORIES_NONE}, {@link #CATEGORIES_ALL},
-         *                    {@link #CATEGORIES_WEB_DEVELOPER}, {@link #CATEGORIES_INPUT_LATENCY},
+         *                    {@link #CATEGORIES_ANDROID_WEBVIEW},
+         *                    {@link #CATEGORIES_WEB_DEVELOPER},
+         *                    {@link #CATEGORIES_INPUT_LATENCY},
          *                    {@link #CATEGORIES_RENDERING},
          *                    {@link #CATEGORIES_JAVASCRIPT_AND_RENDERING} or
          *                    {@link #CATEGORIES_FRAME_VIEWER}.
@@ -250,9 +246,8 @@
         /**
          * Sets the tracing mode for this configuration.
          *
-         * @param tracingMode tracing mode to use, one of {@link #RECORD_UNTIL_FULL},
-         *                    {@link #RECORD_CONTINUOUSLY} or
-         *                    {@link #RECORD_UNTIL_FULL_LARGE_BUFFER}.
+         * @param tracingMode tracing mode to use, one of {@link #RECORD_UNTIL_FULL} or
+         *                    {@link #RECORD_CONTINUOUSLY}.
          * @return The builder to facilitate chaining.
          */
         public Builder setTracingMode(@TracingMode int tracingMode) {
diff --git a/core/java/android/webkit/TracingController.java b/core/java/android/webkit/TracingController.java
index 7871021..50068f5 100644
--- a/core/java/android/webkit/TracingController.java
+++ b/core/java/android/webkit/TracingController.java
@@ -60,9 +60,8 @@
      * Starts tracing all webviews. Depending on the trace mode in traceConfig
      * specifies how the trace events are recorded.
      *
-     * For tracing modes {@link TracingConfig#RECORD_UNTIL_FULL},
-     * {@link TracingConfig#RECORD_CONTINUOUSLY} and
-     * {@link TracingConfig#RECORD_UNTIL_FULL_LARGE_BUFFER} the events are recorded
+     * For tracing modes {@link TracingConfig#RECORD_UNTIL_FULL} and
+     * {@link TracingConfig#RECORD_CONTINUOUSLY} the events are recorded
      * using an internal buffer and flushed to the outputStream when
      * {@link #stop(OutputStream, Executor)} is called.
      *
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 9a99963..298c61e 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -89,7 +89,7 @@
 
 /**
  * Base class that can be used to implement virtualized lists of items. A list does
- * not have a spatial definition here. For instance, subclases of this class can
+ * not have a spatial definition here. For instance, subclasses of this class can
  * display the content of the list in a grid, in a carousel, as stack, etc.
  *
  * @attr ref android.R.styleable#AbsListView_listSelector
diff --git a/core/java/android/widget/MediaControlView2.java b/core/java/android/widget/MediaControlView2.java
index 3ec8ab9..dab0f73 100644
--- a/core/java/android/widget/MediaControlView2.java
+++ b/core/java/android/widget/MediaControlView2.java
@@ -150,7 +150,7 @@
     public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super((instance, superProvider, privateProvider) ->
-                ApiLoader.getProvider(context).createMediaControlView2(
+                ApiLoader.getProvider().createMediaControlView2(
                         (MediaControlView2) instance, superProvider, privateProvider,
                         attrs, defStyleAttr, defStyleRes),
                 context, attrs, defStyleAttr, defStyleRes);
diff --git a/core/java/android/widget/VideoView2.java b/core/java/android/widget/VideoView2.java
index 6f08dc2..214ff3a 100644
--- a/core/java/android/widget/VideoView2.java
+++ b/core/java/android/widget/VideoView2.java
@@ -143,7 +143,7 @@
             @NonNull Context context, @Nullable AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super((instance, superProvider, privateProvider) ->
-                ApiLoader.getProvider(context).createVideoView2(
+                ApiLoader.getProvider().createVideoView2(
                         (VideoView2) instance, superProvider, privateProvider,
                         attrs, defStyleAttr, defStyleRes),
                 context, attrs, defStyleAttr, defStyleRes);
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index d3b4dbf..9a082ec 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -320,8 +320,8 @@
         return builder;
     }
 
-    public static ArrayList<InputMethodInfo> getDefaultEnabledImes(final Context context,
-            final ArrayList<InputMethodInfo> imis) {
+    public static ArrayList<InputMethodInfo> getDefaultEnabledImes(
+            Context context, ArrayList<InputMethodInfo> imis, boolean onlyMinimum) {
         final Locale fallbackLocale = getFallbackLocaleForDefaultIme(imis, context);
         // We will primarily rely on the system locale, but also keep relying on the fallback locale
         // as a last resort.
@@ -329,11 +329,19 @@
         // then pick up suitable auxiliary IMEs when necessary (e.g. Voice IMEs with "automatic"
         // subtype)
         final Locale systemLocale = getSystemLocaleFromContext(context);
-        return getMinimumKeyboardSetWithSystemLocale(imis, context, systemLocale, fallbackLocale)
-                .fillImes(imis, context, true /* checkDefaultAttribute */, systemLocale,
-                        true /* checkCountry */, SUBTYPE_MODE_ANY)
-                .fillAuxiliaryImes(imis, context)
-                .build();
+        final InputMethodListBuilder builder =
+                getMinimumKeyboardSetWithSystemLocale(imis, context, systemLocale, fallbackLocale);
+        if (!onlyMinimum) {
+            builder.fillImes(imis, context, true /* checkDefaultAttribute */, systemLocale,
+                    true /* checkCountry */, SUBTYPE_MODE_ANY)
+                    .fillAuxiliaryImes(imis, context);
+        }
+        return builder.build();
+    }
+
+    public static ArrayList<InputMethodInfo> getDefaultEnabledImes(
+            Context context, ArrayList<InputMethodInfo> imis) {
+        return getDefaultEnabledImes(context, imis, false /* onlyMinimum */);
     }
 
     public static Locale constructLocaleFromString(String localeStr) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 06230c1..bbff515 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.job.JobProtoEnums;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.UidTraffic;
 import android.content.ContentResolver;
@@ -10045,7 +10046,8 @@
             if (t != null) {
                 t.startRunningLocked(elapsedRealtimeMs);
                 StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null,
-                        name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__STARTED);
+                        name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__STARTED,
+                        JobProtoEnums.STOP_REASON_CANCELLED);
             }
         }
 
@@ -10055,7 +10057,8 @@
                 t.stopRunningLocked(elapsedRealtimeMs);
                 if (!t.isRunningLocked()) { // only tell statsd if truly stopped
                     StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, getUid(), null,
-                            name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED);
+                            name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED,
+                            stopReason);
                 }
             }
             if (mBsi.mOnBatteryTimeBase.isRunning()) {
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
new file mode 100644
index 0000000..2c48506
--- /dev/null
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.os;
+
+import android.os.Binder;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * Collects statistics about CPU time spent per binder call across multiple dimensions, e.g.
+ * per thread, uid or call description.
+ */
+public class BinderCallsStats {
+    private static final int CALL_SESSIONS_POOL_SIZE = 100;
+    private static final BinderCallsStats sInstance = new BinderCallsStats();
+
+    private volatile boolean mTrackingEnabled = false;
+    private final SparseArray<UidEntry> mUidEntries = new SparseArray<>();
+    private final Queue<CallSession> mCallSessionsPool = new ConcurrentLinkedQueue<>();
+
+    private BinderCallsStats() {
+    }
+
+    @VisibleForTesting
+    public BinderCallsStats(boolean trackingEnabled) {
+        mTrackingEnabled = trackingEnabled;
+    }
+
+    public CallSession callStarted(Binder binder, int code) {
+        if (!mTrackingEnabled) {
+            return null;
+        }
+
+        return callStarted(binder.getClass().getName(), code);
+    }
+
+    private CallSession callStarted(String className, int code) {
+        CallSession s = mCallSessionsPool.poll();
+        if (s == null) {
+            s = new CallSession();
+        }
+        s.mCallStat.className = className;
+        s.mCallStat.msg = code;
+
+        s.mStarted = getThreadTimeMicro();
+        return s;
+    }
+
+    public void callEnded(CallSession s) {
+        if (!mTrackingEnabled) {
+            return;
+        }
+        Preconditions.checkNotNull(s);
+        final long cpuTimeNow = getThreadTimeMicro();
+        final long duration = cpuTimeNow - s.mStarted;
+        s.mCallingUId = Binder.getCallingUid();
+
+        synchronized (mUidEntries) {
+            UidEntry uidEntry = mUidEntries.get(s.mCallingUId);
+            if (uidEntry == null) {
+                uidEntry = new UidEntry(s.mCallingUId);
+                mUidEntries.put(s.mCallingUId, uidEntry);
+            }
+
+            // Find CallDesc entry and update its total time
+            CallStat callStat = uidEntry.mCallStats.get(s.mCallStat);
+            // Only create CallStat if it's a new entry, otherwise update existing instance
+            if (callStat == null) {
+                callStat = new CallStat(s.mCallStat.className, s.mCallStat.msg);
+                uidEntry.mCallStats.put(callStat, callStat);
+            }
+            uidEntry.time += duration;
+            uidEntry.callCount++;
+            callStat.callCount++;
+            callStat.time += duration;
+        }
+        if (mCallSessionsPool.size() < CALL_SESSIONS_POOL_SIZE) {
+            mCallSessionsPool.add(s);
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        Map<Integer, Long> uidTimeMap = new HashMap<>();
+        Map<Integer, Long> uidCallCountMap = new HashMap<>();
+        long totalCallsCount = 0;
+        long totalCallsTime = 0;
+        int uidEntriesSize = mUidEntries.size();
+        List<UidEntry> entries = new ArrayList<>();
+        synchronized (mUidEntries) {
+            for (int i = 0; i < uidEntriesSize; i++) {
+                UidEntry e = mUidEntries.valueAt(i);
+                entries.add(e);
+                totalCallsTime += e.time;
+                // Update per-uid totals
+                Long totalTimePerUid = uidTimeMap.get(e.uid);
+                uidTimeMap.put(e.uid,
+                        totalTimePerUid == null ? e.time : totalTimePerUid + e.time);
+                Long totalCallsPerUid = uidCallCountMap.get(e.uid);
+                uidCallCountMap.put(e.uid, totalCallsPerUid == null ? e.callCount
+                        : totalCallsPerUid + e.callCount);
+                totalCallsCount += e.callCount;
+            }
+        }
+        pw.println("Binder call stats:");
+        pw.println("  Raw data (uid,call_desc,time):");
+        entries.sort((o1, o2) -> {
+            if (o1.time < o2.time) {
+                return 1;
+            } else if (o1.time > o2.time) {
+                return -1;
+            }
+            return 0;
+        });
+        StringBuilder sb = new StringBuilder();
+        for (UidEntry uidEntry : entries) {
+            List<CallStat> callStats = new ArrayList<>(uidEntry.mCallStats.keySet());
+            callStats.sort((o1, o2) -> {
+                if (o1.time < o2.time) {
+                    return 1;
+                } else if (o1.time > o2.time) {
+                    return -1;
+                }
+                return 0;
+            });
+            for (CallStat e : callStats) {
+                sb.setLength(0);
+                sb.append("    ")
+                        .append(uidEntry.uid).append(",").append(e).append(',').append(e.time);
+                pw.println(sb);
+            }
+        }
+        pw.println();
+        pw.println("  Per UID Summary(UID: time, total_time_percentage, calls_count):");
+        List<Map.Entry<Integer, Long>> uidTotals = new ArrayList<>(uidTimeMap.entrySet());
+        uidTotals.sort((o1, o2) -> o2.getValue().compareTo(o1.getValue()));
+        for (Map.Entry<Integer, Long> uidTotal : uidTotals) {
+            Long callCount = uidCallCountMap.get(uidTotal.getKey());
+            pw.println(String.format("    %5d: %11d %3.0f%% %8d",
+                    uidTotal.getKey(), uidTotal.getValue(),
+                    100d * uidTotal.getValue() / totalCallsTime, callCount));
+        }
+        pw.println();
+        pw.println(String.format("  Summary: total_time=%d, "
+                        + "calls_count=%d, avg_call_time=%.0f",
+                totalCallsTime, totalCallsCount,
+                (double)totalCallsTime / totalCallsCount));
+    }
+
+    private static long getThreadTimeMicro() {
+        return SystemClock.currentThreadTimeMicro();
+    }
+
+    public static BinderCallsStats getInstance() {
+        return sInstance;
+    }
+
+    public void setTrackingEnabled(boolean enabled) {
+        mTrackingEnabled = enabled;
+    }
+
+    public boolean isTrackingEnabled() {
+        return mTrackingEnabled;
+    }
+
+    private static class CallStat {
+        String className;
+        int msg;
+        long time;
+        long callCount;
+
+        CallStat() {
+        }
+
+        CallStat(String className, int msg) {
+            this.className = className;
+            this.msg = msg;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+
+            CallStat callStat = (CallStat) o;
+
+            return msg == callStat.msg && (className == callStat.className);
+        }
+
+        @Override
+        public int hashCode() {
+            int result = className.hashCode();
+            result = 31 * result + msg;
+            return result;
+        }
+
+        @Override
+        public String toString() {
+            return className + "/" + msg;
+        }
+    }
+
+    public static class CallSession {
+        int mCallingUId;
+        long mStarted;
+        CallStat mCallStat = new CallStat();
+    }
+
+    private static class UidEntry {
+        int uid;
+        long time;
+        long callCount;
+
+        UidEntry(int uid) {
+            this.uid = uid;
+        }
+
+        // Aggregate time spent per each call name: call_desc -> cpu_time_micros
+        Map<CallStat, CallStat> mCallStats = new ArrayMap<>();
+
+        @Override
+        public String toString() {
+            return "UidEntry{" +
+                    "time=" + time +
+                    ", callCount=" + callCount +
+                    ", mCallStats=" + mCallStats +
+                    '}';
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+
+            UidEntry uidEntry = (UidEntry) o;
+            return uid == uidEntry.uid;
+        }
+
+        @Override
+        public int hashCode() {
+            return uid;
+        }
+    }
+
+}
diff --git a/core/java/com/android/internal/util/NotificationMessagingUtil.java b/core/java/com/android/internal/util/NotificationMessagingUtil.java
index b962d4f..bf796cd 100644
--- a/core/java/com/android/internal/util/NotificationMessagingUtil.java
+++ b/core/java/com/android/internal/util/NotificationMessagingUtil.java
@@ -26,7 +26,6 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
-import android.text.TextUtils;
 import android.util.ArrayMap;
 
 import java.util.Objects;
@@ -47,6 +46,18 @@
                 Settings.Secure.getUriFor(DEFAULT_SMS_APP_SETTING), false, mSmsContentObserver);
     }
 
+    public boolean isImportantMessaging(StatusBarNotification sbn, int importance) {
+        if (importance < NotificationManager.IMPORTANCE_LOW) {
+            return false;
+        }
+
+        return hasMessagingStyle(sbn) || (isCategoryMessage(sbn) && isDefaultMessagingApp(sbn));
+    }
+
+    public boolean isMessaging(StatusBarNotification sbn) {
+        return hasMessagingStyle(sbn) || isDefaultMessagingApp(sbn) || isCategoryMessage(sbn);
+    }
+
     @SuppressWarnings("deprecation")
     private boolean isDefaultMessagingApp(StatusBarNotification sbn) {
         final int userId = sbn.getUserId();
@@ -73,25 +84,12 @@
         }
     };
 
-    public boolean isImportantMessaging(StatusBarNotification sbn, int importance) {
-        if (importance < NotificationManager.IMPORTANCE_LOW) {
-            return false;
-        }
-
-        return isMessaging(sbn);
+    private boolean hasMessagingStyle(StatusBarNotification sbn) {
+        Class<? extends Notification.Style> style = sbn.getNotification().getNotificationStyle();
+        return Notification.MessagingStyle.class.equals(style);
     }
 
-    public boolean isMessaging(StatusBarNotification sbn) {
-        Class<? extends Notification.Style> style = sbn.getNotification().getNotificationStyle();
-        if (Notification.MessagingStyle.class.equals(style)) {
-            return true;
-        }
-
-        if (Notification.CATEGORY_MESSAGE.equals(sbn.getNotification().category)
-                && isDefaultMessagingApp(sbn)) {
-            return true;
-        }
-
-        return false;
+    private boolean isCategoryMessage(StatusBarNotification sbn) {
+        return Notification.CATEGORY_MESSAGE.equals(sbn.getNotification().category);
     }
 }
diff --git a/core/java/com/android/internal/util/ProviderAccessStats.java b/core/java/com/android/internal/util/ProviderAccessStats.java
new file mode 100644
index 0000000..c3ffb02
--- /dev/null
+++ b/core/java/com/android/internal/util/ProviderAccessStats.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 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.util;
+
+import android.os.SystemClock;
+import android.util.SparseBooleanArray;
+import android.util.SparseLongArray;
+
+import java.io.PrintWriter;
+
+public class ProviderAccessStats {
+    private final Object mLock = new Object();
+
+    private final long mStartUptime = SystemClock.uptimeMillis();
+
+    private final SparseBooleanArray mAllCallingUids = new SparseBooleanArray();
+    private final SparseLongArray mQueryStats = new SparseLongArray(16);
+    private final SparseLongArray mBatchStats = new SparseLongArray(0);
+    private final SparseLongArray mInsertStats = new SparseLongArray(0);
+    private final SparseLongArray mUpdateStats = new SparseLongArray(0);
+    private final SparseLongArray mDeleteStats = new SparseLongArray(0);
+    private final SparseLongArray mInsertInBatchStats = new SparseLongArray(0);
+    private final SparseLongArray mUpdateInBatchStats = new SparseLongArray(0);
+    private final SparseLongArray mDeleteInBatchStats = new SparseLongArray(0);
+
+    private final SparseLongArray mOperationDurationMillis = new SparseLongArray(16);
+
+    private static class PerThreadData {
+        public int nestCount;
+        public long startUptimeMillis;
+    }
+
+    private final ThreadLocal<PerThreadData> mThreadLocal =
+            ThreadLocal.withInitial(() -> new PerThreadData());
+
+    private void incrementStats(int callingUid, SparseLongArray stats) {
+        synchronized (mLock) {
+            stats.put(callingUid, stats.get(callingUid) + 1);
+            mAllCallingUids.put(callingUid, true);
+        }
+
+        final PerThreadData data = mThreadLocal.get();
+        data.nestCount++;
+        if (data.nestCount == 1) {
+            data.startUptimeMillis = SystemClock.uptimeMillis();
+        }
+    }
+
+    private void incrementStats(int callingUid, boolean inBatch,
+            SparseLongArray statsNonBatch, SparseLongArray statsInBatch) {
+        incrementStats(callingUid, inBatch ? statsInBatch : statsNonBatch);
+    }
+
+    public final void incrementInsertStats(int callingUid, boolean inBatch) {
+        incrementStats(callingUid, inBatch, mInsertStats, mInsertInBatchStats);
+    }
+
+    public final void incrementUpdateStats(int callingUid, boolean inBatch) {
+        incrementStats(callingUid, inBatch, mUpdateStats, mUpdateInBatchStats);
+    }
+
+    public final void incrementDeleteStats(int callingUid, boolean inBatch) {
+        incrementStats(callingUid, inBatch, mDeleteStats, mDeleteInBatchStats);
+    }
+
+    public final void incrementQueryStats(int callingUid) {
+        incrementStats(callingUid, mQueryStats);
+    }
+
+    public final void incrementBatchStats(int callingUid) {
+        incrementStats(callingUid, mBatchStats);
+    }
+
+    public void finishOperation(int callingUid) {
+        final PerThreadData data = mThreadLocal.get();
+        data.nestCount--;
+        if (data.nestCount == 0) {
+            // Because we only have millisecond granularity, let's always attribute at least 1ms
+            // for each operation.
+            final long duration = Math.max(1, SystemClock.uptimeMillis() - data.startUptimeMillis);
+
+            synchronized (mLock) {
+                mOperationDurationMillis.put(callingUid,
+                        mOperationDurationMillis.get(callingUid) + duration);
+            }
+        }
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        synchronized (mLock) {
+            pw.print("  Process uptime: ");
+            pw.print((SystemClock.uptimeMillis() - mStartUptime) / (60 * 1000));
+            pw.println(" minutes");
+            pw.println();
+
+            pw.print(prefix);
+            pw.println("Client activities:");
+            pw.print(prefix);
+            pw.println("  UID        Query  Insert Update Delete   Batch Insert Update Delete"
+                    + "          Sec");
+            for (int i = 0; i < mAllCallingUids.size(); i++) {
+                final int uid = mAllCallingUids.keyAt(i);
+                pw.print(prefix);
+                pw.println(String.format(
+                        "  %-9d %6d  %6d %6d %6d  %6d %6d %6d %6d %12.3f",
+                        uid,
+                        mQueryStats.get(uid),
+                        mInsertStats.get(uid),
+                        mUpdateStats.get(uid),
+                        mDeleteStats.get(uid),
+                        mBatchStats.get(uid),
+                        mInsertInBatchStats.get(uid),
+                        mUpdateInBatchStats.get(uid),
+                        mDeleteInBatchStats.get(uid),
+                        (mOperationDurationMillis.get(uid) / 1000.0)
+                ));
+            }
+            pw.println();
+        }
+    }
+}
diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp
index d6496cd..7166c75 100644
--- a/core/jni/android/graphics/AnimatedImageDrawable.cpp
+++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp
@@ -42,7 +42,6 @@
     }
 
     auto* imageDecoder = reinterpret_cast<ImageDecoder*>(nativeImageDecoder);
-    auto info = imageDecoder->mCodec->getInfo();
     const SkISize scaledSize = SkISize::Make(width, height);
     SkIRect subset;
     if (jsubset) {
@@ -51,6 +50,35 @@
         subset = SkIRect::MakeWH(width, height);
     }
 
+    auto info = imageDecoder->mCodec->getInfo();
+    bool hasRestoreFrame = false;
+    if (imageDecoder->mCodec->getEncodedFormat() == SkEncodedImageFormat::kWEBP) {
+        if (width < info.width() && height < info.height()) {
+            // WebP will scale its SkBitmap to the scaled size.
+            // FIXME: b/73529447 GIF should do the same.
+            info = info.makeWH(width, height);
+        }
+    } else {
+        const int frameCount = imageDecoder->mCodec->codec()->getFrameCount();
+        for (int i = 0; i < frameCount; ++i) {
+            SkCodec::FrameInfo frameInfo;
+            if (!imageDecoder->mCodec->codec()->getFrameInfo(i, &frameInfo)) {
+                doThrowIOE(env, "Failed to read frame info!");
+                return 0;
+            }
+            if (frameInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
+                hasRestoreFrame = true;
+                break;
+            }
+        }
+    }
+
+    size_t bytesUsed = info.computeMinByteSize();
+    // SkAnimatedImage has one SkBitmap for decoding, plus an extra one if there is a
+    // kRestorePrevious frame. AnimatedImageDrawable has two SkPictures storing the current
+    // frame and the next frame. (The former assumes that the image is animated, and the
+    // latter assumes that it is drawn to a hardware canvas.)
+    bytesUsed *= hasRestoreFrame ? 4 : 3;
     sk_sp<SkPicture> picture;
     if (jpostProcess) {
         SkRect bounds = SkRect::MakeWH(subset.width(), subset.height());
@@ -63,6 +91,7 @@
             return 0;
         }
         picture = recorder.finishRecordingAsPicture();
+        bytesUsed += picture->approximateBytesUsed();
     }
 
 
@@ -74,7 +103,10 @@
         return 0;
     }
 
-    sk_sp<AnimatedImageDrawable> drawable(new AnimatedImageDrawable(animatedImg));
+    bytesUsed += sizeof(animatedImg.get());
+
+    sk_sp<AnimatedImageDrawable> drawable(new AnimatedImageDrawable(std::move(animatedImg),
+                                                                    bytesUsed));
     return reinterpret_cast<jlong>(drawable.release());
 }
 
@@ -202,10 +234,9 @@
     }
 }
 
-static long AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
+static jlong AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
     auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
-    // FIXME: Report the size of the internal SkBitmap etc.
-    return sizeof(drawable);
+    return drawable->byteSize();
 }
 
 static void AnimatedImageDrawable_nMarkInvisible(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 4b6578b..3fcedd0 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -30,8 +30,8 @@
 
 class SkColorFilterGlue {
 public:
-    static void SafeUnref(SkShader* shader) {
-        SkSafeUnref(shader);
+    static void SafeUnref(SkColorFilter* filter) {
+        SkSafeUnref(filter);
     }
 
     static jlong GetNativeFinalizer(JNIEnv*, jobject) {
diff --git a/core/proto/android/app/jobparameters.proto b/core/proto/android/app/job/enums.proto
similarity index 66%
rename from core/proto/android/app/jobparameters.proto
rename to core/proto/android/app/job/enums.proto
index 4f6a2a2..0f14f20 100644
--- a/core/proto/android/app/jobparameters.proto
+++ b/core/proto/android/app/job/enums.proto
@@ -15,19 +15,18 @@
  */
 
 syntax = "proto2";
+
+package android.app.job;
+
+option java_outer_classname = "JobProtoEnums";
 option java_multiple_files = true;
 
-package android.app;
-
-/**
- * An android.app.JobParameters object.
- */
-message JobParametersProto {
-    enum CancelReason {
-        REASON_CANCELLED = 0;
-        REASON_CONSTRAINTS_NOT_SATISFIED = 1;
-        REASON_PREEMPT = 2;
-        REASON_TIMEOUT = 3;
-        REASON_DEVICE_IDLE = 4;
-    }
+// Reasons a job is stopped.
+// Primarily used in android.app.job.JobParameters.java.
+enum StopReasonEnum {
+  STOP_REASON_CANCELLED = 0;
+  STOP_REASON_CONSTRAINTS_NOT_SATISFIED = 1;
+  STOP_REASON_PREEMPT = 2;
+  STOP_REASON_TIMEOUT = 3;
+  STOP_REASON_DEVICE_IDLE = 4;
 }
diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto
index 345c8ef..8e98ac9 100644
--- a/core/proto/android/os/batterystats.proto
+++ b/core/proto/android/os/batterystats.proto
@@ -19,7 +19,7 @@
 
 package android.os;
 
-import "frameworks/base/core/proto/android/app/jobparameters.proto";
+import "frameworks/base/core/proto/android/app/job/enums.proto";
 import "frameworks/base/core/proto/android/os/powermanager.proto";
 import "frameworks/base/core/proto/android/telephony/enums.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
@@ -637,7 +637,7 @@
     message ReasonCount {
       option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-      optional android.app.JobParametersProto.CancelReason name = 1;
+      optional android.app.job.StopReasonEnum name = 1;
       optional int32 count = 2;
     }
     repeated ReasonCount reason_count = 2;
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 6a3aaab..476d5fe 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -231,22 +231,22 @@
         (section).args = "procstats --proto"
     ];
 
-    optional com.android.server.am.proto.ActivityManagerServiceDumpActivitiesProto activities = 3012 [
+    optional com.android.server.am.ActivityManagerServiceDumpActivitiesProto activities = 3012 [
         (section).type = SECTION_DUMPSYS,
         (section).args = "activity --proto activities"
     ];
 
-    optional com.android.server.am.proto.ActivityManagerServiceDumpBroadcastsProto broadcasts = 3013 [
+    optional com.android.server.am.ActivityManagerServiceDumpBroadcastsProto broadcasts = 3013 [
         (section).type = SECTION_DUMPSYS,
         (section).args = "activity --proto broadcasts"
     ];
 
-    optional com.android.server.am.proto.ActivityManagerServiceDumpServicesProto amservices = 3014 [
+    optional com.android.server.am.ActivityManagerServiceDumpServicesProto amservices = 3014 [
         (section).type = SECTION_DUMPSYS,
         (section).args = "activity --proto service"
     ];
 
-    optional com.android.server.am.proto.ActivityManagerServiceDumpProcessesProto amprocesses = 3015 [
+    optional com.android.server.am.ActivityManagerServiceDumpProcessesProto amprocesses = 3015 [
         (section).type = SECTION_DUMPSYS,
         (section).args = "activity --proto processes"
     ];
@@ -256,12 +256,12 @@
         (section).args = "alarm --proto"
     ];
 
-    optional com.android.server.wm.proto.WindowManagerServiceDumpProto window = 3017 [
+    optional com.android.server.wm.WindowManagerServiceDumpProto window = 3017 [
         (section).type = SECTION_DUMPSYS,
         (section).args = "window --proto"
     ];
 
-    optional com.android.server.am.proto.MemInfoDumpProto meminfo = 3018 [
+    optional com.android.server.am.MemInfoDumpProto meminfo = 3018 [
         (section).type = SECTION_DUMPSYS,
         (section).args = "meminfo -a --proto"
     ];
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index 4e781d6..4bb9707 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -466,7 +466,7 @@
     // skipped.
     optional SettingProto override_settings_provider_restore_any_version = 355 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto chained_battery_attribution_enabled = 356 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto autofill_compat_allowed_packages = 357 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto autofill_compat_mode_allowed_packages = 357 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto hidden_api_blacklist_exemptions = 358 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto sound_trigger_detection_service_op_timeout = 387  [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto max_sound_trigger_detection_service_ops_per_day = 388  [ (android.privacy).dest = DEST_AUTOMATIC ];
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index fcb9807..0c617ff 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -16,7 +16,7 @@
 
 syntax = "proto2";
 
-package com.android.server.am.proto;
+package com.android.server.am;
 
 import "frameworks/base/core/proto/android/app/activitymanager.proto";
 import "frameworks/base/core/proto/android/app/enums.proto";
@@ -59,11 +59,11 @@
 message ActivityStackSupervisorProto {
   option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-  optional .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1;
+  optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
   repeated ActivityDisplayProto displays = 2;
   optional KeyguardControllerProto keyguard_controller = 3;
   optional int32 focused_stack_id = 4;
-  optional .com.android.server.wm.proto.IdentifierProto resumed_activity = 5;
+  optional .com.android.server.wm.IdentifierProto resumed_activity = 5;
   // Whether or not the home activity is the recents activity. This is needed for the CTS tests to
   // know what activity types to check for when invoking splitscreen multi-window.
   optional bool is_home_recents_component = 6;
@@ -73,7 +73,7 @@
 message ActivityDisplayProto {
   option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-  optional .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1;
+  optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
   optional int32 id = 2;
   repeated ActivityStackProto stacks = 3;
 }
@@ -81,10 +81,10 @@
 message ActivityStackProto {
   option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-  optional .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1;
+  optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
   optional int32 id = 2;
   repeated TaskRecordProto tasks = 3;
-  optional .com.android.server.wm.proto.IdentifierProto resumed_activity = 4;
+  optional .com.android.server.wm.IdentifierProto resumed_activity = 4;
   optional int32 display_id = 5;
   optional bool fullscreen = 6;
   optional .android.graphics.RectProto bounds = 7;
@@ -93,7 +93,7 @@
 message TaskRecordProto {
   option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-  optional .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1;
+  optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
   optional int32 id = 2;
   repeated ActivityRecordProto activities = 3;
   optional int32 stack_id = 4;
@@ -111,8 +111,8 @@
 message ActivityRecordProto {
   option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-  optional .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1;
-  optional .com.android.server.wm.proto.IdentifierProto identifier = 2;
+  optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
+  optional .com.android.server.wm.IdentifierProto identifier = 2;
   optional string state = 3;
   optional bool visible = 4;
   optional bool front_of_task = 5;
@@ -689,25 +689,14 @@
   }
   optional SleepStatus sleep_status = 27;
 
-  message VoiceProto {
+  message Voice {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional string session = 1;
     optional .android.os.PowerManagerProto.WakeLock wakelock = 2;
   }
-  optional VoiceProto running_voice = 28;
+  optional Voice running_voice = 28;
 
-  message VrControllerProto {
-    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
-    enum VrMode {
-      FLAG_NON_VR_MODE = 0;
-      FLAG_VR_MODE = 1;
-      FLAG_PERSISTENT_VR_MODE = 2;
-    }
-    repeated VrMode vr_mode = 1;
-    optional int32 render_thread_id = 2;
-  }
   optional VrControllerProto vr_controller = 29;
 
   message DebugApp {
@@ -854,6 +843,19 @@
   optional string reason = 3;
 }
 
+// proto of class VrController.java
+message VrControllerProto {
+  option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+  enum VrMode {
+    FLAG_NON_VR_MODE = 0;
+    FLAG_VR_MODE = 1;
+    FLAG_PERSISTENT_VR_MODE = 2;
+  }
+  repeated VrMode vr_mode = 1;
+  optional int32 render_thread_id = 2;
+}
+
 message ProcessOomProto {
   option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
diff --git a/core/proto/android/server/animationadapter.proto b/core/proto/android/server/animationadapter.proto
index c4ffe8c..9bfa794 100644
--- a/core/proto/android/server/animationadapter.proto
+++ b/core/proto/android/server/animationadapter.proto
@@ -20,7 +20,7 @@
 import "frameworks/base/core/proto/android/view/remote_animation_target.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
-package com.android.server.wm.proto;
+package com.android.server.wm;
 option java_multiple_files = true;
 
 message AnimationAdapterProto {
diff --git a/core/proto/android/server/appwindowthumbnail.proto b/core/proto/android/server/appwindowthumbnail.proto
index 8f48d75..54ad193 100644
--- a/core/proto/android/server/appwindowthumbnail.proto
+++ b/core/proto/android/server/appwindowthumbnail.proto
@@ -19,7 +19,7 @@
 import "frameworks/base/core/proto/android/server/surfaceanimator.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
-package com.android.server.wm.proto;
+package com.android.server.wm;
 option java_multiple_files = true;
 
 /**
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 9193129..122e5c4 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -20,7 +20,7 @@
 
 option java_multiple_files = true;
 
-import "frameworks/base/core/proto/android/app/jobparameters.proto";
+import "frameworks/base/core/proto/android/app/job/enums.proto";
 import "frameworks/base/core/proto/android/content/clipdata.proto";
 import "frameworks/base/core/proto/android/content/component_name.proto";
 import "frameworks/base/core/proto/android/content/intent.proto";
@@ -465,7 +465,7 @@
         message StopReasonCount {
             option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-            optional .android.app.JobParametersProto.CancelReason reason = 1;
+            optional .android.app.job.StopReasonEnum reason = 1;
             optional int32 count = 2;
         }
         repeated StopReasonCount stop_reasons = 9;
@@ -516,7 +516,7 @@
         optional int32 job_id = 4;
         optional string tag = 5 [ (.android.privacy).dest = DEST_EXPLICIT ];
         // Only valid for STOP_JOB or STOP_PERIODIC_JOB Events.
-        optional .android.app.JobParametersProto.CancelReason stop_reason = 6;
+        optional .android.app.job.StopReasonEnum stop_reason = 6;
     }
     repeated HistoryEvent history_event = 1;
 }
diff --git a/core/proto/android/server/surfaceanimator.proto b/core/proto/android/server/surfaceanimator.proto
index dcc2b34..84560bc 100644
--- a/core/proto/android/server/surfaceanimator.proto
+++ b/core/proto/android/server/surfaceanimator.proto
@@ -20,7 +20,7 @@
 import "frameworks/base/core/proto/android/view/surfacecontrol.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
-package com.android.server.wm.proto;
+package com.android.server.wm;
 option java_multiple_files = true;
 
 /**
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 9598f24..063135d 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -28,7 +28,7 @@
 import "frameworks/base/core/proto/android/view/windowlayoutparams.proto";
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 
-package com.android.server.wm.proto;
+package com.android.server.wm;
 
 option java_multiple_files = true;
 
diff --git a/core/proto/android/server/windowmanagertrace.proto b/core/proto/android/server/windowmanagertrace.proto
index 96a90bf..f502961 100644
--- a/core/proto/android/server/windowmanagertrace.proto
+++ b/core/proto/android/server/windowmanagertrace.proto
@@ -18,7 +18,7 @@
 
 import "frameworks/base/core/proto/android/server/windowmanagerservice.proto";
 
-package com.android.server.wm.proto;
+package com.android.server.wm;
 
 option java_multiple_files = true;
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1b4d571..2ebffb7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3310,8 +3310,9 @@
     <permission android:name="android.permission.BACKUP"
         android:protectionLevel="signature|privileged" />
 
-    <!-- @SystemApi Allows application to manage RecoverableKeyStoreLoader.
-    <p>Not for use by third-party applications.
+    <!-- @SystemApi Allows application to manage
+         {@link android.security.keystore.recovery.RecoveryController}.
+         <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.RECOVER_KEYSTORE"
         android:protectionLevel="signature|privileged" />
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index 5c5b985..fa69038 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -35,8 +35,8 @@
         <LinearLayout
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
-            android:paddingLeft="16dp"
-            android:paddingRight="16dp"
+            android:paddingStart="16dp"
+            android:paddingEnd="16dp"
             android:orientation="vertical">
 
             <LinearLayout
@@ -52,7 +52,7 @@
 
                 <TextView
                     android:id="@+id/autofill_save_title"
-                    android:paddingLeft="8dp"
+                    android:paddingStart="8dp"
                     android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/autofill_save_title"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4a72bf9..75b3bcf 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2151,6 +2151,9 @@
             @see android.view.WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
             -->
             <enum name="shortEdges" value="1" />
+            <!-- Use {@code shortEdges} instead. This is temporarily here to unblock pushing the SDK
+                 until all usages have been migrated to {@code shortEdges} -->
+            <enum name="always" value="1" />
             <!-- The window is never allowed to overlap with the DisplayCutout area.
             <p>
             This should be used with windows that transiently set {@code SYSTEM_UI_FLAG_FULLSCREEN}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1083630..bbb0b0a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1996,7 +1996,7 @@
 
     <!-- If true, the doze component is not started until after the screen has been
          turned off and the screen off animation has been performed. -->
-    <bool name="config_dozeAfterScreenOff">false</bool>
+    <bool name="config_dozeAfterScreenOffByDefault">false</bool>
 
     <!-- Doze: should the TYPE_PICK_UP_GESTURE sensor be used as a pulse signal. -->
     <bool name="config_dozePulsePickup">false</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index aac4092..f0f7270 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4475,7 +4475,7 @@
     <string name="package_deleted_device_owner">Deleted by your admin</string>
 
     <!-- [CHAR_LIMIT=NONE] Battery saver: Feature description -->
-    <string name="battery_saver_description">To help improve battery life, Battery Saver reduces your device’s performance and limits vibration, location services, and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery Saver turns off automatically when your device is charging.</string>
+    <string name="battery_saver_description">To extend battery life, Battery Saver reduces your device\'s performance and limits or turns off vibration, location services, and background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery Saver turns off automatically when your device is charging.</string>
 
     <!-- [CHAR_LIMIT=NONE] Data saver: Feature description -->
     <string name="data_saver_description">To help reduce data usage, Data Saver prevents some apps from sending or receiving data in the background. An app you’re currently using can access data, but may do so less frequently. This may mean, for example, that images don’t display until you tap them.</string>
@@ -4578,14 +4578,14 @@
 
     <!-- Displayed when the USSD/SS request is modified by STK CC to a
     different request. This will be displayed in a toast. -->
-    <string name="stk_cc_ussd_to_dial">USSD request is modified to DIAL request.</string>
-    <string name="stk_cc_ussd_to_ss">USSD request is modified to SS request.</string>
-    <string name="stk_cc_ussd_to_ussd">USSD request is modified to new USSD request.</string>
-    <string name="stk_cc_ussd_to_dial_video">USSD request is modified to Video DIAL request.</string>
-    <string name="stk_cc_ss_to_dial">SS request is modified to DIAL request.</string>
-    <string name="stk_cc_ss_to_dial_video">SS request is modified to Video DIAL request.</string>
-    <string name="stk_cc_ss_to_ussd">SS request is modified to USSD request.</string>
-    <string name="stk_cc_ss_to_ss">SS request is modified to new SS request.</string>
+    <string name="stk_cc_ussd_to_dial">USSD request changed to regular call</string>
+    <string name="stk_cc_ussd_to_ss">USSD request changed to SS request</string>
+    <string name="stk_cc_ussd_to_ussd">Changed to new USSD request</string>
+    <string name="stk_cc_ussd_to_dial_video">USSD request changed to video call</string>
+    <string name="stk_cc_ss_to_dial">SS request changed to regular call</string>
+    <string name="stk_cc_ss_to_dial_video">SS request changed to video call</string>
+    <string name="stk_cc_ss_to_ussd">SS request changed to USSD request</string>
+    <string name="stk_cc_ss_to_ss">Changed to new SS request</string>
 
     <!-- Content description of the work profile icon in the notification. -->
     <string name="notification_work_profile_content_description">Work profile</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ac01c4e..4cf50f5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1817,7 +1817,7 @@
   <java-symbol type="bool" name="config_notificationHeaderClickableForExpand" />
   <java-symbol type="bool" name="config_enableNightMode" />
   <java-symbol type="bool" name="config_tintNotificationActionButtons" />
-  <java-symbol type="bool" name="config_dozeAfterScreenOff" />
+  <java-symbol type="bool" name="config_dozeAfterScreenOffByDefault" />
   <java-symbol type="bool" name="config_enableActivityRecognitionHardwareOverlay" />
   <java-symbol type="bool" name="config_enableFusedLocationOverlay" />
   <java-symbol type="bool" name="config_enableHardwareFlpOverlay" />
@@ -2779,7 +2779,6 @@
   <java-symbol type="drawable" name="ic_user_secure" />
 
   <java-symbol type="string" name="android_upgrading_notification_title" />
-  <java-symbol type="string" name="android_upgrading_notification_body" />
 
   <java-symbol type="string" name="usb_mtp_launch_notification_title" />
   <java-symbol type="string" name="usb_mtp_launch_notification_description" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 2036e2f..87a9bd0e 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -117,7 +117,7 @@
                     Settings.Global.APP_STANDBY_ENABLED,
                     Settings.Global.ASSISTED_GPS_ENABLED,
                     Settings.Global.AUDIO_SAFE_VOLUME_STATE,
-                    Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES,
+                    Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES,
                     Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
                     Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
                     Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
@@ -450,6 +450,7 @@
                     Settings.Global.WIFI_SAVED_STATE,
                     Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE,
                     Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,
+                    Settings.Global.WIFI_SCORE_PARAMS,
                     Settings.Global.WIFI_SLEEP_POLICY,
                     Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
                     Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED,
@@ -581,7 +582,9 @@
                  Settings.Secure.KEYGUARD_SLICE_URI,
                  Settings.Secure.PARENTAL_CONTROL_ENABLED,
                  Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
-                 Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING);
+                 Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
+                 Settings.Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT,
+                 Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED);
 
     @Test
     public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/security/keystore/recovery/TrustedRootCertificatesTest.java b/core/tests/coretests/src/android/security/keystore/recovery/TrustedRootCertificatesTest.java
index 3b4ad38..a5a3ca9 100644
--- a/core/tests/coretests/src/android/security/keystore/recovery/TrustedRootCertificatesTest.java
+++ b/core/tests/coretests/src/android/security/keystore/recovery/TrustedRootCertificatesTest.java
@@ -16,7 +16,7 @@
 
 package android.security.keystore.recovery;
 
-import static android.security.keystore.recovery.TrustedRootCertificates.listRootCertificates;
+import static android.security.keystore.recovery.TrustedRootCertificates.getRootCertificates;
 
 import static org.junit.Assert.assertTrue;
 
@@ -36,8 +36,8 @@
             "GoogleCloudKeyVaultServiceV1";
 
     @Test
-    public void listRootCertificates_listsGoogleCloudVaultV1Certificate() {
-        Map<String, X509Certificate> certificates = listRootCertificates();
+    public void getRootCertificates_listsGoogleCloudVaultV1Certificate() {
+        Map<String, X509Certificate> certificates = getRootCertificates();
 
         assertTrue(certificates.containsKey(GOOGLE_CLOUD_KEY_VAULT_SERVICE_V1_ALIAS));
     }
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index e6ac682..1fd24e3 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -99,6 +99,10 @@
         assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US,
                 "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
                 "DummyNonDefaultAutoVoiceIme1");
+        assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US,
+                "DummyDefaultEnKeyboardIme");
+        assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US,
+                "DummyDefaultEnKeyboardIme");
 
         // locale: en_GB
         assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB,
@@ -106,6 +110,10 @@
         assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB,
                 "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
                 "DummyNonDefaultAutoVoiceIme1");
+        assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB,
+                "DummyDefaultEnKeyboardIme");
+        assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB,
+                "DummyDefaultEnKeyboardIme");
 
         // locale: ja_JP
         assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP,
@@ -113,6 +121,10 @@
         assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP,
                 "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
                 "DummyNonDefaultAutoVoiceIme1");
+        assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP,
+                "DummyDefaultEnKeyboardIme");
+        assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP,
+                "DummyDefaultEnKeyboardIme");
     }
 
     @Test
@@ -120,34 +132,49 @@
         // locale: en_US
         assertDefaultEnabledImes(getSamplePreinstalledImes("en-rUS"), LOCALE_EN_US,
                 "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
+        assertDefaultEnabledMinimumImes(getSamplePreinstalledImes("en-rUS"), LOCALE_EN_US,
+                "com.android.apps.inputmethod.latin");
 
         // locale: en_GB
         assertDefaultEnabledImes(getSamplePreinstalledImes("en-rGB"), LOCALE_EN_GB,
                 "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
+        assertDefaultEnabledMinimumImes(getSamplePreinstalledImes("en-rGB"), LOCALE_EN_GB,
+                "com.android.apps.inputmethod.latin");
 
         // locale: en_IN
         assertDefaultEnabledImes(getSamplePreinstalledImes("en-rIN"), LOCALE_EN_IN,
                 "com.android.apps.inputmethod.hindi",
                 "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
+        assertDefaultEnabledMinimumImes(getSamplePreinstalledImes("en-rIN"), LOCALE_EN_IN,
+                "com.android.apps.inputmethod.hindi",
+                "com.android.apps.inputmethod.latin");
 
         // locale: hi
         assertDefaultEnabledImes(getSamplePreinstalledImes("hi"), LOCALE_HI,
                 "com.android.apps.inputmethod.hindi", "com.android.apps.inputmethod.latin",
                 "com.android.apps.inputmethod.voice");
+        assertDefaultEnabledMinimumImes(getSamplePreinstalledImes("hi"), LOCALE_HI,
+                "com.android.apps.inputmethod.hindi", "com.android.apps.inputmethod.latin");
 
         // locale: ja_JP
         assertDefaultEnabledImes(getSamplePreinstalledImes("ja-rJP"), LOCALE_JA_JP,
                 "com.android.apps.inputmethod.japanese", "com.android.apps.inputmethod.voice");
+        assertDefaultEnabledMinimumImes(getSamplePreinstalledImes("ja-rJP"), LOCALE_JA_JP,
+                "com.android.apps.inputmethod.japanese");
 
         // locale: zh_CN
         assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rCN"), LOCALE_ZH_CN,
                 "com.android.apps.inputmethod.pinyin", "com.android.apps.inputmethod.voice");
+        assertDefaultEnabledMinimumImes(getSamplePreinstalledImes("zh-rCN"), LOCALE_ZH_CN,
+                "com.android.apps.inputmethod.pinyin");
 
         // locale: zh_TW
         // Note: In this case, no IME is suitable for the system locale. Hence we will pick up a
         // fallback IME regardless of the "default" attribute.
         assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rTW"), LOCALE_ZH_TW,
                 "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
+        assertDefaultEnabledMinimumImes(getSamplePreinstalledImes("zh-rTW"), LOCALE_ZH_TW,
+                "com.android.apps.inputmethod.latin");
     }
 
     @Test
@@ -785,6 +812,18 @@
         }
     }
 
+    private void assertDefaultEnabledMinimumImes(final ArrayList<InputMethodInfo> preinstalledImes,
+            final Locale systemLocale, String... expectedImeNames) {
+        final Context context = createTargetContextWithLocales(new LocaleList(systemLocale));
+        final String[] actualImeNames = getPackageNames(
+                InputMethodUtils.getDefaultEnabledImes(context, preinstalledImes,
+                        true /* onlyMinimum */));
+        assertEquals(expectedImeNames.length, actualImeNames.length);
+        for (int i = 0; i < expectedImeNames.length; ++i) {
+            assertEquals(expectedImeNames[i], actualImeNames[i]);
+        }
+    }
+
     private static List<InputMethodInfo> cloneViaParcel(final List<InputMethodInfo> list) {
         Parcel p = null;
         try {
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index c0f4920..a47ecf5 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -292,8 +292,7 @@
         mState = new State(nCreate(nativeImageDecoder, decoder, width, height, cropRect),
                 inputStream, afd);
 
-        // FIXME: Use the right size for the native allocation.
-        long nativeSize = 200;
+        final long nativeSize = nNativeByteSize(mState.mNativePtr);
         NativeAllocationRegistry registry = new NativeAllocationRegistry(
                 AnimatedImageDrawable.class.getClassLoader(), nGetNativeFinalizer(), nativeSize);
         registry.registerNativeAllocation(mState, mState.mNativePtr);
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 28d0bc4..c529f87 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -26,8 +26,8 @@
 
 namespace android {
 
-AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage)
-        : mSkAnimatedImage(std::move(animatedImage)) {
+AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed)
+        : mSkAnimatedImage(std::move(animatedImage)), mBytesUsed(bytesUsed) {
     mTimeToShowNextSnapshot = mSkAnimatedImage->currentFrameDuration();
 }
 
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.h b/libs/hwui/hwui/AnimatedImageDrawable.h
index f4e2ba7..a92b62d 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.h
+++ b/libs/hwui/hwui/AnimatedImageDrawable.h
@@ -45,7 +45,9 @@
  */
 class ANDROID_API AnimatedImageDrawable : public SkDrawable {
 public:
-    AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage);
+    // bytesUsed includes the approximate sizes of the SkAnimatedImage and the SkPictures in the
+    // Snapshots.
+    AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed);
 
     /**
      * This updates the internal time and returns true if the animation needs
@@ -100,11 +102,17 @@
     Snapshot decodeNextFrame();
     Snapshot reset();
 
+    size_t byteSize() const {
+        return sizeof(this) + mBytesUsed;
+    }
+
 protected:
     virtual void onDraw(SkCanvas* canvas) override;
 
 private:
     sk_sp<SkAnimatedImage> mSkAnimatedImage;
+    const size_t mBytesUsed;
+
     bool mRunning = false;
     bool mStarting = false;
 
diff --git a/location/java/android/location/IFusedProvider.aidl b/location/java/android/location/IFusedProvider.aidl
deleted file mode 100644
index e86ad1a..0000000
--- a/location/java/android/location/IFusedProvider.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2013 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.location;
-
-import android.hardware.location.IFusedLocationHardware;
-
-/**
- * Interface definition for Location providers that require FLP services.
- * @hide
- */
-oneway interface IFusedProvider {
-    /**
-     * Provides access to a FusedLocationHardware instance needed for the provider to work.
-     *
-     * @param instance      The FusedLocationHardware available for the provider to use.
-     */
-    void onFusedLocationHardwareChange(in IFusedLocationHardware instance);
-}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 2dd8c36..a523958 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -23,6 +23,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
@@ -42,12 +43,14 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Log;
 import com.android.internal.location.ProviderProperties;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Set;
 
 /**
  * This class provides access to the system location services.  These
@@ -234,12 +237,6 @@
         "android.location.HIGH_POWER_REQUEST_CHANGE";
 
     /**
-     * The value returned by {@link LocationManager#getGnssHardwareModelName()} when the hardware
-     * does not support providing the actual value.
-     */
-    public static final String GNSS_HARDWARE_MODEL_NAME_UNKNOWN = "Model Name Unknown";
-
-    /**
      * Broadcast intent action for Settings app to inject a footer at the bottom of location
      * settings.
      *
@@ -1252,12 +1249,40 @@
     @SystemApi
     @RequiresPermission(WRITE_SECURE_SETTINGS)
     public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
-        for (String provider : getAllProviders()) {
+        final List<String> allProvidersList = getAllProviders();
+        // Update all providers on device plus gps and network provider when disabling location.
+        Set<String> allProvidersSet = new ArraySet<>(allProvidersList.size() + 2);
+        allProvidersSet.addAll(allProvidersList);
+        // When disabling location, disable gps and network provider that could have been enabled by
+        // location mode api.
+        if (enabled == false) {
+            allProvidersSet.add(GPS_PROVIDER);
+            allProvidersSet.add(NETWORK_PROVIDER);
+        }
+        if (allProvidersSet.isEmpty()) {
+            return;
+        }
+        // to ensure thread safety, we write the provider name with a '+' or '-'
+        // and let the SettingsProvider handle it rather than reading and modifying
+        // the list of enabled providers.
+        final String prefix = enabled ? "+" : "-";
+        StringBuilder locationProvidersAllowed = new StringBuilder();
+        for (String provider : allProvidersSet) {
+            checkProvider(provider);
             if (provider.equals(PASSIVE_PROVIDER)) {
                 continue;
             }
-            setProviderEnabledForUser(provider, enabled, userHandle);
+            locationProvidersAllowed.append(prefix);
+            locationProvidersAllowed.append(provider);
+            locationProvidersAllowed.append(",");
         }
+        // Remove the trailing comma
+        locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1);
+        Settings.Secure.putStringForUser(
+                mContext.getContentResolver(),
+                Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                locationProvidersAllowed.toString(),
+                userHandle.getIdentifier());
     }
 
     /**
@@ -2176,7 +2201,9 @@
     /**
      * Returns the model year of the GNSS hardware and software build.
      *
-     * May return 0 if the model year is less than 2016.
+     * <p> More details, such as build date, may be available in {@link #getGnssHardwareModelName()}.
+     *
+     * <p> May return 0 if the model year is less than 2016.
      */
     public int getGnssYearOfHardware() {
         try {
@@ -2190,10 +2217,12 @@
      * Returns the Model Name (including Vendor and Hardware/Software Version) of the GNSS hardware
      * driver.
      *
-     * Will return {@link LocationManager#GNSS_HARDWARE_MODEL_NAME_UNKNOWN} when the GNSS hardware
-     * abstraction layer does not support providing this value.
+     * <p> No device-specific serial number or ID is returned from this API.
+     *
+     * <p> Will return null when the GNSS hardware abstraction layer does not support providing
+     * this value.
      */
-    @NonNull
+    @Nullable
     public String getGnssHardwareModelName() {
         try {
             return mService.getGnssHardwareModelName();
diff --git a/location/lib/Android.mk b/location/lib/Android.mk
index 8424601..6642134 100644
--- a/location/lib/Android.mk
+++ b/location/lib/Android.mk
@@ -42,3 +42,25 @@
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 
 include $(BUILD_PREBUILT)
+
+# ==== Stub library  ===========================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.location.provider-stubs-gen
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_SRC_FILES := $(call all-java-files-under,java)
+LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/com.android.location.provider.stubs_intermediates/src
+LOCAL_DROIDDOC_OPTIONS:= \
+    -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 \
+    -stubpackages com.android.location.provider \
+    -nodocs
+LOCAL_UNINSTALLABLE_MODULE := true
+include $(BUILD_DROIDDOC)
+com_android_nfc_extras_gen_stamp := $(full_target)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.location.provider.stubs
+LOCAL_SOURCE_FILES_ALL_GENERATED := true
+LOCAL_SDK_VERSION := current
+LOCAL_ADDITIONAL_DEPENDENCIES := $(com_android_nfc_extras_gen_stamp)
+com_android_nfc_extras_gen_stamp :=
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/location/lib/java/com/android/location/provider/ActivityChangedEvent.java b/location/lib/java/com/android/location/provider/ActivityChangedEvent.java
index c7dfc88..843dd67 100644
--- a/location/lib/java/com/android/location/provider/ActivityChangedEvent.java
+++ b/location/lib/java/com/android/location/provider/ActivityChangedEvent.java
@@ -23,6 +23,7 @@
 
 /**
  * A class representing an event for Activity changes.
+ * @hide
  */
 public class ActivityChangedEvent {
     private final List<ActivityRecognitionEvent> mActivityRecognitionEvents;
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java b/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java
index a39cff2..e54dea4 100644
--- a/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java
@@ -18,6 +18,7 @@
 
 /**
  * A class that represents an Activity Recognition Event.
+ * @hide
  */
 public class ActivityRecognitionEvent {
     private final String mActivity;
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
index bc2dae1..0eff7d3 100644
--- a/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
@@ -28,6 +28,7 @@
 
 /**
  * A class that exposes {@link IActivityRecognitionHardware} functionality to unbundled services.
+ * @hide
  */
 public final class ActivityRecognitionProvider {
     private final IActivityRecognitionHardware mService;
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java
index 0b878d7..326d901 100644
--- a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java
@@ -27,6 +27,7 @@
 
 /**
  * A client class for interaction with an Activity-Recognition provider.
+ * @hide
  */
 public abstract class ActivityRecognitionProviderClient {
     private static final String TAG = "ArProviderClient";
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java
index 7139025..42f77b4 100644
--- a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java
@@ -30,6 +30,7 @@
  * A watcher class for Activity-Recognition instances.
  *
  * @deprecated use {@link ActivityRecognitionProviderClient} instead.
+ * @hide
  */
 @Deprecated
 public class ActivityRecognitionProviderWatcher {
diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardware.java b/location/lib/java/com/android/location/provider/FusedLocationHardware.java
deleted file mode 100644
index eb3b2f4..0000000
--- a/location/lib/java/com/android/location/provider/FusedLocationHardware.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (C) 2013 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.location.provider;
-
-import android.hardware.location.IFusedLocationHardware;
-import android.hardware.location.IFusedLocationHardwareSink;
-
-import android.location.Location;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Class that exposes IFusedLocationHardware functionality to unbundled services.
- */
-public final class FusedLocationHardware {
-    private static final String TAG = "FusedLocationHardware";
-
-    private IFusedLocationHardware mLocationHardware;
-
-    // the list uses a copy-on-write pattern to update its contents
-    HashMap<FusedLocationHardwareSink, DispatcherHandler> mSinkList =
-            new HashMap<FusedLocationHardwareSink, DispatcherHandler>();
-
-    private IFusedLocationHardwareSink mInternalSink = new IFusedLocationHardwareSink.Stub() {
-        @Override
-        public void onLocationAvailable(Location[] locations) {
-            dispatchLocations(locations);
-        }
-
-        @Override
-        public void onDiagnosticDataAvailable(String data) {
-            dispatchDiagnosticData(data);
-        }
-
-        @Override
-        public void onCapabilities(int capabilities) {
-            dispatchCapabilities(capabilities);
-        }
-
-        @Override
-        public void onStatusChanged(int status) {
-            dispatchStatus(status);
-        }
-    };
-
-    /**
-     * @hide
-     */
-    public FusedLocationHardware(IFusedLocationHardware locationHardware) {
-        mLocationHardware = locationHardware;
-    }
-
-    /*
-     * Methods to provide a Facade for IFusedLocationHardware
-     */
-    public void registerSink(FusedLocationHardwareSink sink, Looper looper) {
-        if(sink == null || looper == null) {
-            throw new IllegalArgumentException("Parameter sink and looper cannot be null.");
-        }
-
-        boolean registerSink;
-        synchronized (mSinkList) {
-            // register only on first insertion
-            registerSink = mSinkList.size() == 0;
-            // guarantee uniqueness
-            if(mSinkList.containsKey(sink)) {
-                return;
-            }
-
-            HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
-                    new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
-            newSinkList.put(sink, new DispatcherHandler(looper));
-            mSinkList = newSinkList;
-        }
-
-        if(registerSink) {
-            try {
-                mLocationHardware.registerSink(mInternalSink);
-            } catch(RemoteException e) {
-                Log.e(TAG, "RemoteException at registerSink");
-            }
-        }
-    }
-
-    public void unregisterSink(FusedLocationHardwareSink sink) {
-        if(sink == null) {
-            throw new IllegalArgumentException("Parameter sink cannot be null.");
-        }
-
-        boolean unregisterSink;
-        synchronized(mSinkList) {
-            if(!mSinkList.containsKey(sink)) {
-                //done
-                return;
-            }
-
-            HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
-                    new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
-            newSinkList.remove(sink);
-            //unregister after the last sink
-            unregisterSink = newSinkList.size() == 0;
-
-            mSinkList = newSinkList;
-        }
-
-        if(unregisterSink) {
-            try {
-                mLocationHardware.unregisterSink(mInternalSink);
-            } catch(RemoteException e) {
-                Log.e(TAG, "RemoteException at unregisterSink");
-            }
-        }
-    }
-
-    public int getSupportedBatchSize() {
-        try {
-            return mLocationHardware.getSupportedBatchSize();
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at getSupportedBatchSize");
-            return 0;
-        }
-    }
-
-    public void startBatching(int id, GmsFusedBatchOptions batchOptions) {
-        try {
-            mLocationHardware.startBatching(id, batchOptions.getParcelableOptions());
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at startBatching");
-        }
-    }
-
-    public void stopBatching(int id) {
-        try {
-            mLocationHardware.stopBatching(id);
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at stopBatching");
-        }
-    }
-
-    public void updateBatchingOptions(int id, GmsFusedBatchOptions batchOptions) {
-        try {
-            mLocationHardware.updateBatchingOptions(id, batchOptions.getParcelableOptions());
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at updateBatchingOptions");
-        }
-    }
-
-    public void requestBatchOfLocations(int batchSizeRequest) {
-        try {
-            mLocationHardware.requestBatchOfLocations(batchSizeRequest);
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at requestBatchOfLocations");
-        }
-    }
-
-    public void flushBatchedLocations() {
-        try {
-            mLocationHardware.flushBatchedLocations();
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at flushBatchedLocations");
-        }
-    }
-
-    public boolean supportsDiagnosticDataInjection() {
-        try {
-            return mLocationHardware.supportsDiagnosticDataInjection();
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at supportsDiagnisticDataInjection");
-            return false;
-        }
-    }
-
-    public void injectDiagnosticData(String data) {
-        try {
-            mLocationHardware.injectDiagnosticData(data);
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at injectDiagnosticData");
-        }
-    }
-
-    public boolean supportsDeviceContextInjection() {
-        try {
-            return mLocationHardware.supportsDeviceContextInjection();
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at supportsDeviceContextInjection");
-            return false;
-        }
-    }
-
-    public void injectDeviceContext(int deviceEnabledContext) {
-        try {
-            mLocationHardware.injectDeviceContext(deviceEnabledContext);
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at injectDeviceContext");
-        }
-    }
-
-
-    /**
-     * Returns the version of the FLP HAL.
-     *
-     * <p>Version 1 is the initial release.
-     * <p>Version 2 adds the ability to use {@link #flushBatchedLocations},
-     * {@link FusedLocationHardwareSink#onCapabilities}, and
-     * {@link FusedLocationHardwareSink#onStatusChanged}.
-     *
-     * <p>This method is only available on API 23 or later.  Older APIs have version 1.
-     */
-    public int getVersion() {
-        try {
-            return mLocationHardware.getVersion();
-        } catch(RemoteException e) {
-            Log.e(TAG, "RemoteException at getVersion");
-        }
-        return 1;
-    }
-
-    /*
-     * Helper methods and classes
-     */
-    private class DispatcherHandler extends Handler {
-        public static final int DISPATCH_LOCATION = 1;
-        public static final int DISPATCH_DIAGNOSTIC_DATA = 2;
-        public static final int DISPATCH_CAPABILITIES = 3;
-        public static final int DISPATCH_STATUS = 4;
-
-        public DispatcherHandler(Looper looper) {
-            super(looper, null /*callback*/ , true /*async*/);
-        }
-
-        @Override
-        public void handleMessage(Message message) {
-            MessageCommand command = (MessageCommand) message.obj;
-            switch(message.what) {
-                case DISPATCH_LOCATION:
-                    command.dispatchLocation();
-                    break;
-                case DISPATCH_DIAGNOSTIC_DATA:
-                    command.dispatchDiagnosticData();
-                    break;
-                case DISPATCH_CAPABILITIES:
-                    command.dispatchCapabilities();
-                    break;
-                case DISPATCH_STATUS:
-                    command.dispatchStatus();
-                    break;
-                default:
-                    Log.e(TAG, "Invalid dispatch message");
-                    break;
-            }
-        }
-    }
-
-    private class MessageCommand {
-        private final FusedLocationHardwareSink mSink;
-        private final Location[] mLocations;
-        private final String mData;
-        private final int mCapabilities;
-        private final int mStatus;
-
-        public MessageCommand(
-                FusedLocationHardwareSink sink,
-                Location[] locations,
-                String data,
-                int capabilities,
-                int status) {
-            mSink = sink;
-            mLocations = locations;
-            mData = data;
-            mCapabilities = capabilities;
-            mStatus = status;
-        }
-
-        public void dispatchLocation() {
-            mSink.onLocationAvailable(mLocations);
-        }
-
-        public void dispatchDiagnosticData() {
-            mSink.onDiagnosticDataAvailable(mData);
-        }
-
-        public void dispatchCapabilities() {
-            mSink.onCapabilities(mCapabilities);
-        }
-
-        public void dispatchStatus() {
-            mSink.onStatusChanged(mStatus);
-        }
-    }
-
-    private void dispatchLocations(Location[] locations) {
-        HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
-        synchronized (mSinkList) {
-            sinks = mSinkList;
-        }
-
-        for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
-            Message message = Message.obtain(
-                    entry.getValue(),
-                    DispatcherHandler.DISPATCH_LOCATION,
-                    new MessageCommand(entry.getKey(), locations, null /*data*/, 0, 0));
-            message.sendToTarget();
-        }
-    }
-
-    private void dispatchDiagnosticData(String data) {
-        HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
-        synchronized(mSinkList) {
-            sinks = mSinkList;
-        }
-
-        for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
-            Message message = Message.obtain(
-                    entry.getValue(),
-                    DispatcherHandler.DISPATCH_DIAGNOSTIC_DATA,
-                    new MessageCommand(entry.getKey(), null /*locations*/, data, 0, 0));
-            message.sendToTarget();
-        }
-    }
-
-    private void dispatchCapabilities(int capabilities) {
-        HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
-        synchronized(mSinkList) {
-            sinks = mSinkList;
-        }
-
-        for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
-            Message message = Message.obtain(
-                    entry.getValue(),
-                    DispatcherHandler.DISPATCH_CAPABILITIES,
-                    new MessageCommand(entry.getKey(), null /*locations*/, null, capabilities, 0));
-            message.sendToTarget();
-        }
-    }
-
-    private void dispatchStatus(int status) {
-        HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
-        synchronized(mSinkList) {
-            sinks = mSinkList;
-        }
-
-        for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
-            Message message = Message.obtain(
-                    entry.getValue(),
-                    DispatcherHandler.DISPATCH_STATUS,
-                    new MessageCommand(entry.getKey(), null /*locations*/, null, 0, status));
-            message.sendToTarget();
-        }
-    }
-}
diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java b/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
deleted file mode 100644
index 01d37ac..0000000
--- a/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2013 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.location.provider;
-
-import android.location.Location;
-
-/**
- * Base class for sinks to interact with FusedLocationHardware.
- *
- * <p>Default implementations allow new methods to be added without crashing
- * clients compiled against an old library version.
- */
-public class FusedLocationHardwareSink {
-    /**
-     * Called when one or more locations are available from the FLP
-     * HAL.
-     */
-    public void onLocationAvailable(Location[] locations) {
-        // default do nothing
-    }
-
-    /**
-     * Called when diagnostic data is available from the FLP HAL.
-     */
-    public void onDiagnosticDataAvailable(String data) {
-        // default do nothing
-    }
-
-    /**
-     * Called when capabilities are available from the FLP HAL.
-     * Should be called once right after initialization.
-     *
-     * @param capabilities A bitmask of capabilities defined in
-     *                     fused_location.h.
-     */
-    public void onCapabilities(int capabilities) {
-        // default do nothing
-    }
-
-    /**
-     * Called when the status changes in the underlying FLP HAL
-     * implementation (the ability to compute location).  This
-     * callback will only be made on version 2 or later
-     * (see {@link FusedLocationHardware#getVersion()}).
-     *
-     * @param status One of FLP_STATUS_LOCATION_AVAILABLE or
-     *               FLP_STATUS_LOCATION_UNAVAILABLE as defined in
-     *               fused_location.h.
-     */
-    public void onStatusChanged(int status) {
-        // default do nothing
-    }
-}
\ No newline at end of file
diff --git a/location/lib/java/com/android/location/provider/FusedProvider.java b/location/lib/java/com/android/location/provider/FusedProvider.java
index c966ade..78a593b 100644
--- a/location/lib/java/com/android/location/provider/FusedProvider.java
+++ b/location/lib/java/com/android/location/provider/FusedProvider.java
@@ -16,8 +16,6 @@
 
 package com.android.location.provider;
 
-import android.hardware.location.IFusedLocationHardware;
-import android.location.IFusedProvider;
 import android.os.IBinder;
 
 /**
@@ -26,17 +24,12 @@
  * <p>Fused providers can be implemented as services and return the result of
  * {@link com.android.location.provider.FusedProvider#getBinder()} in its getBinder() method.
  *
- * <p>IMPORTANT: This class is effectively a public API for unbundled applications, and must remain
- * API stable. See README.txt in the root of this package for more information.
+ * @deprecated This class should no longer be used. The location service does not uses this.
+ * This class exist here just to prevent existing apps having reference to this class from
+ * breaking.
  */
+@Deprecated
 public abstract class FusedProvider {
-    private IFusedProvider.Stub mProvider = new IFusedProvider.Stub() {
-        @Override
-        public void onFusedLocationHardwareChange(IFusedLocationHardware instance) {
-            setFusedLocationHardware(new FusedLocationHardware(instance));
-        }
-    };
-
     /**
      * Gets the Binder associated with the provider.
      * This is intended to be used for the onBind() method of a service that implements a fused
@@ -45,13 +38,6 @@
      * @return The IBinder instance associated with the provider.
      */
     public IBinder getBinder() {
-        return mProvider;
+        return null;
     }
-
-    /**
-     * Sets the FusedLocationHardware instance in the provider..
-     * @param value     The instance to set. This can be null in cases where the service connection
-     *                  is disconnected.
-     */
-    public abstract void setFusedLocationHardware(FusedLocationHardware value);
 }
diff --git a/location/lib/java/com/android/location/provider/GeocodeProvider.java b/location/lib/java/com/android/location/provider/GeocodeProvider.java
index d7a34af..f7f3d82 100644
--- a/location/lib/java/com/android/location/provider/GeocodeProvider.java
+++ b/location/lib/java/com/android/location/provider/GeocodeProvider.java
@@ -33,6 +33,7 @@
  * <p>IMPORTANT: This class is effectively a public API for unbundled
  * applications, and must remain API stable. See README.txt in the root
  * of this package for more information.
+ * @hide
  */
 public abstract class GeocodeProvider {
 
diff --git a/location/lib/java/com/android/location/provider/GeofenceProvider.java b/location/lib/java/com/android/location/provider/GeofenceProvider.java
index fafaa84..43690ab 100644
--- a/location/lib/java/com/android/location/provider/GeofenceProvider.java
+++ b/location/lib/java/com/android/location/provider/GeofenceProvider.java
@@ -31,6 +31,7 @@
  * <p>IMPORTANT: This class is effectively a public API for unbundled
  * applications, and must remain API stable. See README.txt in the root
  * of this package for more information.
+ * @hide
  */
 public abstract class GeofenceProvider {
 
diff --git a/location/lib/java/com/android/location/provider/GmsFusedBatchOptions.java b/location/lib/java/com/android/location/provider/GmsFusedBatchOptions.java
deleted file mode 100644
index 29818ec..0000000
--- a/location/lib/java/com/android/location/provider/GmsFusedBatchOptions.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2013 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.location.provider;
-
-import android.location.FusedBatchOptions;
-
-/**
- * Class that exposes FusedBatchOptions to the GmsCore .
- */
-public class GmsFusedBatchOptions {
-    private FusedBatchOptions mOptions = new FusedBatchOptions();
-
-    /*
-     * Methods that provide a facade for properties in FusedBatchOptions.
-     */
-    public void setMaxPowerAllocationInMW(double value) {
-        mOptions.setMaxPowerAllocationInMW(value);
-    }
-
-    public double getMaxPowerAllocationInMW() {
-        return mOptions.getMaxPowerAllocationInMW();
-    }
-
-    public void setPeriodInNS(long value) {
-        mOptions.setPeriodInNS(value);
-    }
-
-    public long getPeriodInNS() {
-        return mOptions.getPeriodInNS();
-    }
-
-    public void setSmallestDisplacementMeters(float value) {
-        mOptions.setSmallestDisplacementMeters(value);
-    }
-
-    public float getSmallestDisplacementMeters() {
-        return mOptions.getSmallestDisplacementMeters();
-    }
-
-    public void setSourceToUse(int source) {
-        mOptions.setSourceToUse(source);
-    }
-
-    public void resetSourceToUse(int source) {
-        mOptions.resetSourceToUse(source);
-    }
-
-    public boolean isSourceToUseSet(int source) {
-        return mOptions.isSourceToUseSet(source);
-    }
-
-    public int getSourcesToUse() {
-        return mOptions.getSourcesToUse();
-    }
-
-    public void setFlag(int flag) {
-        mOptions.setFlag(flag);
-    }
-
-    public void resetFlag(int flag) {
-        mOptions.resetFlag(flag);
-    }
-
-    public boolean isFlagSet(int flag) {
-        return mOptions.isFlagSet(flag);
-    }
-
-    public int getFlags() {
-        return mOptions.getFlags();
-    }
-
-    /**
-     * Definition of enum flag sets needed by this class.
-     * Such values need to be kept in sync with the ones in fused_location.h
-     */
-
-    public static final class SourceTechnologies {
-        public static int GNSS = 1<<0;
-        public static int WIFI = 1<<1;
-        public static int SENSORS = 1<<2;
-        public static int CELL = 1<<3;
-        public static int BLUETOOTH = 1<<4;
-    }
-
-    public static final class BatchFlags {
-        public static int WAKEUP_ON_FIFO_FULL = 1<<0;
-        public static int CALLBACK_ON_LOCATION_FIX = 1<<1;
-    }
-
-    /*
-     * Method definitions for internal use.
-     */
-
-    /*
-     * @hide
-     */
-    public FusedBatchOptions getParcelableOptions() {
-        return mOptions;
-    }
-}
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index d717f40..30655f5 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -56,6 +56,7 @@
 public abstract class LocationProviderBase {
     private final String TAG;
 
+    /** @hide */
     protected final ILocationManager mLocationManager;
     private final ProviderProperties mProperties;
     private final IBinder mBinder;
diff --git a/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java b/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java
index 9ee4df21..b1a1bda 100644
--- a/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java
+++ b/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java
@@ -41,6 +41,7 @@
         mProperties = properties;
     }
 
+    /** @hide */
     public ProviderProperties getProviderProperties() {
         return mProperties;
     }
diff --git a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
index ad3d1df..6a8e618 100644
--- a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
+++ b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
@@ -33,6 +33,7 @@
 public final class ProviderRequestUnbundled {
     private final ProviderRequest mRequest;
 
+    /** @hide */
     public ProviderRequestUnbundled(ProviderRequest request) {
         mRequest = request;
     }
diff --git a/media/java/android/media/AudioPresentation.java b/media/java/android/media/AudioPresentation.java
index 4652c18..e39cb7d 100644
--- a/media/java/android/media/AudioPresentation.java
+++ b/media/java/android/media/AudioPresentation.java
@@ -17,6 +17,9 @@
 package android.media;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -88,10 +91,14 @@
      */
     public static final int MASTERED_FOR_HEADPHONE          = 4;
 
-    AudioPresentation(int presentationId,
+    /**
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public AudioPresentation(int presentationId,
                         int programId,
-                        Map<String, String> labels,
-                        String language,
+                        @NonNull Map<String, String> labels,
+                        @NonNull String language,
                         @MasteringIndicationType int masteringIndication,
                         boolean audioDescriptionAvailable,
                         boolean spokenSubtitlesAvailable,
@@ -112,6 +119,7 @@
      * decoder. Presentation id is typically sequential, but does not have to be.
      * @hide
      */
+    @VisibleForTesting
     public int getPresentationId() {
         return mPresentationId;
     }
@@ -121,13 +129,14 @@
      * Program id can be used to further uniquely identify the presentation to a decoder.
      * @hide
      */
+    @VisibleForTesting
     public int getProgramId() {
         return mProgramId;
     }
 
     /**
      * @return a map of available text labels for this presentation. Each label is indexed by its
-     * locale corresponding to the language code as specified by ISO 639-2 [42]. Either ISO 639-2/B
+     * locale corresponding to the language code as specified by ISO 639-2. Either ISO 639-2/B
      * or ISO 639-2/T could be used.
      */
     public Map<Locale, String> getLabels() {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 2d5fad5..9c48e09 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -2012,9 +2012,10 @@
      * If the audio presentation is invalid then {@link #ERROR_BAD_VALUE} will be returned.
      * If a multi-stream decoder (MSD) is not present, or the format does not support
      * multiple presentations, then {@link #ERROR_INVALID_OPERATION} will be returned.
+     * {@link #ERROR} is returned in case of any other error.
      * @param presentation see {@link AudioPresentation}. In particular, id should be set.
-     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
-     *    {@link #ERROR_INVALID_OPERATION}
+     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR},
+     *    {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}
      * @throws IllegalArgumentException if the audio presentation is null.
      * @throws IllegalStateException if track is not initialized.
      */
diff --git a/media/java/android/media/MediaBrowser2.java b/media/java/android/media/MediaBrowser2.java
index cf33958..f246005 100644
--- a/media/java/android/media/MediaBrowser2.java
+++ b/media/java/android/media/MediaBrowser2.java
@@ -142,8 +142,8 @@
     @Override
     MediaBrowser2Provider createProvider(Context context, SessionToken2 token,
             Executor executor, ControllerCallback callback) {
-        return ApiLoader.getProvider(context)
-                .createMediaBrowser2(context, this, token, executor, (BrowserCallback) callback);
+        return ApiLoader.getProvider().createMediaBrowser2(
+                context, this, token, executor, (BrowserCallback) callback);
     }
 
     /**
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index 20c3209..14dcced 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -366,8 +366,8 @@
     MediaController2Provider createProvider(@NonNull Context context,
             @NonNull SessionToken2 token, @NonNull Executor executor,
             @NonNull ControllerCallback callback) {
-        return ApiLoader.getProvider(context)
-                .createMediaController2(context, this, token, executor, callback);
+        return ApiLoader.getProvider().createMediaController2(
+                context, this, token, executor, callback);
     }
 
     /**
diff --git a/media/java/android/media/MediaItem2.java b/media/java/android/media/MediaItem2.java
index b50c3e4..8d62bd4 100644
--- a/media/java/android/media/MediaItem2.java
+++ b/media/java/android/media/MediaItem2.java
@@ -81,7 +81,7 @@
     }
 
     public static MediaItem2 fromBundle(Context context, Bundle bundle) {
-        return ApiLoader.getProvider(context).fromBundle_MediaItem2(context, bundle);
+        return ApiLoader.getProvider().fromBundle_MediaItem2(context, bundle);
     }
 
     public String toString() {
@@ -164,8 +164,7 @@
          * @param flags
          */
         public Builder(@NonNull Context context, @Flags int flags) {
-            mProvider = ApiLoader.getProvider(context).createMediaItem2Builder(
-                    context, this, flags);
+            mProvider = ApiLoader.getProvider().createMediaItem2Builder(context, this, flags);
         }
 
         /**
diff --git a/media/java/android/media/MediaLibraryService2.java b/media/java/android/media/MediaLibraryService2.java
index 6cab430..f3684d6 100644
--- a/media/java/android/media/MediaLibraryService2.java
+++ b/media/java/android/media/MediaLibraryService2.java
@@ -210,9 +210,8 @@
             public Builder(@NonNull MediaLibraryService2 service,
                     @NonNull @CallbackExecutor Executor callbackExecutor,
                     @NonNull MediaLibrarySessionCallback callback) {
-                super((instance) -> ApiLoader.getProvider(service)
-                        .createMediaLibraryService2Builder(service, (Builder) instance,
-                                callbackExecutor, callback));
+                super((instance) -> ApiLoader.getProvider().createMediaLibraryService2Builder(
+                        service, (Builder) instance, callbackExecutor, callback));
             }
 
             @Override
@@ -309,7 +308,7 @@
 
     @Override
     MediaSessionService2Provider createProvider() {
-        return ApiLoader.getProvider(this).createMediaLibraryService2(this);
+        return ApiLoader.getProvider().createMediaLibraryService2(this);
     }
 
     /**
@@ -403,7 +402,7 @@
          */
         public LibraryRoot(@NonNull Context context,
                 @NonNull String rootId, @Nullable Bundle extras) {
-            mProvider = ApiLoader.getProvider(context).createMediaLibraryService2LibraryRoot(
+            mProvider = ApiLoader.getProvider().createMediaLibraryService2LibraryRoot(
                     context, this, rootId, extras);
         }
 
diff --git a/media/java/android/media/MediaMetadata2.java b/media/java/android/media/MediaMetadata2.java
index fb12065..2ba66b2 100644
--- a/media/java/android/media/MediaMetadata2.java
+++ b/media/java/android/media/MediaMetadata2.java
@@ -684,7 +684,7 @@
      */
     public static @NonNull MediaMetadata2 fromBundle(@NonNull Context context,
             @Nullable Bundle bundle) {
-        return ApiLoader.getProvider(context).fromBundle_MediaMetadata2(context, bundle);
+        return ApiLoader.getProvider().fromBundle_MediaMetadata2(context, bundle);
     }
 
     /**
@@ -699,8 +699,7 @@
          * {@link MediaMetadata2} must be added.
          */
         public Builder(@NonNull Context context) {
-            mProvider = ApiLoader.getProvider(context).createMediaMetadata2Builder(
-                    context, this);
+            mProvider = ApiLoader.getProvider().createMediaMetadata2Builder(context, this);
         }
 
         /**
@@ -711,8 +710,7 @@
          * @param source
          */
         public Builder(@NonNull Context context, @NonNull MediaMetadata2 source) {
-            mProvider = ApiLoader.getProvider(context).createMediaMetadata2Builder(
-                    context, this, source);
+            mProvider = ApiLoader.getProvider().createMediaMetadata2Builder(context, this, source);
         }
 
         /**
diff --git a/media/java/android/media/MediaPlaylistAgent.java b/media/java/android/media/MediaPlaylistAgent.java
index 6b3620b..1250810 100644
--- a/media/java/android/media/MediaPlaylistAgent.java
+++ b/media/java/android/media/MediaPlaylistAgent.java
@@ -148,7 +148,7 @@
     }
 
     public MediaPlaylistAgent(@NonNull Context context) {
-        mProvider = ApiLoader.getProvider(context).createMediaPlaylistAgent(context, this);
+        mProvider = ApiLoader.getProvider().createMediaPlaylistAgent(context, this);
     }
 
     /**
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index 6647831..472d942 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -431,16 +431,16 @@
         private final CommandProvider mProvider;
 
         public Command(@NonNull Context context, int commandCode) {
-            mProvider = ApiLoader.getProvider(context)
-                    .createMediaSession2Command(this, commandCode, null, null);
+            mProvider = ApiLoader.getProvider().createMediaSession2Command(
+                    this, commandCode, null, null);
         }
 
         public Command(@NonNull Context context, @NonNull String action, @Nullable Bundle extras) {
             if (action == null) {
                 throw new IllegalArgumentException("action shouldn't be null");
             }
-            mProvider = ApiLoader.getProvider(context)
-                    .createMediaSession2Command(this, COMMAND_CODE_CUSTOM, action, extras);
+            mProvider = ApiLoader.getProvider().createMediaSession2Command(
+                    this, COMMAND_CODE_CUSTOM, action, extras);
         }
 
         /**
@@ -488,7 +488,7 @@
          * @hide
          */
         public static Command fromBundle(@NonNull Context context, @NonNull Bundle command) {
-            return ApiLoader.getProvider(context).fromBundle_MediaSession2Command(context, command);
+            return ApiLoader.getProvider().fromBundle_MediaSession2Command(context, command);
         }
     }
 
@@ -499,13 +499,13 @@
         private final CommandGroupProvider mProvider;
 
         public CommandGroup(@NonNull Context context) {
-            mProvider = ApiLoader.getProvider(context)
-                    .createMediaSession2CommandGroup(context, this, null);
+            mProvider = ApiLoader.getProvider().createMediaSession2CommandGroup(
+                    context, this, null);
         }
 
         public CommandGroup(@NonNull Context context, @Nullable CommandGroup others) {
-            mProvider = ApiLoader.getProvider(context)
-                    .createMediaSession2CommandGroup(context, this, others);
+            mProvider = ApiLoader.getProvider().createMediaSession2CommandGroup(
+                    context, this, others);
         }
 
         /**
@@ -559,8 +559,7 @@
          * @hide
          */
         public static @Nullable CommandGroup fromBundle(Context context, Bundle commands) {
-            return ApiLoader.getProvider(context)
-                    .fromBundle_MediaSession2CommandGroup(context, commands);
+            return ApiLoader.getProvider().fromBundle_MediaSession2CommandGroup(context, commands);
         }
     }
 
@@ -1010,7 +1009,7 @@
     // This workarounds javadoc issue described in the MediaSession2.BuilderBase.
     public static final class Builder extends BuilderBase<MediaSession2, Builder, SessionCallback> {
         public Builder(Context context) {
-            super((instance) -> ApiLoader.getProvider(context).createMediaSession2Builder(
+            super((instance) -> ApiLoader.getProvider().createMediaSession2Builder(
                     context, (Builder) instance));
         }
 
@@ -1062,9 +1061,8 @@
          */
         public ControllerInfo(@NonNull Context context, int uid, int pid,
                 @NonNull String packageName, @NonNull IInterface callback) {
-            mProvider = ApiLoader.getProvider(context)
-                    .createMediaSession2ControllerInfo(
-                            context, this, uid, pid, packageName, callback);
+            mProvider = ApiLoader.getProvider().createMediaSession2ControllerInfo(
+                    context, this, uid, pid, packageName, callback);
         }
 
         /**
@@ -1192,8 +1190,8 @@
             private final CommandButtonProvider.BuilderProvider mProvider;
 
             public Builder(@NonNull Context context) {
-                mProvider = ApiLoader.getProvider(context)
-                        .createMediaSession2CommandButtonBuilder(context, this);
+                mProvider = ApiLoader.getProvider().createMediaSession2CommandButtonBuilder(
+                        context, this);
             }
 
             public @NonNull Builder setCommand(@Nullable Command command) {
diff --git a/media/java/android/media/MediaSessionService2.java b/media/java/android/media/MediaSessionService2.java
index 32caf4b..b830694 100644
--- a/media/java/android/media/MediaSessionService2.java
+++ b/media/java/android/media/MediaSessionService2.java
@@ -123,7 +123,7 @@
     }
 
     MediaSessionService2Provider createProvider() {
-        return ApiLoader.getProvider(this).createMediaSessionService2(this);
+        return ApiLoader.getProvider().createMediaSessionService2(this);
     }
 
     /**
@@ -220,9 +220,8 @@
          */
         public MediaNotification(@NonNull Context context,
                 int notificationId, @NonNull Notification notification) {
-            mProvider = ApiLoader.getProvider(context)
-                    .createMediaSessionService2MediaNotification(
-                            context, this, notificationId, notification);
+            mProvider = ApiLoader.getProvider().createMediaSessionService2MediaNotification(
+                    context, this, notificationId, notification);
         }
 
         public int getNotificationId() {
diff --git a/media/java/android/media/Rating2.java b/media/java/android/media/Rating2.java
index 29bd922..5f7a334 100644
--- a/media/java/android/media/Rating2.java
+++ b/media/java/android/media/Rating2.java
@@ -131,7 +131,7 @@
      * @return new Rating2 instance or {@code null} for error
      */
     public static Rating2 fromBundle(@NonNull Context context, @Nullable Bundle bundle) {
-        return ApiLoader.getProvider(context).fromBundle_Rating2(context, bundle);
+        return ApiLoader.getProvider().fromBundle_Rating2(context, bundle);
     }
 
     /**
@@ -154,7 +154,7 @@
      */
     public static @Nullable Rating2 newUnratedRating(@NonNull Context context,
             @Style int ratingStyle) {
-        return ApiLoader.getProvider(context).newUnratedRating_Rating2(context, ratingStyle);
+        return ApiLoader.getProvider().newUnratedRating_Rating2(context, ratingStyle);
     }
 
     /**
@@ -166,7 +166,7 @@
      * @return a new Rating2 instance.
      */
     public static @Nullable Rating2 newHeartRating(@NonNull Context context, boolean hasHeart) {
-        return ApiLoader.getProvider(context).newHeartRating_Rating2(context, hasHeart);
+        return ApiLoader.getProvider().newHeartRating_Rating2(context, hasHeart);
     }
 
     /**
@@ -178,7 +178,7 @@
      * @return a new Rating2 instance.
      */
     public static @Nullable Rating2 newThumbRating(@NonNull Context context, boolean thumbIsUp) {
-        return ApiLoader.getProvider(context).newThumbRating_Rating2(context, thumbIsUp);
+        return ApiLoader.getProvider().newThumbRating_Rating2(context, thumbIsUp);
     }
 
     /**
@@ -196,8 +196,7 @@
      */
     public static @Nullable Rating2 newStarRating(@NonNull Context context,
             @StarStyle int starRatingStyle, float starRating) {
-        return ApiLoader.getProvider(context).newStarRating_Rating2(
-                context, starRatingStyle, starRating);
+        return ApiLoader.getProvider().newStarRating_Rating2(context, starRatingStyle, starRating);
     }
 
     /**
@@ -209,7 +208,7 @@
      * @return null if the rating is out of range, a new Rating2 instance otherwise.
      */
     public static @Nullable Rating2 newPercentageRating(@NonNull Context context, float percent) {
-        return ApiLoader.getProvider(context).newPercentageRating_Rating2(context, percent);
+        return ApiLoader.getProvider().newPercentageRating_Rating2(context, percent);
     }
 
     /**
diff --git a/media/java/android/media/SessionToken2.java b/media/java/android/media/SessionToken2.java
index fdfa43a..68a5641 100644
--- a/media/java/android/media/SessionToken2.java
+++ b/media/java/android/media/SessionToken2.java
@@ -80,7 +80,7 @@
      */
     public SessionToken2(@NonNull Context context, @NonNull String packageName,
             @NonNull String serviceName, int uid) {
-        mProvider = ApiLoader.getProvider(context).createSessionToken2(
+        mProvider = ApiLoader.getProvider().createSessionToken2(
                 context, this, packageName, serviceName, uid);
     }
 
@@ -150,7 +150,7 @@
      * @return
      */
     public static SessionToken2 fromBundle(@NonNull Context context, @NonNull Bundle bundle) {
-        return ApiLoader.getProvider(context).fromBundle_SessionToken2(context, bundle);
+        return ApiLoader.getProvider().fromBundle_SessionToken2(context, bundle);
     }
 
     /**
diff --git a/media/java/android/media/VolumeProvider2.java b/media/java/android/media/VolumeProvider2.java
index 711f51f..8501924 100644
--- a/media/java/android/media/VolumeProvider2.java
+++ b/media/java/android/media/VolumeProvider2.java
@@ -76,7 +76,7 @@
      */
     public VolumeProvider2(@NonNull Context context, @ControlType int controlType,
             int maxVolume, int currentVolume) {
-        mProvider = ApiLoader.getProvider(context).createVolumeProvider2(
+        mProvider = ApiLoader.getProvider().createVolumeProvider2(
                 context, this, controlType, maxVolume, currentVolume);
     }
 
diff --git a/media/java/android/media/update/ApiLoader.java b/media/java/android/media/update/ApiLoader.java
index cf18bdd..6f82f68 100644
--- a/media/java/android/media/update/ApiLoader.java
+++ b/media/java/android/media/update/ApiLoader.java
@@ -46,11 +46,6 @@
 
     private ApiLoader() { }
 
-    @Deprecated
-    public static StaticProvider getProvider(Context context) {
-        return getProvider();
-    }
-
     public static StaticProvider getProvider() {
         if (sMediaUpdatable != null) return sMediaUpdatable;
 
@@ -79,7 +74,7 @@
             ActivityManager.getService().addPackageDependency(ai.packageName);
         }
 
-        PathClassLoader classLoader = new PathClassLoader(ai.sourceDir,
+        ClassLoader classLoader = new PathClassLoader(ai.sourceDir,
                 ai.nativeLibraryDir + File.pathSeparator + System.getProperty("java.library.path"),
                 ClassLoader.getSystemClassLoader().getParent());
         return sMediaUpdatable = (StaticProvider) classLoader.loadClass(UPDATE_CLASS)
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 23ef84f6..12d7440 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -39,6 +39,7 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
 #include <jni.h>
+#include <media/stagefright/NuMediaExtractor.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedLocalRef.h>
 
@@ -788,6 +789,41 @@
     return exif_get_long(e->data, o);
 }
 
+static ExifData *getExifFromExtractor(const char *path) {
+    std::unique_ptr<uint8_t[]> exifBuf;
+    ExifData *exifdata = NULL;
+
+    FILE *fp = fopen (path, "rb");
+    if (!fp) {
+        ALOGE("failed to open file");
+        return NULL;
+    }
+
+    sp<NuMediaExtractor> extractor = new NuMediaExtractor();
+    fseek(fp, 0L, SEEK_END);
+    if (extractor->setDataSource(fileno(fp), 0, ftell(fp)) != OK) {
+        ALOGE("failed to setDataSource");
+        fclose(fp);
+        return NULL;
+    }
+
+    off64_t offset;
+    size_t size;
+    if (extractor->getExifOffsetSize(&offset, &size) != OK) {
+        fclose(fp);
+        return NULL;
+    }
+
+    exifBuf.reset(new uint8_t[size]);
+    fseek(fp, offset, SEEK_SET);
+    if (fread(exifBuf.get(), 1, size, fp) == size) {
+        exifdata = exif_data_new_from_data(exifBuf.get(), size);
+    }
+
+    fclose(fp);
+    return exifdata;
+}
+
 MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
                                              MtpObjectInfo& info) {
     MtpString       path;
@@ -834,7 +870,12 @@
         case MTP_FORMAT_EXIF_JPEG:
         case MTP_FORMAT_HEIF:
         case MTP_FORMAT_JFIF: {
-            ExifData *exifdata = exif_data_new_from_file(path);
+            ExifData *exifdata;
+            if (info.mFormat == MTP_FORMAT_HEIF) {
+                exifdata = getExifFromExtractor(path);
+            } else {
+                exifdata = exif_data_new_from_file(path);
+            }
             if (exifdata) {
                 if ((false)) {
                     exif_data_foreach_content(exifdata, foreachcontent, NULL);
@@ -892,7 +933,12 @@
             case MTP_FORMAT_EXIF_JPEG:
             case MTP_FORMAT_HEIF:
             case MTP_FORMAT_JFIF: {
-                ExifData *exifdata = exif_data_new_from_file(path);
+                ExifData *exifdata;
+                if (format == MTP_FORMAT_HEIF) {
+                    exifdata = getExifFromExtractor(path);
+                } else {
+                    exifdata = exif_data_new_from_file(path);
+                }
                 if (exifdata) {
                     if (exifdata->data) {
                         result = malloc(exifdata->size);
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 589608a..98ef62ad7 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1093,4 +1093,7 @@
     <string name="zen_mode_duration_settings_title">Duration</string>
     <!-- Do not disturb: Duration option to always prompt for the duration of dnd -->
     <string name="zen_mode_duration_always_prompt_title">Ask every time</string>
+
+    <!-- time label for event have that happened very recently [CHAR LIMIT=60] -->
+    <string name="time_unit_just_now">Just now</string>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
new file mode 100644
index 0000000..e2c7747
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 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.settingslib.fuelgauge;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.PowerManager;
+import android.provider.Settings.Secure;
+import android.util.Log;
+
+/**
+ * Utilities related to battery saver.
+ */
+public class BatterySaverUtils {
+    private static final String TAG = "BatterySaverUtils";
+
+    private BatterySaverUtils() {
+    }
+
+    private static final boolean DEBUG = false;
+
+    // Broadcast action for SystemUI to show the battery saver confirmation dialog.
+    public static final String ACTION_SHOW_START_SAVER_CONFIRMATION = "PNW.startSaverConfirmation";
+
+    /**
+     * Enable / disable battery saver by user request.
+     * - If it's the first time and needFirstTimeWarning, show the first time dialog.
+     * - If it's 4th time through 8th time, show the schedule suggestion notification.
+     *
+     * @param enable true to disable battery saver.
+     *
+     * @return true if the request succeeded.
+     */
+    public static synchronized boolean setPowerSaveMode(Context context,
+            boolean enable, boolean needFirstTimeWarning) {
+        if (DEBUG) {
+            Log.d(TAG, "Battery saver turning " + (enable ? "ON" : "OFF"));
+        }
+        final ContentResolver cr = context.getContentResolver();
+
+        if (enable && needFirstTimeWarning && maybeShowBatterySaverConfirmation(context)) {
+            return false;
+        }
+        if (enable && !needFirstTimeWarning) {
+            setBatterySaverConfirmationAcknowledged(context);
+        }
+
+        if (context.getSystemService(PowerManager.class).setPowerSaveMode(enable)) {
+            if (enable) {
+                Secure.putInt(cr, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT,
+                        Secure.getInt(cr, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 0) + 1);
+
+                // TODO If enabling, and the count is between 4 and 8 (inclusive), then
+                // show the "battery saver schedule suggestion" notification.
+            }
+
+            return true;
+        }
+        return false;
+    }
+
+    private static boolean maybeShowBatterySaverConfirmation(Context context) {
+        if (Secure.getInt(context.getContentResolver(),
+                Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 0) != 0) {
+            return false; // Already shown.
+        }
+        final Intent i = new Intent(ACTION_SHOW_START_SAVER_CONFIRMATION);
+        context.sendBroadcast(i);
+
+        return true;
+    }
+
+    private static void setBatterySaverConfirmationAcknowledged(Context context) {
+        Secure.putInt(context.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
new file mode 100644
index 0000000..cc69e0e
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2018 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.settingslib.users;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import com.android.internal.util.UserIcons;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Helper class for managing users, providing methods for removing, adding and switching users.
+ */
+public final class UserManagerHelper {
+    private static final String TAG = "UserManagerHelper";
+    private final Context mContext;
+    private final UserManager mUserManager;
+    private OnUsersUpdateListener mUpdateListener;
+    private final BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mUpdateListener.onUsersUpdate();
+        }
+    };
+
+    public UserManagerHelper(Context context) {
+        mContext = context;
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+    }
+
+    /**
+     * Registers a listener for updates to all users - removing, adding users or changing user info.
+     *
+     * @param listener Instance of {@link OnUsersUpdateListener}.
+     */
+    public void registerOnUsersUpdateListener(OnUsersUpdateListener listener) {
+        mUpdateListener = listener;
+        registerReceiver();
+    }
+
+    /**
+     * Unregisters listener by unregistering {@code BroadcastReceiver}.
+     */
+    public void unregisterOnUsersUpdateListener() {
+        unregisterReceiver();
+    }
+
+    /**
+     * Gets {@link UserInfo} for the current user.
+     *
+     * @return {@link UserInfo} for the current user.
+     */
+    public UserInfo getCurrentUserInfo() {
+        return mUserManager.getUserInfo(UserHandle.myUserId());
+    }
+
+    /**
+     * Gets all the other users on the system that are not the current user.
+     *
+     * @return List of {@code UserInfo} for each user that is not the current user.
+     */
+    public List<UserInfo> getAllUsersExcludesCurrentUser() {
+        List<UserInfo> others = mUserManager.getUsers(true);
+
+        for (Iterator<UserInfo> iterator = others.iterator(); iterator.hasNext(); ) {
+            UserInfo userInfo = iterator.next();
+            if (userInfo.id == UserHandle.myUserId()) {
+                // Remove current user from the list.
+                iterator.remove();
+            }
+        }
+        return others;
+    }
+
+    // User information accessors
+
+    /**
+     * Checks whether the user is system user (admin).
+     *
+     * @param userInfo User to check against system user.
+     * @return {@code true} if system user, {@code false} otherwise.
+     */
+    public boolean userIsSystemUser(UserInfo userInfo) {
+        return userInfo.id == UserHandle.USER_SYSTEM;
+    }
+
+    /**
+     * Returns whether this user can be removed from the system.
+     *
+     * @param userInfo User to be removed
+     * @return {@code true} if they can be removed, {@code false} otherwise.
+     */
+    public boolean userCanBeRemoved(UserInfo userInfo) {
+        return !userIsSystemUser(userInfo);
+    }
+
+    /**
+     * Checks whether passed in user is the user that's currently logged in.
+     *
+     * @param userInfo User to check.
+     * @return {@code true} if current user, {@code false} otherwise.
+     */
+    public boolean userIsCurrentUser(UserInfo userInfo) {
+        return getCurrentUserInfo().id == userInfo.id;
+    }
+
+    // Current user information accessors
+
+    /**
+     * Checks if the current user is a demo user.
+     */
+    public boolean isDemoUser() {
+        return mUserManager.isDemoUser();
+    }
+
+    /**
+     * Checks if the current user is a guest user.
+     */
+    public boolean isGuestUser() {
+        return mUserManager.isGuestUser();
+    }
+
+    /**
+     * Checks if the current user is the system user (User 0).
+     */
+    public boolean isSystemUser() {
+        return mUserManager.isSystemUser();
+    }
+
+    // Current user restriction accessors
+
+    /**
+     * Return whether the current user has a restriction.
+     *
+     * @param restriction Restriction to check. Should be a UserManager.* restriction.
+     * @return Whether that restriction exists for the current user.
+     */
+    public boolean hasUserRestriction(String restriction) {
+        return mUserManager.hasUserRestriction(restriction);
+    }
+
+    /**
+     * Checks if the current user can add new users.
+     */
+    public boolean canAddUsers() {
+        return !hasUserRestriction(UserManager.DISALLOW_ADD_USER);
+    }
+
+    /**
+     * Checks if the current user can remove users.
+     */
+    public boolean canRemoveUsers() {
+        return !hasUserRestriction(UserManager.DISALLOW_REMOVE_USER);
+    }
+
+    /**
+     * Checks if the current user is allowed to switch to another user.
+     */
+    public boolean canSwitchUsers() {
+        return !hasUserRestriction(UserManager.DISALLOW_USER_SWITCH);
+    }
+
+    /**
+     * Checks if the current user can modify accounts. Demo and Guest users cannot modify accounts
+     * even if the DISALLOW_MODIFY_ACCOUNTS restriction is not applied.
+     */
+    public boolean canModifyAccounts() {
+        return !hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS) && !isDemoUser()
+                && !isGuestUser();
+    }
+
+    // User actions
+
+    /**
+     * Creates a new user on the system.
+     *
+     * @param userName Name to give to the newly created user.
+     * @return Newly created user.
+     */
+    public UserInfo createNewUser(String userName) {
+        UserInfo user = mUserManager.createUser(userName, 0 /* flags */);
+        if (user == null) {
+            // Couldn't create user, most likely because there are too many, but we haven't
+            // been able to reload the list yet.
+            Log.w(TAG, "can't create user.");
+            return null;
+        }
+        assignDefaultIcon(user);
+        return user;
+    }
+
+    /**
+     * Tries to remove the user that's passed in. System user cannot be removed.
+     * If the user to be removed is current user, it switches to the system user first, and then
+     * removes the user.
+     *
+     * @param userInfo User to be removed
+     * @return {@code true} if user is successfully removed, {@code false} otherwise.
+     */
+    public boolean removeUser(UserInfo userInfo) {
+        if (userInfo.id == UserHandle.USER_SYSTEM) {
+            Log.w(TAG, "User " + userInfo.id + " is system user, could not be removed.");
+            return false;
+        }
+
+        if (userInfo.id == getCurrentUserInfo().id) {
+            switchToUserId(UserHandle.USER_SYSTEM);
+        }
+
+        return mUserManager.removeUser(userInfo.id);
+    }
+
+    /**
+     * Switches (logs in) to another user.
+     *
+     * @param userInfo User to switch to.
+     */
+    public void switchToUser(UserInfo userInfo) {
+        if (userInfo.id == getCurrentUserInfo().id) {
+            return;
+        }
+
+        if (userInfo.isGuest()) {
+            switchToGuest(userInfo.name);
+            return;
+        }
+
+        if (UserManager.isGuestUserEphemeral()) {
+            // If switching from guest, we want to bring up the guest exit dialog instead of
+            // switching
+            UserInfo currUserInfo = getCurrentUserInfo();
+            if (currUserInfo != null && currUserInfo.isGuest()) {
+                return;
+            }
+        }
+
+        switchToUserId(userInfo.id);
+    }
+
+    /**
+     * Creates a guest session and switches into the guest session.
+     *
+     * @param guestName Username for the guest user.
+     */
+    public void switchToGuest(String guestName) {
+        UserInfo guest = mUserManager.createGuest(mContext, guestName);
+        if (guest == null) {
+            // Couldn't create user, most likely because there are too many, but we haven't
+            // been able to reload the list yet.
+            Log.w(TAG, "can't create user.");
+            return;
+        }
+        switchToUserId(guest.id);
+    }
+
+    /**
+     * Gets an icon for the user.
+     *
+     * @param userInfo User for which we want to get the icon.
+     * @return a Bitmap for the icon
+     */
+    public Bitmap getUserIcon(UserInfo userInfo) {
+        Bitmap picture = mUserManager.getUserIcon(userInfo.id);
+
+        if (picture == null) {
+            return assignDefaultIcon(userInfo);
+        }
+
+        return picture;
+    }
+
+    /**
+     * Method for scaling a Bitmap icon to a desirable size.
+     *
+     * @param icon Bitmap to scale.
+     * @param desiredSize Wanted size for the icon.
+     * @return Drawable for the icon, scaled to the new size.
+     */
+    public Drawable scaleUserIcon(Bitmap icon, int desiredSize) {
+        Bitmap scaledIcon = Bitmap.createScaledBitmap(
+                icon, desiredSize, desiredSize, true /* filter */);
+        return new BitmapDrawable(mContext.getResources(), scaledIcon);
+    }
+
+    /**
+     * Sets new Username for the user.
+     *
+     * @param user User whose name should be changed.
+     * @param name New username.
+     */
+    public void setUserName(UserInfo user, String name) {
+        mUserManager.setUserName(user.id, name);
+    }
+
+    private void registerReceiver() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_USER_REMOVED);
+        filter.addAction(Intent.ACTION_USER_ADDED);
+        filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+        mContext.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null, null);
+    }
+
+    /**
+     * Assigns a default icon to a user according to the user's id.
+     *
+     * @param userInfo User to assign a default icon to.
+     * @return Bitmap that has been assigned to the user.
+     */
+    private Bitmap assignDefaultIcon(UserInfo userInfo) {
+        Bitmap bitmap = UserIcons.convertToBitmap(
+                UserIcons.getDefaultUserIcon(mContext.getResources(), userInfo.id, false));
+        mUserManager.setUserIcon(userInfo.id, bitmap);
+        return bitmap;
+    }
+
+    private void switchToUserId(int id) {
+        try {
+            final ActivityManager am = (ActivityManager)
+                    mContext.getSystemService(Context.ACTIVITY_SERVICE);
+            am.switchUser(id);
+        } catch (Exception e) {
+            Log.e(TAG, "Couldn't switch user.", e);
+        }
+    }
+
+    private void unregisterReceiver() {
+        mContext.unregisterReceiver(mUserChangeReceiver);
+    }
+
+    /**
+     * Interface for listeners that want to register for receiving updates to changes to the users
+     * on the system including removing and adding users, and changing user info.
+     */
+    public interface OnUsersUpdateListener {
+        /**
+         * Method that will get called when users list has been changed.
+         */
+        void onUsersUpdate();
+    }
+}
+
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
index 68be2b4..81a2d43 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/StringUtil.java
@@ -27,6 +27,9 @@
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.style.TtsSpan;
+
+import com.android.settingslib.R;
+
 import java.util.ArrayList;
 import java.util.Locale;
 
@@ -121,8 +124,7 @@
         final RelativeUnit unit;
         final int value;
         if (withSeconds && seconds < 2 * SECONDS_PER_MINUTE) {
-            unit = RelativeUnit.SECONDS;
-            value = seconds;
+            return context.getResources().getString(R.string.time_unit_just_now);
         } else if (seconds < 2 * SECONDS_PER_HOUR) {
             unit = RelativeUnit.MINUTES;
             value = (seconds + SECONDS_PER_MINUTE / 2)
@@ -141,7 +143,7 @@
         final RelativeDateTimeFormatter formatter = RelativeDateTimeFormatter.getInstance(
                 ULocale.forLocale(locale),
                 null /* default NumberFormat */,
-                RelativeDateTimeFormatter.Style.SHORT,
+                RelativeDateTimeFormatter.Style.LONG,
                 android.icu.text.DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE);
 
         return formatter.format(value, RelativeDateTimeFormatter.Direction.LAST, unit);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
index fd48eea..61efabc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
@@ -76,7 +76,8 @@
      * ["rssi 5Ghz", "num results on 5GHz" / "rssi 5Ghz", "num results on 5GHz"]
      * For instance [-40,5/-30,2]
      */
-    private static String getVisibilityStatus(AccessPoint accessPoint) {
+    @VisibleForTesting
+    static String getVisibilityStatus(AccessPoint accessPoint) {
         final WifiInfo info = accessPoint.getInfo();
         StringBuilder visibility = new StringBuilder();
         StringBuilder scans24GHz = new StringBuilder();
@@ -110,6 +111,9 @@
         // TODO: sort list by RSSI or age
         long nowMs = SystemClock.elapsedRealtime();
         for (ScanResult result : accessPoint.getScanResults()) {
+            if (result == null) {
+                continue;
+            }
             if (result.frequency >= AccessPoint.LOWER_FREQ_5GHZ
                     && result.frequency <= AccessPoint.HIGHER_FREQ_5GHZ) {
                 // Strictly speaking: [4915, 5825]
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
new file mode 100644
index 0000000..325ef3a
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2018 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.settingslib.users;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class UserManagerHelperTest {
+    @Mock
+    private Context mContext;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private ActivityManager mActivityManager;
+    @Mock
+    private UserManagerHelper.OnUsersUpdateListener mTestListener;
+
+    private UserManagerHelper mHelper;
+    private UserInfo mCurrentUser;
+    private UserInfo mSystemUser;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager);
+        when(mContext.getResources())
+                .thenReturn(InstrumentationRegistry.getTargetContext().getResources());
+        mHelper = new UserManagerHelper(mContext);
+
+        mCurrentUser = createUserInfoForId(UserHandle.myUserId());
+        mSystemUser = createUserInfoForId(UserHandle.USER_SYSTEM);
+        when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(mCurrentUser);
+    }
+
+    @Test
+    public void testUserIsSystemUser() {
+        UserInfo testInfo = new UserInfo();
+
+        testInfo.id = UserHandle.USER_SYSTEM;
+        assertThat(mHelper.userIsSystemUser(testInfo)).isTrue();
+
+        testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
+        assertThat(mHelper.userIsSystemUser(testInfo)).isFalse();
+    }
+
+    @Test
+    public void testGetAllUsersExcludesCurrentUser() {
+        int currentUser = UserHandle.myUserId();
+
+        UserInfo otherUser1 = createUserInfoForId(currentUser + 1);
+        UserInfo otherUser2 = createUserInfoForId(currentUser - 1);
+        UserInfo otherUser3 = createUserInfoForId(currentUser + 2);
+
+        List<UserInfo> testUsers = new ArrayList<>();
+        testUsers.add(otherUser1);
+        testUsers.add(otherUser2);
+        testUsers.add(mCurrentUser);
+        testUsers.add(otherUser3);
+
+        when(mUserManager.getUsers(true)).thenReturn(testUsers);
+
+        // Should return 3 users that don't have currentUser id.
+        assertThat(mHelper.getAllUsersExcludesCurrentUser().size()).isEqualTo(3);
+        // Should not contain current user.
+        assertThat(mHelper.getAllUsersExcludesCurrentUser()).doesNotContain(mCurrentUser);
+        // Should contain non-current users.
+        assertThat(mHelper.getAllUsersExcludesCurrentUser()).contains(otherUser1);
+        assertThat(mHelper.getAllUsersExcludesCurrentUser()).contains(otherUser2);
+        assertThat(mHelper.getAllUsersExcludesCurrentUser()).contains(otherUser3);
+    }
+
+    @Test
+    public void testUserCanBeRemoved() {
+        UserInfo testInfo = new UserInfo();
+
+        // System user cannot be removed.
+        testInfo.id = UserHandle.USER_SYSTEM;
+        assertThat(mHelper.userCanBeRemoved(testInfo)).isFalse();
+
+        testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
+        assertThat(mHelper.userCanBeRemoved(testInfo)).isTrue();
+    }
+
+    @Test
+    public void testUserIsCurrentUser() {
+        UserInfo testInfo = new UserInfo();
+
+        // System user cannot be removed.
+        testInfo.id = UserHandle.myUserId();
+        assertThat(mHelper.userIsCurrentUser(testInfo)).isTrue();
+
+        testInfo.id = UserHandle.myUserId() + 2;
+        assertThat(mHelper.userIsCurrentUser(testInfo)).isFalse();
+    }
+
+    @Test
+    public void testCanAddUsers() {
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(false);
+        assertThat(mHelper.canAddUsers()).isTrue();
+
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(true);
+        assertThat(mHelper.canAddUsers()).isFalse();
+    }
+
+    @Test
+    public void testCanRemoveUsers() {
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(false);
+        assertThat(mHelper.canRemoveUsers()).isTrue();
+
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(true);
+        assertThat(mHelper.canRemoveUsers()).isFalse();
+    }
+
+    @Test
+    public void testCanSwitchUsers() {
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
+        assertThat(mHelper.canSwitchUsers()).isTrue();
+
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true);
+        assertThat(mHelper.canSwitchUsers()).isFalse();
+    }
+
+    @Test
+    public void testGuestCannotModifyAccounts() {
+        assertThat(mHelper.canModifyAccounts()).isTrue();
+
+        when(mUserManager.isGuestUser()).thenReturn(true);
+        assertThat(mHelper.canModifyAccounts()).isFalse();
+    }
+
+    @Test
+    public void testDemoUserCannotModifyAccounts() {
+        assertThat(mHelper.canModifyAccounts()).isTrue();
+
+        when(mUserManager.isDemoUser()).thenReturn(true);
+        assertThat(mHelper.canModifyAccounts()).isFalse();
+    }
+
+    @Test
+    public void testUserWithDisallowModifyAccountsRestrictionCannotModifyAccounts() {
+        assertThat(mHelper.canModifyAccounts()).isTrue();
+
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS))
+                .thenReturn(true);
+        assertThat(mHelper.canModifyAccounts()).isFalse();
+    }
+
+    @Test
+    public void testCreateNewUser() {
+        // Verify createUser on UserManager gets called.
+        mHelper.createNewUser("Test User");
+        verify(mUserManager).createUser("Test User", 0);
+
+        when(mUserManager.createUser("Test User", 0)).thenReturn(null);
+        assertThat(mHelper.createNewUser("Test User")).isNull();
+
+        UserInfo newUser = new UserInfo();
+        newUser.name = "Test User";
+        when(mUserManager.createUser("Test User", 0)).thenReturn(newUser);
+        assertThat(mHelper.createNewUser("Test User")).isEqualTo(newUser);
+    }
+
+    @Test
+    public void testRemoveUser() {
+        // Cannot remove system user.
+        assertThat(mHelper.removeUser(mSystemUser)).isFalse();
+
+        // Removing current user, calls "switch" to system user.
+        mHelper.removeUser(mCurrentUser);
+        verify(mActivityManager).switchUser(UserHandle.USER_SYSTEM);
+        verify(mUserManager).removeUser(mCurrentUser.id);
+
+        // Removing non-current, non-system user, simply calls removeUser.
+        UserInfo userToRemove = createUserInfoForId(mCurrentUser.id + 2);
+        mHelper.removeUser(userToRemove);
+        verify(mUserManager).removeUser(mCurrentUser.id + 2);
+    }
+
+    @Test
+    public void testSwitchToUser() {
+        // Switching to current user doesn't do anything.
+        mHelper.switchToUser(mCurrentUser);
+        verify(mActivityManager, never()).switchUser(mCurrentUser.id);
+
+        // Switching to Guest calls createGuest.
+        UserInfo guestInfo = new UserInfo(mCurrentUser.id + 1, "Test Guest", UserInfo.FLAG_GUEST);
+        mHelper.switchToUser(guestInfo);
+        verify(mUserManager).createGuest(mContext, "Test Guest");
+
+        // Switching to non-current, non-guest user, simply calls switchUser.
+        UserInfo userToSwitchTo = new UserInfo(mCurrentUser.id + 5, "Test User", 0);
+        mHelper.switchToUser(userToSwitchTo);
+        verify(mActivityManager).switchUser(mCurrentUser.id + 5);
+    }
+
+    @Test
+    public void testSwitchToGuest() {
+        mHelper.switchToGuest("Test Guest");
+        verify(mUserManager).createGuest(mContext, "Test Guest");
+
+        UserInfo guestInfo = new UserInfo(mCurrentUser.id + 2, "Test Guest", UserInfo.FLAG_GUEST);
+        when(mUserManager.createGuest(mContext, "Test Guest")).thenReturn(guestInfo);
+        mHelper.switchToGuest("Test Guest");
+        verify(mActivityManager).switchUser(mCurrentUser.id + 2);
+    }
+
+    @Test
+    public void testGetUserIcon() {
+        mHelper.getUserIcon(mCurrentUser);
+        verify(mUserManager).getUserIcon(mCurrentUser.id);
+    }
+
+    @Test
+    public void testScaleUserIcon() {
+        Bitmap fakeIcon = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+        Drawable scaledIcon = mHelper.scaleUserIcon(fakeIcon, 300);
+        assertThat(scaledIcon.getIntrinsicWidth()).isEqualTo(300);
+        assertThat(scaledIcon.getIntrinsicHeight()).isEqualTo(300);
+    }
+
+    @Test
+    public void testSetUserName() {
+        UserInfo testInfo = createUserInfoForId(mCurrentUser.id + 3);
+        mHelper.setUserName(testInfo, "New Test Name");
+        verify(mUserManager).setUserName(mCurrentUser.id + 3, "New Test Name");
+    }
+
+    @Test
+    public void testRegisterUserChangeReceiver() {
+        mHelper.registerOnUsersUpdateListener(mTestListener);
+
+        ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        ArgumentCaptor<UserHandle> handleCaptor = ArgumentCaptor.forClass(UserHandle.class);
+        ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass(IntentFilter.class);
+        ArgumentCaptor<String> permissionCaptor = ArgumentCaptor.forClass(String.class);
+        ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+
+        verify(mContext).registerReceiverAsUser(
+                receiverCaptor.capture(),
+                handleCaptor.capture(),
+                filterCaptor.capture(),
+                permissionCaptor.capture(),
+                handlerCaptor.capture());
+
+        // Verify we're listening to Intents from ALL users.
+        assertThat(handleCaptor.getValue()).isEqualTo(UserHandle.ALL);
+
+        // Verify the presence of each intent in the filter.
+        // Verify the exact number of filters. Every time a new intent is added, this test should
+        // get updated.
+        assertThat(filterCaptor.getValue().countActions()).isEqualTo(3);
+        assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_REMOVED)).isTrue();
+        assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_ADDED)).isTrue();
+        assertThat(filterCaptor.getValue().hasAction(Intent.ACTION_USER_INFO_CHANGED)).isTrue();
+
+        // Verify that calling the receiver calls the listener.
+        receiverCaptor.getValue().onReceive(mContext, new Intent());
+        verify(mTestListener).onUsersUpdate();
+
+        assertThat(permissionCaptor.getValue()).isNull();
+        assertThat(handlerCaptor.getValue()).isNull();
+
+
+        // Unregister the receiver.
+        mHelper.unregisterOnUsersUpdateListener();
+        verify(mContext).unregisterReceiver(receiverCaptor.getValue());
+    }
+
+    private UserInfo createUserInfoForId(int id) {
+        UserInfo userInfo = new UserInfo();
+        userInfo.id = id;
+        return userInfo;
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
new file mode 100644
index 0000000..b33df30
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2018 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.settingslib.fuelgauge;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.PowerManager;
+import android.provider.Settings.Secure;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class BatterySaverUtilsTest {
+    @Mock
+    Context mMockContext;
+
+    @Mock
+    ContentResolver mMockResolver;
+
+    @Mock
+    PowerManager mMockPowerManager;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
+        when(mMockContext.getSystemService(eq(PowerManager.class))).thenReturn(mMockPowerManager);
+        when(mMockPowerManager.setPowerSaveMode(anyBoolean())).thenReturn(true);
+    }
+
+    @Test
+    public void testSetPowerSaveMode_enable_firstCall_needWarning() throws Exception {
+        Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+        Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
+
+        assertEquals(false, BatterySaverUtils.setPowerSaveMode(mMockContext, true, true));
+
+        verify(mMockContext, times(1)).sendBroadcast(any(Intent.class));
+        verify(mMockPowerManager, times(0)).setPowerSaveMode(anyBoolean());
+
+        // They shouldn't have changed.
+        assertEquals(-1,
+                Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(-2,
+                Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+    }
+
+    @Test
+    public void testSetPowerSaveMode_enable_secondCall_needWarning() throws Exception {
+        Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
+        Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
+
+        assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, true, true));
+
+        verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
+        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(true));
+
+        assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+    }
+
+    @Test
+    public void testSetPowerSaveMode_enable_thridCall_needWarning() throws Exception {
+        Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
+        Secure.putInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 1);
+
+        assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, true, true));
+
+        verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
+        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(true));
+
+        assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(2, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+    }
+
+    @Test
+    public void testSetPowerSaveMode_enable_firstCall_noWarning() throws Exception {
+        Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+        Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
+
+        assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, true, false));
+
+        verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
+        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(true));
+
+        assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(1, Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+    }
+
+    @Test
+    public void testSetPowerSaveMode_disable_firstCall_noWarning() throws Exception {
+        Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+        Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
+
+        // When disabling, needFirstTimeWarning doesn't matter.
+        assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, false, false));
+
+        verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
+        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(false));
+
+        assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(-2,
+                Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+    }
+
+    @Test
+    public void testSetPowerSaveMode_disable_firstCall_needWarning() throws Exception {
+        Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+        Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
+
+        // When disabling, needFirstTimeWarning doesn't matter.
+        assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, false, true));
+
+        verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
+        verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(false));
+
+        assertEquals(-1, Secure.getInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, -1));
+        assertEquals(-2,
+                Secure.getInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, -2));
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
index 47dd022..532c755 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
@@ -114,7 +114,7 @@
     @Test
     public void testFormatRelativeTime_WithSeconds_ShowSeconds() {
         final double testMillis = 40 * DateUtils.SECOND_IN_MILLIS;
-        final String expectedTime = "40 sec. ago";
+        final String expectedTime = "Just now";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
                 expectedTime);
@@ -123,7 +123,7 @@
     @Test
     public void testFormatRelativeTime_NoSeconds_DoNotShowSeconds() {
         final double testMillis = 40 * DateUtils.SECOND_IN_MILLIS;
-        final String expectedTime = "1 min. ago";
+        final String expectedTime = "1 minute ago";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
                 expectedTime);
@@ -132,7 +132,7 @@
     @Test
     public void testFormatRelativeTime_LessThanTwoMinutes_withSeconds() {
         final double testMillis = 119 * DateUtils.SECOND_IN_MILLIS;
-        final String expectedTime = "119 sec. ago";
+        final String expectedTime = "Just now";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
                 expectedTime);
@@ -141,7 +141,7 @@
     @Test
     public void testFormatRelativeTime_LessThanTwoMinutes_NoSeconds() {
         final double testMillis = 119 * DateUtils.SECOND_IN_MILLIS;
-        final String expectedTime = "2 min. ago";
+        final String expectedTime = "2 minutes ago";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
                 expectedTime);
@@ -150,7 +150,7 @@
     @Test
     public void testFormatRelativeTime_TwoMinutes_withSeconds() {
         final double testMillis = 2 * DateUtils.MINUTE_IN_MILLIS;
-        final String expectedTime = "2 min. ago";
+        final String expectedTime = "2 minutes ago";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
                 expectedTime);
@@ -159,7 +159,7 @@
     @Test
     public void testFormatRelativeTime_LessThanTwoHours_withSeconds() {
         final double testMillis = 119 * DateUtils.MINUTE_IN_MILLIS;
-        final String expectedTime = "119 min. ago";
+        final String expectedTime = "119 minutes ago";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
                 expectedTime);
@@ -168,7 +168,7 @@
     @Test
     public void testFormatRelativeTime_TwoHours_withSeconds() {
         final double testMillis = 2 * DateUtils.HOUR_IN_MILLIS;
-        final String expectedTime = "2 hr. ago";
+        final String expectedTime = "2 hours ago";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
                 expectedTime);
@@ -177,7 +177,7 @@
     @Test
     public void testFormatRelativeTime_LessThanTwoDays_withSeconds() {
         final double testMillis = 47 * DateUtils.HOUR_IN_MILLIS;
-        final String expectedTime = "47 hr. ago";
+        final String expectedTime = "47 hours ago";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
                 expectedTime);
@@ -195,7 +195,7 @@
     @Test
     public void testFormatRelativeTime_FormatZero_WithSeconds() {
         final double testMillis = 0;
-        final String expectedTime = "0 sec. ago";
+        final String expectedTime = "Just now";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, true).toString()).isEqualTo(
                 expectedTime);
@@ -204,7 +204,7 @@
     @Test
     public void testFormatRelativeTime_FormatZero_NoSeconds() {
         final double testMillis = 0;
-        final String expectedTime = "0 min. ago";
+        final String expectedTime = "0 minutes ago";
 
         assertThat(StringUtil.formatRelativeTime(mContext, testMillis, false).toString()).isEqualTo(
                 expectedTime);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
index ea8ecba..91d9f91 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
@@ -18,6 +18,7 @@
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -31,6 +32,7 @@
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.text.format.DateUtils;
+import android.util.ArraySet;
 
 import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
@@ -43,6 +45,7 @@
 import org.robolectric.RuntimeEnvironment;
 
 import java.util.ArrayList;
+import java.util.Set;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
 public class WifiUtilsTest {
@@ -56,6 +59,8 @@
     private RssiCurve mockBadgeCurve;
     @Mock
     private WifiNetworkScoreCache mockWifiNetworkScoreCache;
+    @Mock
+    private AccessPoint mAccessPoint;
 
     @Before
     public void setUp() {
@@ -84,6 +89,15 @@
         assertThat(summary.contains(mContext.getString(R.string.speed_label_very_fast))).isTrue();
     }
 
+    @Test
+    public void testGetVisibilityStatus_nullResultDoesNotCrash() {
+        doReturn(null).when(mAccessPoint).getInfo();
+        Set<ScanResult> set = new ArraySet<>();
+        set.add(null);
+        doReturn(set).when(mAccessPoint).getScanResults();
+        WifiUtils.getVisibilityStatus(mAccessPoint);
+    }
+
     private static ArrayList<ScanResult> buildScanResultCache() {
         ArrayList<ScanResult> scanResults = new ArrayList<>();
         for (int i = 0; i < 5; i++) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 34aae49..797b4f9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1158,8 +1158,8 @@
                 Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED,
                 GlobalSettingsProto.CHAINED_BATTERY_ATTRIBUTION_ENABLED);
         dumpSetting(s, p,
-                Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES,
-                GlobalSettingsProto.AUTOFILL_COMPAT_ALLOWED_PACKAGES);
+                Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES,
+                GlobalSettingsProto.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES);
         dumpSetting(s, p,
                 Global.HIDDEN_API_BLACKLIST_EXEMPTIONS,
                 GlobalSettingsProto.HIDDEN_API_BLACKLIST_EXEMPTIONS);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index f215c12..b37071b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1798,76 +1798,52 @@
         if (TextUtils.isEmpty(value)) {
             return false;
         }
-
-        final char prefix = value.charAt(0);
-        if (prefix != '+' && prefix != '-') {
-            if (forceNotify) {
-                final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId);
-                mSettingsRegistry.notifyForSettingsChange(key,
-                        Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
-            }
+        Setting oldSetting = getSecureSetting(
+                Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
+        if (oldSetting == null) {
             return false;
         }
+        String oldProviders = oldSetting.getValue();
+        List<String> oldProvidersList = TextUtils.isEmpty(oldProviders)
+                ? new ArrayList<>() : new ArrayList<>(Arrays.asList(oldProviders.split(",")));
+        Set<String> newProvidersSet = new ArraySet<>();
+        newProvidersSet.addAll(oldProvidersList);
 
-        // skip prefix
-        value = value.substring(1);
-
-        Setting settingValue = getSecureSetting(
-                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
-        if (settingValue == null) {
-            return false;
-        }
-
-        String oldProviders = !settingValue.isNull() ? settingValue.getValue() : "";
-
-        int index = oldProviders.indexOf(value);
-        int end = index + value.length();
-
-        // check for commas to avoid matching on partial string
-        if (index > 0 && oldProviders.charAt(index - 1) != ',') {
-            index = -1;
-        }
-
-        // check for commas to avoid matching on partial string
-        if (end < oldProviders.length() && oldProviders.charAt(end) != ',') {
-            index = -1;
-        }
-
-        String newProviders;
-
-        if (prefix == '+' && index < 0) {
-            // append the provider to the list if not present
-            if (oldProviders.length() == 0) {
-                newProviders = value;
-            } else {
-                newProviders = oldProviders + ',' + value;
+        String[] providerUpdates = value.split(",");
+        boolean inputError = false;
+        for (String provider : providerUpdates) {
+            // do not update location_providers_allowed when input is invalid
+            if (TextUtils.isEmpty(provider)) {
+                inputError = true;
+                break;
             }
-        } else if (prefix == '-' && index >= 0) {
-            // remove the provider from the list if present
-            // remove leading or trailing comma
-            if (index > 0) {
-                index--;
-            } else if (end < oldProviders.length()) {
-                end++;
+            final char prefix = provider.charAt(0);
+            // do not update location_providers_allowed when input is invalid
+            if (prefix != '+' && prefix != '-') {
+                inputError = true;
+                break;
             }
-
-            newProviders = oldProviders.substring(0, index);
-            if (end < oldProviders.length()) {
-                newProviders += oldProviders.substring(end);
+            // skip prefix
+            provider = provider.substring(1);
+            if (prefix == '+') {
+                newProvidersSet.add(provider);
+            } else if (prefix == '-') {
+                newProvidersSet.remove(provider);
             }
-        } else {
+        }
+        String newProviders = TextUtils.join(",", newProvidersSet.toArray());
+        if (inputError == true || newProviders.equals(oldProviders)) {
             // nothing changed, so no need to update the database
             if (forceNotify) {
-                final int key = makeKey(SETTINGS_TYPE_SECURE, owningUserId);
-                mSettingsRegistry.notifyForSettingsChange(key,
+                mSettingsRegistry.notifyForSettingsChange(
+                        makeKey(SETTINGS_TYPE_SECURE, owningUserId),
                         Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
             }
             return false;
         }
-
         return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
-                owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders,
-                tag, makeDefault, getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
+                owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders, tag,
+                makeDefault, getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
     }
 
     private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
index e2a8fba..b6f51bc 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
@@ -17,8 +17,8 @@
 package com.android.providers.settings;
 
 import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertSame;
 import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
 import static junit.framework.Assert.fail;
 
 import android.content.ContentResolver;
@@ -32,9 +32,8 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
-import org.junit.Test;
-
 import java.util.concurrent.atomic.AtomicBoolean;
+import org.junit.Test;
 
 /**
  * Tests for the SettingContentProvider.
@@ -688,4 +687,112 @@
             cursor.close();
         }
     }
+
+    @Test
+    public void testUpdateLocationProvidersAllowedLocked_enableProviders() throws Exception {
+        setSettingViaFrontEndApiAndAssertSuccessfulChange(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_MODE,
+                String.valueOf(Settings.Secure.LOCATION_MODE_OFF),
+                UserHandle.USER_SYSTEM);
+
+        // Enable one provider
+        updateStringViaProviderApiSetting(
+                SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "+gps");
+
+        assertEquals(
+                "Wrong location providers",
+                "gps",
+                queryStringViaProviderApi(
+                        SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+
+        // Enable a list of providers, including the one that is already enabled
+        updateStringViaProviderApiSetting(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                "+gps,+network,+network");
+
+        assertEquals(
+                "Wrong location providers",
+                "gps,network",
+                queryStringViaProviderApi(
+                        SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+    }
+
+    @Test
+    public void testUpdateLocationProvidersAllowedLocked_disableProviders() throws Exception {
+        setSettingViaFrontEndApiAndAssertSuccessfulChange(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_MODE,
+                String.valueOf(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY),
+                UserHandle.USER_SYSTEM);
+
+        // Disable providers that were enabled
+        updateStringViaProviderApiSetting(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                "-gps,-network");
+
+        assertEquals(
+                "Wrong location providers",
+                "",
+                queryStringViaProviderApi(
+                        SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+
+        // Disable a provider that was not enabled
+        updateStringViaProviderApiSetting(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                "-test");
+
+        assertEquals(
+                "Wrong location providers",
+                "",
+                queryStringViaProviderApi(
+                        SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+    }
+
+    @Test
+    public void testUpdateLocationProvidersAllowedLocked_enableAndDisable() throws Exception {
+        setSettingViaFrontEndApiAndAssertSuccessfulChange(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_MODE,
+                String.valueOf(Settings.Secure.LOCATION_MODE_OFF),
+                UserHandle.USER_SYSTEM);
+
+        updateStringViaProviderApiSetting(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                "+gps,+network,+test");
+        updateStringViaProviderApiSetting(
+                SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "-test");
+
+        assertEquals(
+                "Wrong location providers",
+                "gps,network",
+                queryStringViaProviderApi(
+                        SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+    }
+
+    @Test
+    public void testUpdateLocationProvidersAllowedLocked_invalidInput() throws Exception {
+        setSettingViaFrontEndApiAndAssertSuccessfulChange(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_MODE,
+                String.valueOf(Settings.Secure.LOCATION_MODE_OFF),
+                UserHandle.USER_SYSTEM);
+
+        // update providers with a invalid string
+        updateStringViaProviderApiSetting(
+                SETTING_TYPE_SECURE,
+                Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                "+gps, invalid-string");
+
+        // Verifies providers list does not change
+        assertEquals(
+                "Wrong location providers",
+                "",
+                queryStringViaProviderApi(
+                        SETTING_TYPE_SECURE, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
+    }
 }
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index f65efb8..68293d9 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -37,6 +37,7 @@
 LOCAL_STATIC_ANDROID_LIBRARIES := \
     SystemUIPluginLib \
     SystemUISharedLib \
+    android-support-car \
     android-support-v4 \
     android-support-v7-recyclerview \
     android-support-v7-preference \
diff --git a/packages/SystemUI/res/drawable/car_rounded_bg_bottom.xml b/packages/SystemUI/res/drawable/car_rounded_bg_bottom.xml
new file mode 100644
index 0000000..25b449a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/car_rounded_bg_bottom.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid android:color="?android:attr/colorBackgroundFloating" />
+    <corners
+        android:bottomLeftRadius="@dimen/car_radius_3"
+        android:topLeftRadius="0dp"
+        android:bottomRightRadius="@dimen/car_radius_3"
+        android:topRightRadius="0dp"
+        />
+</shape>
diff --git a/packages/SystemUI/res/layout/car_volume_dialog.xml b/packages/SystemUI/res/layout/car_volume_dialog.xml
new file mode 100644
index 0000000..dca50a5
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_volume_dialog.xml
@@ -0,0 +1,68 @@
+<!--
+     Copyright (C) 2018 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginStart="@dimen/car_margin"
+    android:layout_marginEnd="@dimen/car_margin"
+    android:background="@drawable/car_rounded_bg_bottom"
+    android:theme="@style/qs_theme"
+    android:clipChildren="false" >
+    <LinearLayout
+        android:id="@+id/volume_dialog"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal|top"
+        android:orientation="vertical"
+        android:clipChildren="false" >
+
+        <LinearLayout
+            android:id="@+id/main"
+            android:layout_width="match_parent"
+            android:minWidth="@dimen/volume_dialog_panel_width"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:elevation="@dimen/volume_panel_elevation" >
+            <LinearLayout
+                android:id="@+id/car_volume_dialog_rows"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:orientation="vertical" >
+                <!-- volume rows added and removed here! :-) -->
+            </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+    <FrameLayout
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/car_single_line_list_item_height"
+        android:gravity="center"
+        android:layout_marginEnd="@dimen/car_keyline_1">
+        <ImageButton
+            android:id="@+id/expand"
+            android:layout_gravity="center"
+            android:layout_width="@dimen/car_primary_icon_size"
+            android:layout_height="@dimen/car_primary_icon_size"
+            android:layout_marginEnd="@dimen/car_keyline_1"
+            android:src="@drawable/car_ic_arrow_drop_up"
+            android:tint="@color/car_tint"
+            android:scaleType="fitCenter"
+        />
+    </FrameLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/car_volume_dialog_row.xml b/packages/SystemUI/res/layout/car_volume_dialog_row.xml
new file mode 100644
index 0000000..14baf49
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_volume_dialog_row.xml
@@ -0,0 +1,47 @@
+<!--
+     Copyright (C) 2018 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:tag="row"
+    android:layout_height="@dimen/car_single_line_list_item_height"
+    android:layout_width="match_parent"
+    android:clipChildren="false"
+    android:clipToPadding="false"
+    android:theme="@style/qs_theme">
+
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:gravity="center"
+        android:layout_gravity="center"
+        android:orientation="horizontal" >
+        <com.android.keyguard.AlphaOptimizedImageButton
+            android:id="@+id/volume_row_icon"
+            android:layout_width="@dimen/car_primary_icon_size"
+            android:layout_height="@dimen/car_primary_icon_size"
+            android:layout_marginStart="@dimen/car_keyline_1"
+            android:tint="@color/car_tint"
+            android:scaleType="fitCenter"
+            android:soundEffectsEnabled="false" />
+        <SeekBar
+                android:id="@+id/volume_row_slider"
+                android:clickable="true"
+                android:layout_marginStart="@dimen/car_keyline_3"
+                android:layout_marginEnd="@dimen/car_keyline_3"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/car_single_line_list_item_height"/>
+    </LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3c8a695..375c31a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -669,7 +669,7 @@
     <string name="ethernet_label">Ethernet</string>
 
     <!-- QuickSettings: Onboarding text that introduces users to long press on an option in order to view the option's menu in Settings [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_header_onboarding_text">Press &amp; hold on the icons for more options</string>
+    <string name="quick_settings_header_onboarding_text">Touch &amp; hold icons for more options</string>
     <!-- QuickSettings: Do not disturb [CHAR LIMIT=NONE] -->
     <string name="quick_settings_dnd_label">Do not disturb</string>
     <!-- QuickSettings: Do not disturb - Priority only [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 9a3a825..b89e15d 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -27,7 +27,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.media.AudioAttributes;
-import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PowerManager;
@@ -37,6 +36,7 @@
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.settingslib.Utils;
+import com.android.settingslib.fuelgauge.BatterySaverUtils;
 import com.android.settingslib.utils.PowerUtil;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
@@ -72,6 +72,8 @@
             "PNW.clickedThermalShutdownWarning";
     private static final String ACTION_DISMISSED_THERMAL_SHUTDOWN_WARNING =
             "PNW.dismissedThermalShutdownWarning";
+    private static final String ACTION_SHOW_START_SAVER_CONFIRMATION =
+            BatterySaverUtils.ACTION_SHOW_START_SAVER_CONFIRMATION;
 
     private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -404,7 +406,7 @@
         d.setTitle(R.string.battery_saver_confirmation_title);
         d.setMessage(com.android.internal.R.string.battery_saver_description);
         d.setNegativeButton(android.R.string.cancel, null);
-        d.setPositiveButton(R.string.battery_saver_confirmation_ok, mStartSaverMode);
+        d.setPositiveButton(R.string.battery_saver_confirmation_ok, mStartSaverModeNoConfirmation);
         d.setShowForAllUsers(true);
         d.setOnDismissListener(new OnDismissListener() {
             @Override
@@ -416,8 +418,8 @@
         mSaverConfirmation = d;
     }
 
-    private void setSaverMode(boolean mode) {
-        mPowerMan.setPowerSaveMode(mode);
+    private void setSaverMode(boolean mode, boolean needFirstTimeWarning) {
+        BatterySaverUtils.setPowerSaveMode(mContext, mode, needFirstTimeWarning);
     }
 
     private final class Receiver extends BroadcastReceiver {
@@ -431,8 +433,9 @@
             filter.addAction(ACTION_DISMISSED_TEMP_WARNING);
             filter.addAction(ACTION_CLICKED_THERMAL_SHUTDOWN_WARNING);
             filter.addAction(ACTION_DISMISSED_THERMAL_SHUTDOWN_WARNING);
+            filter.addAction(ACTION_SHOW_START_SAVER_CONFIRMATION);
             mContext.registerReceiverAsUser(this, UserHandle.ALL, filter,
-                    android.Manifest.permission.STATUS_BAR_SERVICE, mHandler);
+                    android.Manifest.permission.DEVICE_POWER, mHandler);
         }
 
         @Override
@@ -443,6 +446,9 @@
                 dismissLowBatteryNotification();
                 mContext.startActivityAsUser(mOpenBatterySettings, UserHandle.CURRENT);
             } else if (action.equals(ACTION_START_SAVER)) {
+                setSaverMode(true, true);
+                dismissLowBatteryNotification();
+            } else if (action.equals(ACTION_SHOW_START_SAVER_CONFIRMATION)) {
                 dismissLowBatteryNotification();
                 showStartSaverConfirmation();
             } else if (action.equals(ACTION_DISMISSED_WARNING)) {
@@ -461,15 +467,6 @@
         }
     }
 
-    private final OnClickListener mStartSaverMode = new OnClickListener() {
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            AsyncTask.execute(new Runnable() {
-                @Override
-                public void run() {
-                    setSaverMode(true);
-                }
-            });
-        }
-    };
+    private final OnClickListener mStartSaverModeNoConfirmation =
+            (dialog, which) -> setSaverMode(true, false);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index ac86c8a..f08219a 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -137,24 +137,9 @@
     void updateBatteryWarningLevels() {
         int critLevel = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_criticalBatteryWarningLevel);
-
-        final ContentResolver resolver = mContext.getContentResolver();
-        final int defWarnLevel = mContext.getResources().getInteger(
+        int warnLevel = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lowBatteryWarningLevel);
-        final int lowPowerModeTriggerLevel = Settings.Global.getInt(resolver,
-                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);
 
-        // Note LOW_POWER_MODE_TRIGGER_LEVEL can take any value between 0 and 100, but
-        // for the UI purposes, let's cap it at 15% -- i.e. even if the trigger level is higher
-        // like 50%, let's not show the "low battery" notification until it hits
-        // config_lowBatteryWarningLevel, which is 15% by default.
-        // LOW_POWER_MODE_TRIGGER_LEVEL is still used in other places as-is. For example, if it's
-        // 50, then battery saver kicks in when the battery level hits 50%.
-        int warnLevel =  Math.min(defWarnLevel, lowPowerModeTriggerLevel);
-
-        if (warnLevel == 0) {
-            warnLevel = defWarnLevel;
-        }
         if (warnLevel < critLevel) {
             warnLevel = critLevel;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 40b8d78..834feb7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -85,6 +85,7 @@
     private String mTileSpec;
     private EnforcedAdmin mEnforcedAdmin;
     private boolean mShowingDetail;
+    private int mIsFullQs;
 
     public abstract TState newTileState();
 
@@ -110,18 +111,7 @@
      * listening client it will go into the listening state.
      */
     public void setListening(Object listener, boolean listening) {
-        if (listening) {
-            if (mListeners.add(listener) && mListeners.size() == 1) {
-                if (DEBUG) Log.d(TAG, "setListening " + true);
-                mHandler.obtainMessage(H.SET_LISTENING, 1, 0).sendToTarget();
-                refreshState(); // Ensure we get at least one refresh after listening.
-            }
-        } else {
-            if (mListeners.remove(listener) && mListeners.size() == 0) {
-                if (DEBUG) Log.d(TAG, "setListening " + false);
-                mHandler.obtainMessage(H.SET_LISTENING, 0, 0).sendToTarget();
-            }
-        }
+        mHandler.obtainMessage(H.SET_LISTENING, listening ? 1 : 0, 0, listener).sendToTarget();
     }
 
     protected long getStaleTimeout() {
@@ -205,19 +195,10 @@
             logMaker.addTaggedData(FIELD_QS_VALUE, ((BooleanState) mState).value ? 1 : 0);
         }
         return logMaker.setSubtype(getMetricsCategory())
-                .addTaggedData(FIELD_CONTEXT, isFullQs())
+                .addTaggedData(FIELD_CONTEXT, mIsFullQs)
                 .addTaggedData(FIELD_QS_POSITION, mHost.indexOf(mTileSpec));
     }
 
-    private int isFullQs() {
-        for (Object listener : mListeners) {
-            if (TilePage.class.equals(listener.getClass())) {
-                return 1;
-            }
-        }
-        return 0;
-    }
-
     public void showDetail(boolean show) {
         mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0).sendToTarget();
     }
@@ -352,6 +333,32 @@
         handleRefreshState(null);
     }
 
+    private void handleSetListeningInternal(Object listener, boolean listening) {
+        if (listening) {
+            if (mListeners.add(listener) && mListeners.size() == 1) {
+                if (DEBUG) Log.d(TAG, "handleSetListening true");
+                handleSetListening(listening);
+                refreshState(); // Ensure we get at least one refresh after listening.
+            }
+        } else {
+            if (mListeners.remove(listener) && mListeners.size() == 0) {
+                if (DEBUG) Log.d(TAG, "handleSetListening false");
+                handleSetListening(listening);
+            }
+        }
+        updateIsFullQs();
+    }
+
+    private void updateIsFullQs() {
+        for (Object listener : mListeners) {
+            if (TilePage.class.equals(listener.getClass())) {
+                mIsFullQs = 1;
+                return;
+            }
+        }
+        mIsFullQs = 0;
+    }
+
     protected abstract void handleSetListening(boolean listening);
 
     protected void handleDestroy() {
@@ -464,8 +471,8 @@
                     name = "handleClearState";
                     handleClearState();
                 } else if (msg.what == SET_LISTENING) {
-                    name = "handleSetListening";
-                    handleSetListening(msg.arg1 != 0);
+                    name = "handleSetListeningInternal";
+                    handleSetListeningInternal(msg.obj, msg.arg1 != 0);
                 } else if (msg.what == STALE) {
                     name = "handleStale";
                     handleStale();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 7db2a50..068fd3f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.screenshot;
 
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
 import static com.android.systemui.screenshot.GlobalScreenshot.SHARING_INTENT;
 import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
 
@@ -26,11 +28,11 @@
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
-import android.app.admin.DevicePolicyManager;
 import android.app.Notification;
 import android.app.Notification.BigPictureStyle;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -58,7 +60,6 @@
 import android.os.UserHandle;
 import android.provider.MediaStore;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.util.Slog;
 import android.view.Display;
 import android.view.LayoutInflater;
@@ -517,6 +518,7 @@
                     | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
                 PixelFormat.TRANSLUCENT);
         mWindowLayoutParams.setTitle("ScreenshotAnimation");
+        mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         mNotificationManager =
             (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index fcbd37c..8fb0620 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -679,11 +679,12 @@
 
     public void updateStates() {
         updateSlippery();
+        reloadNavIcons();
         updateNavButtonIcons();
     }
 
     private void updateSlippery() {
-        setSlippery(mOverviewProxyService.getProxy() != null && mPanelView.isFullyExpanded());
+        setSlippery(!isQuickStepSwipeUpEnabled() || mPanelView.isFullyExpanded());
     }
 
     private void setSlippery(boolean slippery) {
@@ -818,8 +819,6 @@
     public void onOverviewProxyConnectionChanged(boolean isConnected) {
         updateStates();
         setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
-        reloadNavIcons();
-        updateNavButtonIcons();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 49f880c..7221efa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -28,6 +28,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.fuelgauge.BatterySaverUtils;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -93,7 +94,7 @@
 
     @Override
     public void setPowerSaveMode(boolean powerSave) {
-        mPowerManager.setPowerSaveMode(powerSave);
+        BatterySaverUtils.setPowerSaveMode(mContext, powerSave, /*needFirstTimeWarning*/ true);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
new file mode 100644
index 0000000..41b094a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -0,0 +1,835 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume;
+
+import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.ColorDrawable;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.os.Debug;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.provider.Settings.Global;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+import android.view.ContextThemeWrapper;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.ImageButton;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.plugins.VolumeDialog;
+import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.plugins.VolumeDialogController.State;
+import com.android.systemui.plugins.VolumeDialogController.StreamState;
+
+/**
+ * Car version of the volume dialog.
+ *
+ * A client of VolumeDialogControllerImpl and its state model.
+ *
+ * Methods ending in "H" must be called on the (ui) handler.
+ */
+public class CarVolumeDialogImpl implements VolumeDialog {
+    private static final String TAG = Util.logTag(CarVolumeDialogImpl.class);
+
+    private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
+    private static final int UPDATE_ANIMATION_DURATION = 80;
+
+    private final Context mContext;
+    private final H mHandler = new H();
+    private final VolumeDialogController mController;
+
+    private Window mWindow;
+    private CustomDialog mDialog;
+    private ViewGroup mDialogView;
+    private ViewGroup mDialogRowsView;
+    private final List<VolumeRow> mRows = new ArrayList<>();
+    private ConfigurableTexts mConfigurableTexts;
+    private final SparseBooleanArray mDynamic = new SparseBooleanArray();
+    private final KeyguardManager mKeyguard;
+    private final Object mSafetyWarningLock = new Object();
+    private final ColorStateList mActiveSliderTint;
+    private final ColorStateList mInactiveSliderTint;
+
+    private boolean mShowing;
+
+    private int mActiveStream;
+    private int mPrevActiveStream;
+    private boolean mAutomute = VolumePrefs.DEFAULT_ENABLE_AUTOMUTE;
+    private boolean mSilentMode = VolumePrefs.DEFAULT_ENABLE_SILENT_MODE;
+    private State mState;
+    private SafetyWarningDialog mSafetyWarning;
+    private boolean mHovering = false;
+    private boolean mExpanded = false;
+    private View mExpandBtn;
+
+    public CarVolumeDialogImpl(Context context) {
+        mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
+        mController = Dependency.get(VolumeDialogController.class);
+        mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
+        mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
+    }
+
+    public void init(int windowType, Callback callback) {
+        initDialog();
+
+        mController.addCallback(mControllerCallbackH, mHandler);
+        mController.getState();
+    }
+
+    @Override
+    public void destroy() {
+        mController.removeCallback(mControllerCallbackH);
+        mHandler.removeCallbacksAndMessages(null);
+    }
+
+    private void initDialog() {
+        mDialog = new CustomDialog(mContext);
+
+        mConfigurableTexts = new ConfigurableTexts(mContext);
+        mHovering = false;
+        mShowing = false;
+        mWindow = mDialog.getWindow();
+        mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+        mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+        mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
+            | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
+        mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+            | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+            | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+            | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+        mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast);
+        final WindowManager.LayoutParams lp = mWindow.getAttributes();
+        lp.format = PixelFormat.TRANSLUCENT;
+        lp.setTitle(VolumeDialogImpl.class.getSimpleName());
+        lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
+        lp.windowAnimations = -1;
+        mWindow.setAttributes(lp);
+        mWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+
+        mDialog.setCanceledOnTouchOutside(true);
+        mDialog.setContentView(R.layout.car_volume_dialog);
+        mDialog.setOnShowListener(dialog -> {
+            mDialogView.setTranslationY(-mDialogView.getHeight());
+            mDialogView.setAlpha(0);
+            mDialogView.animate()
+                .alpha(1)
+                .translationY(0)
+                .setDuration(300)
+                .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
+                .start();
+        });
+        mExpandBtn = mDialog.findViewById(R.id.expand);
+        mExpandBtn.setOnClickListener(v -> {
+            mExpanded = !mExpanded;
+            updateRowsH(getActiveRow());
+        });
+        mDialogView = mDialog.findViewById(R.id.volume_dialog);
+        mDialogView.setOnHoverListener((v, event) -> {
+            int action = event.getActionMasked();
+            mHovering = (action == MotionEvent.ACTION_HOVER_ENTER)
+                || (action == MotionEvent.ACTION_HOVER_MOVE);
+            rescheduleTimeoutH();
+            return true;
+        });
+
+        mDialogRowsView = mDialog.findViewById(R.id.car_volume_dialog_rows);
+
+        if (mRows.isEmpty()) {
+            addRow(AudioManager.STREAM_MUSIC,
+                R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true, true);
+            addRow(AudioManager.STREAM_RING,
+                R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true, false);
+            addRow(AudioManager.STREAM_ALARM,
+                R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, true, false);
+        } else {
+            addExistingRows();
+        }
+
+        updateRowsH(getActiveRow());
+    }
+
+    private ColorStateList loadColorStateList(int colorResId) {
+        return ColorStateList.valueOf(mContext.getColor(colorResId));
+    }
+
+    public void setStreamImportant(int stream, boolean important) {
+        mHandler.obtainMessage(H.SET_STREAM_IMPORTANT, stream, important ? 1 : 0).sendToTarget();
+    }
+
+    public void setAutomute(boolean automute) {
+        if (mAutomute == automute) return;
+        mAutomute = automute;
+        mHandler.sendEmptyMessage(H.RECHECK_ALL);
+    }
+
+    public void setSilentMode(boolean silentMode) {
+        if (mSilentMode == silentMode) return;
+        mSilentMode = silentMode;
+        mHandler.sendEmptyMessage(H.RECHECK_ALL);
+    }
+
+    private void addRow(int stream, int iconRes, int iconMuteRes, boolean important,
+        boolean defaultStream) {
+        addRow(stream, iconRes, iconMuteRes, important, defaultStream, false);
+    }
+
+    private void addRow(int stream, int iconRes, int iconMuteRes, boolean important,
+        boolean defaultStream, boolean dynamic) {
+        if (D.BUG) Slog.d(TAG, "Adding row for stream " + stream);
+        VolumeRow row = new VolumeRow();
+        initRow(row, stream, iconRes, iconMuteRes, important, defaultStream);
+        mDialogRowsView.addView(row.view);
+        mRows.add(row);
+    }
+
+    private void addExistingRows() {
+        int N = mRows.size();
+        for (int i = 0; i < N; i++) {
+            final VolumeRow row = mRows.get(i);
+            initRow(row, row.stream, row.iconRes, row.iconMuteRes, row.important,
+                row.defaultStream);
+            mDialogRowsView.addView(row.view);
+            updateVolumeRowH(row);
+        }
+    }
+
+    private VolumeRow getActiveRow() {
+        for (VolumeRow row : mRows) {
+            if (row.stream == mActiveStream) {
+                return row;
+            }
+        }
+        return mRows.get(0);
+    }
+
+    private VolumeRow findRow(int stream) {
+        for (VolumeRow row : mRows) {
+            if (row.stream == stream) return row;
+        }
+        return null;
+    }
+
+    public void dump(PrintWriter writer) {
+        writer.println(VolumeDialogImpl.class.getSimpleName() + " state:");
+        writer.print("  mShowing: "); writer.println(mShowing);
+        writer.print("  mActiveStream: "); writer.println(mActiveStream);
+        writer.print("  mDynamic: "); writer.println(mDynamic);
+        writer.print("  mAutomute: "); writer.println(mAutomute);
+        writer.print("  mSilentMode: "); writer.println(mSilentMode);
+    }
+
+    private static int getImpliedLevel(SeekBar seekBar, int progress) {
+        final int m = seekBar.getMax();
+        final int n = m / 100 - 1;
+        final int level = progress == 0 ? 0
+            : progress == m ? (m / 100) : (1 + (int)((progress / (float) m) * n));
+        return level;
+    }
+
+    @SuppressLint("InflateParams")
+    private void initRow(final VolumeRow row, final int stream, int iconRes, int iconMuteRes,
+        boolean important, boolean defaultStream) {
+        row.stream = stream;
+        row.iconRes = iconRes;
+        row.iconMuteRes = iconMuteRes;
+        row.important = important;
+        row.defaultStream = defaultStream;
+        row.view = mDialog.getLayoutInflater().inflate(R.layout.car_volume_dialog_row, null);
+        row.view.setId(row.stream);
+        row.view.setTag(row);
+        row.slider =  row.view.findViewById(R.id.volume_row_slider);
+        row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
+        row.anim = null;
+
+        row.icon = row.view.findViewById(R.id.volume_row_icon);
+        row.icon.setImageResource(iconRes);
+    }
+
+    public void show(int reason) {
+        mHandler.obtainMessage(H.SHOW, reason, 0).sendToTarget();
+    }
+
+    public void dismiss(int reason) {
+        mHandler.obtainMessage(H.DISMISS, reason, 0).sendToTarget();
+    }
+
+    private void showH(int reason) {
+        if (D.BUG) Log.d(TAG, "showH r=" + Events.DISMISS_REASONS[reason]);
+        mHandler.removeMessages(H.SHOW);
+        mHandler.removeMessages(H.DISMISS);
+        rescheduleTimeoutH();
+        if (mShowing) return;
+        mShowing = true;
+
+        mDialog.show();
+        Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
+        mController.notifyVisible(true);
+    }
+
+    protected void rescheduleTimeoutH() {
+        mHandler.removeMessages(H.DISMISS);
+        final int timeout = computeTimeoutH();
+        mHandler.sendMessageDelayed(mHandler
+            .obtainMessage(H.DISMISS, Events.DISMISS_REASON_TIMEOUT, 0), timeout);
+        if (D.BUG) Log.d(TAG, "rescheduleTimeout " + timeout + " " + Debug.getCaller());
+        mController.userActivity();
+    }
+
+    private int computeTimeoutH() {
+        if (mHovering) return 16000;
+        if (mSafetyWarning != null) return 5000;
+        return 3000;
+    }
+
+    protected void dismissH(int reason) {
+        mHandler.removeMessages(H.DISMISS);
+        mHandler.removeMessages(H.SHOW);
+        if (!mShowing) return;
+        mDialogView.animate().cancel();
+        mShowing = false;
+
+        mDialogView.setTranslationY(0);
+        mDialogView.setAlpha(1);
+        mDialogView.animate()
+            .alpha(0)
+            .translationY(-mDialogView.getHeight())
+            .setDuration(250)
+            .setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator())
+            .withEndAction(() -> mHandler.postDelayed(() -> {
+                if (D.BUG) Log.d(TAG, "mDialog.dismiss()");
+                mDialog.dismiss();
+            }, 50))
+            .start();
+
+        Events.writeEvent(mContext, Events.EVENT_DISMISS_DIALOG, reason);
+        mController.notifyVisible(false);
+        synchronized (mSafetyWarningLock) {
+            if (mSafetyWarning != null) {
+                if (D.BUG) Log.d(TAG, "SafetyWarning dismissed");
+                mSafetyWarning.dismiss();
+            }
+        }
+    }
+
+    private boolean shouldBeVisibleH(VolumeRow row) {
+        if (mExpanded) {
+            return true;
+        }
+        return row.defaultStream;
+    }
+
+    private void updateRowsH(final VolumeRow activeRow) {
+        if (D.BUG) Log.d(TAG, "updateRowsH");
+        if (!mShowing) {
+            trimObsoleteH();
+        }
+        // apply changes to all rows
+        for (final VolumeRow row : mRows) {
+            final boolean isActive = row == activeRow;
+            final boolean shouldBeVisible = shouldBeVisibleH(row);
+            Util.setVisOrGone(row.view, shouldBeVisible);
+            if (row.view.isShown()) {
+                updateVolumeRowSliderTintH(row, isActive);
+            }
+        }
+    }
+
+    private void trimObsoleteH() {
+        if (D.BUG) Log.d(TAG, "trimObsoleteH");
+        for (int i = mRows.size() - 1; i >= 0; i--) {
+            final VolumeRow row = mRows.get(i);
+            if (row.ss == null || !row.ss.dynamic) continue;
+            if (!mDynamic.get(row.stream)) {
+                mRows.remove(i);
+                mDialogRowsView.removeView(row.view);
+            }
+        }
+    }
+
+    protected void onStateChangedH(State state) {
+        mState = state;
+        mDynamic.clear();
+        // add any new dynamic rows
+        for (int i = 0; i < state.states.size(); i++) {
+            final int stream = state.states.keyAt(i);
+            final StreamState ss = state.states.valueAt(i);
+            if (!ss.dynamic) continue;
+            mDynamic.put(stream, true);
+            if (findRow(stream) == null) {
+                addRow(stream, R.drawable.ic_volume_remote, R.drawable.ic_volume_remote_mute, true,
+                    false, true);
+            }
+        }
+
+        if (mActiveStream != state.activeStream) {
+            mPrevActiveStream = mActiveStream;
+            mActiveStream = state.activeStream;
+            updateRowsH(getActiveRow());
+            rescheduleTimeoutH();
+        }
+        for (VolumeRow row : mRows) {
+            updateVolumeRowH(row);
+        }
+
+    }
+
+    private void updateVolumeRowH(VolumeRow row) {
+        if (D.BUG) Log.d(TAG, "updateVolumeRowH s=" + row.stream);
+        if (mState == null) return;
+        final StreamState ss = mState.states.get(row.stream);
+        if (ss == null) return;
+        row.ss = ss;
+        if (ss.level > 0) {
+            row.lastAudibleLevel = ss.level;
+        }
+        if (ss.level == row.requestedLevel) {
+            row.requestedLevel = -1;
+        }
+        final boolean isRingStream = row.stream == AudioManager.STREAM_RING;
+        final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;
+        final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
+        final boolean isMusicStream = row.stream == AudioManager.STREAM_MUSIC;
+        final boolean isRingVibrate = isRingStream
+            && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
+        final boolean isRingSilent = isRingStream
+            && mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT;
+        final boolean isZenPriorityOnly = mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS;
+        final boolean isZenNone = mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+        final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream)
+            : isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream)
+                : isZenPriorityOnly ? ((isAlarmStream && mState.disallowAlarms) ||
+                    (isMusicStream && mState.disallowMedia) ||
+                    (isRingStream && mState.disallowRinger) ||
+                    (isSystemStream && mState.disallowSystem))
+                    : false;
+
+        // update slider max
+        final int max = ss.levelMax * 100;
+        if (max != row.slider.getMax()) {
+            row.slider.setMax(max);
+        }
+
+        // update icon
+        final boolean iconEnabled = (mAutomute || ss.muteSupported) && !zenMuted;
+        row.icon.setEnabled(iconEnabled);
+        row.icon.setAlpha(iconEnabled ? 1 : 0.5f);
+        final int iconRes =
+            isRingVibrate ? R.drawable.ic_volume_ringer_vibrate
+                : isRingSilent || zenMuted ? row.iconMuteRes
+                    : ss.routedToBluetooth ?
+                        (ss.muted ? R.drawable.ic_volume_media_bt_mute
+                            : R.drawable.ic_volume_media_bt)
+                        : mAutomute && ss.level == 0 ? row.iconMuteRes
+                            : (ss.muted ? row.iconMuteRes : row.iconRes);
+        row.icon.setImageResource(iconRes);
+        row.iconState =
+            iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE
+                : (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes)
+                    ? Events.ICON_STATE_MUTE
+                    : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes)
+                        ? Events.ICON_STATE_UNMUTE
+                        : Events.ICON_STATE_UNKNOWN;
+        if (iconEnabled) {
+            if (isRingStream) {
+                if (isRingVibrate) {
+                    row.icon.setContentDescription(mContext.getString(
+                        R.string.volume_stream_content_description_unmute,
+                        getStreamLabelH(ss)));
+                } else {
+                    if (mController.hasVibrator()) {
+                        row.icon.setContentDescription(mContext.getString(
+                            R.string.volume_stream_content_description_vibrate,
+                            getStreamLabelH(ss)));
+                    } else {
+                        row.icon.setContentDescription(mContext.getString(
+                            R.string.volume_stream_content_description_mute,
+                            getStreamLabelH(ss)));
+                    }
+                }
+            } else {
+                if (ss.muted || mAutomute && ss.level == 0) {
+                    row.icon.setContentDescription(mContext.getString(
+                        R.string.volume_stream_content_description_unmute,
+                        getStreamLabelH(ss)));
+                } else {
+                    row.icon.setContentDescription(mContext.getString(
+                        R.string.volume_stream_content_description_mute,
+                        getStreamLabelH(ss)));
+                }
+            }
+        } else {
+            row.icon.setContentDescription(getStreamLabelH(ss));
+        }
+
+        // ensure tracking is disabled if zenMuted
+        if (zenMuted) {
+            row.tracking = false;
+        }
+
+        // update slider
+        final boolean enableSlider = !zenMuted;
+        final int vlevel = row.ss.muted && (!isRingStream && !zenMuted) ? 0
+            : row.ss.level;
+        updateVolumeRowSliderH(row, enableSlider, vlevel);
+    }
+
+    private String getStreamLabelH(StreamState ss) {
+        if (ss.remoteLabel != null) {
+            return ss.remoteLabel;
+        }
+        try {
+            return mContext.getResources().getString(ss.name);
+        } catch (Resources.NotFoundException e) {
+            Slog.e(TAG, "Can't find translation for stream " + ss);
+            return "";
+        }
+    }
+
+    private void updateVolumeRowSliderTintH(VolumeRow row, boolean isActive) {
+        if (isActive) {
+            row.slider.requestFocus();
+        }
+        final ColorStateList tint = isActive && row.slider.isEnabled() ? mActiveSliderTint
+            : mInactiveSliderTint;
+        if (tint == row.cachedSliderTint) return;
+        row.cachedSliderTint = tint;
+        row.slider.setProgressTintList(tint);
+        row.slider.setThumbTintList(tint);
+    }
+
+    private void updateVolumeRowSliderH(VolumeRow row, boolean enable, int vlevel) {
+        row.slider.setEnabled(enable);
+        updateVolumeRowSliderTintH(row, row.stream == mActiveStream);
+        if (row.tracking) {
+            return;  // don't update if user is sliding
+        }
+        final int progress = row.slider.getProgress();
+        final int level = getImpliedLevel(row.slider, progress);
+        final boolean rowVisible = row.view.getVisibility() == View.VISIBLE;
+        final boolean inGracePeriod = (SystemClock.uptimeMillis() - row.userAttempt)
+            < USER_ATTEMPT_GRACE_PERIOD;
+        mHandler.removeMessages(H.RECHECK, row);
+        if (mShowing && rowVisible && inGracePeriod) {
+            if (D.BUG) Log.d(TAG, "inGracePeriod");
+            mHandler.sendMessageAtTime(mHandler.obtainMessage(H.RECHECK, row),
+                row.userAttempt + USER_ATTEMPT_GRACE_PERIOD);
+            return;  // don't update if visible and in grace period
+        }
+        if (vlevel == level) {
+            if (mShowing && rowVisible) {
+                return;  // don't clamp if visible
+            }
+        }
+        final int newProgress = vlevel * 100;
+        if (progress != newProgress) {
+            if (mShowing && rowVisible) {
+                // animate!
+                if (row.anim != null && row.anim.isRunning()
+                    && row.animTargetProgress == newProgress) {
+                    return;  // already animating to the target progress
+                }
+                // start/update animation
+                if (row.anim == null) {
+                    row.anim = ObjectAnimator.ofInt(row.slider, "progress", progress, newProgress);
+                    row.anim.setInterpolator(new DecelerateInterpolator());
+                } else {
+                    row.anim.cancel();
+                    row.anim.setIntValues(progress, newProgress);
+                }
+                row.animTargetProgress = newProgress;
+                row.anim.setDuration(UPDATE_ANIMATION_DURATION);
+                row.anim.start();
+            } else {
+                // update slider directly to clamped value
+                if (row.anim != null) {
+                    row.anim.cancel();
+                }
+                row.slider.setProgress(newProgress, true);
+            }
+        }
+    }
+
+    private void recheckH(VolumeRow row) {
+        if (row == null) {
+            if (D.BUG) Log.d(TAG, "recheckH ALL");
+            trimObsoleteH();
+            for (VolumeRow r : mRows) {
+                updateVolumeRowH(r);
+            }
+        } else {
+            if (D.BUG) Log.d(TAG, "recheckH " + row.stream);
+            updateVolumeRowH(row);
+        }
+    }
+
+    private void setStreamImportantH(int stream, boolean important) {
+        for (VolumeRow row : mRows) {
+            if (row.stream == stream) {
+                row.important = important;
+                return;
+            }
+        }
+    }
+
+    private void showSafetyWarningH(int flags) {
+        if ((flags & (AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_SHOW_UI_WARNINGS)) != 0
+            || mShowing) {
+            synchronized (mSafetyWarningLock) {
+                if (mSafetyWarning != null) {
+                    return;
+                }
+                mSafetyWarning = new SafetyWarningDialog(mContext, mController.getAudioManager()) {
+                    @Override
+                    protected void cleanUp() {
+                        synchronized (mSafetyWarningLock) {
+                            mSafetyWarning = null;
+                        }
+                        recheckH(null);
+                    }
+                };
+                mSafetyWarning.show();
+            }
+            recheckH(null);
+        }
+        rescheduleTimeoutH();
+    }
+
+    private final VolumeDialogController.Callbacks mControllerCallbackH
+        = new VolumeDialogController.Callbacks() {
+        @Override
+        public void onShowRequested(int reason) {
+            showH(reason);
+        }
+
+        @Override
+        public void onDismissRequested(int reason) {
+            dismissH(reason);
+        }
+
+        @Override
+        public void onScreenOff() {
+            dismissH(Events.DISMISS_REASON_SCREEN_OFF);
+        }
+
+        @Override
+        public void onStateChanged(State state) {
+            onStateChangedH(state);
+        }
+
+        @Override
+        public void onLayoutDirectionChanged(int layoutDirection) {
+            mDialogView.setLayoutDirection(layoutDirection);
+        }
+
+        @Override
+        public void onConfigurationChanged() {
+            mDialog.dismiss();
+            initDialog();
+            mConfigurableTexts.update();
+        }
+
+        @Override
+        public void onShowVibrateHint() {
+            if (mSilentMode) {
+                mController.setRingerMode(AudioManager.RINGER_MODE_SILENT, false);
+            }
+        }
+
+        @Override
+        public void onShowSilentHint() {
+            if (mSilentMode) {
+                mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+            }
+        }
+
+        @Override
+        public void onShowSafetyWarning(int flags) {
+            showSafetyWarningH(flags);
+        }
+
+        @Override
+        public void onAccessibilityModeChanged(Boolean showA11yStream) {
+        }
+    };
+
+    private final class H extends Handler {
+        private static final int SHOW = 1;
+        private static final int DISMISS = 2;
+        private static final int RECHECK = 3;
+        private static final int RECHECK_ALL = 4;
+        private static final int SET_STREAM_IMPORTANT = 5;
+        private static final int RESCHEDULE_TIMEOUT = 6;
+        private static final int STATE_CHANGED = 7;
+
+        public H() {
+            super(Looper.getMainLooper());
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case SHOW: showH(msg.arg1); break;
+                case DISMISS: dismissH(msg.arg1); break;
+                case RECHECK: recheckH((VolumeRow) msg.obj); break;
+                case RECHECK_ALL: recheckH(null); break;
+                case SET_STREAM_IMPORTANT: setStreamImportantH(msg.arg1, msg.arg2 != 0); break;
+                case RESCHEDULE_TIMEOUT: rescheduleTimeoutH(); break;
+                case STATE_CHANGED: onStateChangedH(mState); break;
+            }
+        }
+    }
+
+    private final class CustomDialog extends Dialog implements DialogInterface {
+        public CustomDialog(Context context) {
+            super(context, com.android.systemui.R.style.qs_theme);
+        }
+
+        @Override
+        public boolean dispatchTouchEvent(MotionEvent ev) {
+            rescheduleTimeoutH();
+            return super.dispatchTouchEvent(ev);
+        }
+
+        @Override
+        protected void onStart() {
+            super.setCanceledOnTouchOutside(true);
+            super.onStart();
+        }
+
+        @Override
+        protected void onStop() {
+            super.onStop();
+            mHandler.sendEmptyMessage(H.RECHECK_ALL);
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
+            if (isShowing()) {
+                if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                    dismissH(Events.DISMISS_REASON_TOUCH_OUTSIDE);
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    private final class VolumeSeekBarChangeListener implements OnSeekBarChangeListener {
+        private final VolumeRow mRow;
+
+        private VolumeSeekBarChangeListener(VolumeRow row) {
+            mRow = row;
+        }
+
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            if (mRow.ss == null) return;
+            if (D.BUG) Log.d(TAG, AudioSystem.streamToString(mRow.stream)
+                + " onProgressChanged " + progress + " fromUser=" + fromUser);
+            if (!fromUser) return;
+            if (mRow.ss.levelMin > 0) {
+                final int minProgress = mRow.ss.levelMin * 100;
+                if (progress < minProgress) {
+                    seekBar.setProgress(minProgress);
+                    progress = minProgress;
+                }
+            }
+            final int userLevel = getImpliedLevel(seekBar, progress);
+            if (mRow.ss.level != userLevel || mRow.ss.muted && userLevel > 0) {
+                mRow.userAttempt = SystemClock.uptimeMillis();
+                if (mRow.requestedLevel != userLevel) {
+                    mController.setStreamVolume(mRow.stream, userLevel);
+                    mRow.requestedLevel = userLevel;
+                    Events.writeEvent(mContext, Events.EVENT_TOUCH_LEVEL_CHANGED, mRow.stream,
+                        userLevel);
+                }
+            }
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+            if (D.BUG) Log.d(TAG, "onStartTrackingTouch"+ " " + mRow.stream);
+            mController.setActiveStream(mRow.stream);
+            mRow.tracking = true;
+        }
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream);
+            mRow.tracking = false;
+            mRow.userAttempt = SystemClock.uptimeMillis();
+            final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress());
+            Events.writeEvent(mContext, Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel);
+            if (mRow.ss.level != userLevel) {
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(H.RECHECK, mRow),
+                    USER_ATTEMPT_GRACE_PERIOD);
+            }
+        }
+    }
+
+    private static class VolumeRow {
+        private View view;
+        private ImageButton icon;
+        private SeekBar slider;
+        private int stream;
+        private StreamState ss;
+        private long userAttempt;  // last user-driven slider change
+        private boolean tracking;  // tracking slider touch
+        private int requestedLevel = -1;  // pending user-requested level via progress changed
+        private int iconRes;
+        private int iconMuteRes;
+        private boolean important;
+        private boolean defaultStream;
+        private ColorStateList cachedSliderTint;
+        private int iconState;  // from Events
+        private ObjectAnimator anim;  // slider progress animation for non-touch-related updates
+        private int animTargetProgress;
+        private int lastAudibleLevel = 1;
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index 0203c43..6e5b548 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.media.AudioManager;
 import android.media.VolumePolicy;
@@ -80,6 +81,7 @@
         Dependency.get(ExtensionController.class).newExtension(VolumeDialog.class)
                 .withPlugin(VolumeDialog.class)
                 .withDefault(this::createDefault)
+                .withFeature(PackageManager.FEATURE_AUTOMOTIVE, this::createCarDefault)
                 .withCallback(dialog -> {
                     if (mDialog != null) {
                         mDialog.destroy();
@@ -100,6 +102,14 @@
         return impl;
     }
 
+    private VolumeDialog createCarDefault() {
+        CarVolumeDialogImpl impl = new CarVolumeDialogImpl(mContext);
+        impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false);
+        impl.setAutomute(true);
+        impl.setSilentMode(false);
+        return impl;
+    }
+
     @Override
     public void onTuningChanged(String key, String newValue) {
         if (VOLUME_DOWN_SILENT.equals(key)) {
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index ebb088b..107ce1e 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -40,6 +40,7 @@
 LOCAL_STATIC_ANDROID_LIBRARIES := \
     SystemUIPluginLib \
     SystemUISharedLib \
+    android-support-car \
     android-support-v4 \
     android-support-v7-recyclerview \
     android-support-v7-preference \
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 0cc60e3..9417f04 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3964,7 +3964,8 @@
     // Type TYPE_FAILURE: The request failed
     // Package: Package of app that is autofilled
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets returned (only in success case)
+    // Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets returned in the response, or -1 if
+    // the service returned a null response.
     // NOTE: starting on OS P, it also added:
     // Type TYPE_CLOSE: Service returned a null response.
     // Tag FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS: if service requested field classification,
@@ -5541,6 +5542,11 @@
     // OS: P
     FIELD_ANOMALY_TYPE = 1366;
 
+    // ACTION: Settings > Anomaly receiver > Anomaly received
+    // CATEGORY: SETTINGS
+    // OS: P
+    ACTION_ANOMALY_TRIGGERED = 1367;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/art-profile b/services/art-profile
index d2cde02..93e580a 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -10677,7 +10677,6 @@
 PLcom/android/server/location/CountryDetectorBase;-><init>(Landroid/content/Context;)V
 PLcom/android/server/location/CountryDetectorBase;->notifyListener(Landroid/location/Country;)V
 PLcom/android/server/location/CountryDetectorBase;->setCountryListener(Landroid/location/CountryListener;)V
-PLcom/android/server/location/FlpHardwareProvider;->isSupported()Z
 PLcom/android/server/location/GeocoderProxy;-><init>(Landroid/content/Context;IIILandroid/os/Handler;)V
 PLcom/android/server/location/GeocoderProxy;->bind()Z
 PLcom/android/server/location/GeocoderProxy;->createAndBind(Landroid/content/Context;IIILandroid/os/Handler;)Lcom/android/server/location/GeocoderProxy;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index a5339e0..7409ec2 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -575,7 +575,7 @@
     private String getWhitelistedCompatModePackagesFromSettings() {
         return Settings.Global.getString(
                 mContext.getContentResolver(),
-                Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES);
+                Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES);
     }
 
     @Nullable
@@ -1179,7 +1179,7 @@
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES), false, this,
+                    Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES), false, this,
                     UserHandle.USER_ALL);
         }
 
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 7f57615..55c0372 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -596,6 +596,9 @@
             }
             if (response == null) {
                 processNullResponseLocked(requestFlags);
+                mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
+                        .setType(MetricsEvent.TYPE_SUCCESS)
+                        .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, -1));
                 return;
             }
 
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 4cac707..d6f6c6c 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -215,6 +215,13 @@
     // Timeout interval for deciding that a bind or clear-data has taken too long
     private static final long TIMEOUT_INTERVAL = 10 * 1000;
 
+    // Timeout intervals for agent backup & restore operations
+    public static final long TIMEOUT_BACKUP_INTERVAL = 30 * 1000;
+    public static final long TIMEOUT_FULL_BACKUP_INTERVAL = 5 * 60 * 1000;
+    public static final long TIMEOUT_SHARED_BACKUP_INTERVAL = 30 * 60 * 1000;
+    public static final long TIMEOUT_RESTORE_INTERVAL = 60 * 1000;
+    public static final long TIMEOUT_RESTORE_FINISHED_INTERVAL = 30 * 1000;
+
     // User confirmation timeout for a full backup/restore operation.  It's this long in
     // order to give them time to enter the backup password.
     private static final long TIMEOUT_FULL_CONFIRMATION = 60 * 1000;
@@ -225,7 +232,6 @@
     private static final int BUSY_BACKOFF_FUZZ = 1000 * 60 * 60 * 2;  // two hours
 
     private BackupManagerConstants mConstants;
-    private BackupAgentTimeoutParameters mAgentTimeoutParameters;
     private Context mContext;
     private PackageManager mPackageManager;
     private IPackageManager mPackageManagerBinder;
@@ -309,10 +315,6 @@
         return mConstants;
     }
 
-    public BackupAgentTimeoutParameters getAgentTimeoutParameters() {
-        return mAgentTimeoutParameters;
-    }
-
     public Context getContext() {
         return mContext;
     }
@@ -854,10 +856,6 @@
         // require frequent starting and stopping.
         mConstants.start();
 
-        mAgentTimeoutParameters = new
-                BackupAgentTimeoutParameters(mBackupHandler, mContext.getContentResolver());
-        mAgentTimeoutParameters.start();
-
         // Set up the various sorts of package tracking we do
         mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
         initPackageTracking();
@@ -3409,7 +3407,7 @@
             }
             mActiveRestoreSession = new ActiveRestoreSession(this, packageName, transport);
             mBackupHandler.sendEmptyMessageDelayed(MSG_RESTORE_SESSION_TIMEOUT,
-                    mAgentTimeoutParameters.getRestoreAgentTimeoutMillis());
+                    TIMEOUT_RESTORE_INTERVAL);
         }
         return mActiveRestoreSession;
     }
diff --git a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
index aabe7f6..7b021c6 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
@@ -191,7 +191,4 @@
   void dump(FileDescriptor fd, PrintWriter pw, String[] args);
 
   IBackupManager getBackupManagerBinder();
-
-  // Gets access to the backup/restore agent timeout parameters.
-  BackupAgentTimeoutParameters getAgentTimeoutParameters();
 }
diff --git a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
index f08c655..4755877 100644
--- a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
@@ -4,8 +4,8 @@
 import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
 import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
-
 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_BACKUP_INTERVAL;
 
 import android.app.ApplicationThreadConstants;
 import android.app.IBackupAgent;
@@ -59,7 +59,6 @@
     private ParcelFileDescriptor mSavedState;
     private ParcelFileDescriptor mBackupData;
     private ParcelFileDescriptor mNewState;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     public KeyValueAdbBackupEngine(OutputStream output, PackageInfo packageInfo,
             BackupManagerServiceInterface backupManagerService, PackageManager packageManager,
@@ -82,7 +81,6 @@
                 pkg + BACKUP_KEY_VALUE_NEW_STATE_FILENAME_SUFFIX);
 
         mManifestFile = new File(mDataDir, BackupManagerService.BACKUP_MANIFEST_FILENAME);
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
     }
 
     public void backupOnePackage() throws IOException {
@@ -150,9 +148,8 @@
     // Return true on backup success, false otherwise
     private boolean invokeAgentForAdbBackup(String packageName, IBackupAgent agent) {
         int token = mBackupManagerService.generateRandomIntegerToken();
-        long kvBackupAgentTimeoutMillis = mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis();
         try {
-            mBackupManagerService.prepareOperationTimeout(token, kvBackupAgentTimeoutMillis, null,
+            mBackupManagerService.prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL, null,
                     OP_TYPE_BACKUP_WAIT);
 
             // Start backup and wait for BackupManagerService to get callback for success or timeout
@@ -234,14 +231,14 @@
     }
 
     private void writeBackupData() throws IOException {
+
         int token = mBackupManagerService.generateRandomIntegerToken();
-        long kvBackupAgentTimeoutMillis = mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis();
 
         ParcelFileDescriptor[] pipes = null;
         try {
             pipes = ParcelFileDescriptor.createPipe();
 
-            mBackupManagerService.prepareOperationTimeout(token, kvBackupAgentTimeoutMillis, null,
+            mBackupManagerService.prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL, null,
                     OP_TYPE_BACKUP_WAIT);
 
             // We will have to create a runnable that will read the manifest and backup data we
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
index 597da21..0582aba 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -25,6 +25,9 @@
 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
 import static com.android.server.backup.BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
 import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
+import static com.android.server.backup.BackupManagerService
+        .TIMEOUT_SHARED_BACKUP_INTERVAL;
 
 import android.app.ApplicationThreadConstants;
 import android.app.IBackupAgent;
@@ -42,9 +45,8 @@
 import android.util.StringBuilderPrinter;
 
 import com.android.server.AppWidgetBackupBridge;
-import com.android.server.backup.BackupAgentTimeoutParameters;
-import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.BackupRestoreTask;
+import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.utils.FullBackupUtils;
 
 import java.io.BufferedOutputStream;
@@ -73,7 +75,6 @@
     private final long mQuota;
     private final int mOpToken;
     private final int mTransportFlags;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     class FullBackupRunner implements Runnable {
 
@@ -136,8 +137,8 @@
                 final boolean isSharedStorage =
                         mPackage.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
                 final long timeout = isSharedStorage ?
-                        mAgentTimeoutParameters.getSharedBackupAgentTimeoutMillis() :
-                        mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
+                        TIMEOUT_SHARED_BACKUP_INTERVAL :
+                        TIMEOUT_FULL_BACKUP_INTERVAL;
 
                 if (DEBUG) {
                     Slog.d(TAG, "Calling doFullBackup() on " + mPackage.packageName);
@@ -179,7 +180,6 @@
         mQuota = quota;
         mOpToken = opToken;
         mTransportFlags = transportFlags;
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
     }
 
     public int preflightCheck() throws RemoteException {
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
index d441cf6..40b6967 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
@@ -19,6 +19,7 @@
 import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
 import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
 
 import android.app.backup.IBackupManager;
 import android.content.ComponentName;
@@ -32,7 +33,6 @@
 import android.util.Slog;
 
 import com.android.internal.backup.IObbBackupService;
-import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.utils.FullBackupUtils;
 
@@ -46,12 +46,10 @@
 
     private BackupManagerService backupManagerService;
     volatile IObbBackupService mService;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     public FullBackupObbConnection(BackupManagerService backupManagerService) {
         this.backupManagerService = backupManagerService;
         mService = null;
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
     }
 
     public void establish() {
@@ -77,10 +75,8 @@
         try {
             pipes = ParcelFileDescriptor.createPipe();
             int token = backupManagerService.generateRandomIntegerToken();
-            long fullBackupAgentTimeoutMillis =
-                    mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
             backupManagerService.prepareOperationTimeout(
-                    token, fullBackupAgentTimeoutMillis, null, OP_TYPE_BACKUP_WAIT);
+                    token, TIMEOUT_FULL_BACKUP_INTERVAL, null, OP_TYPE_BACKUP_WAIT);
             mService.backupObbs(pkg.packageName, pipes[1], token,
                     backupManagerService.getBackupManagerBinder());
             FullBackupUtils.routeSocketDataToOutput(pipes[0], out);
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index 1ea3eb5..2c2dd85 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -22,6 +22,7 @@
 import static com.android.server.backup.BackupManagerService.OP_PENDING;
 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP;
 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
 
 import android.annotation.Nullable;
 import android.app.IBackupAgent;
@@ -43,7 +44,6 @@
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
-import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.FullBackupJob;
 import com.android.server.backup.BackupManagerService;
@@ -146,7 +146,6 @@
     private volatile boolean mIsDoingBackup;
     private volatile boolean mCancelAll;
     private final int mCurrentOpToken;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     public PerformFullTransportBackupTask(BackupManagerService backupManagerService,
             TransportClient transportClient,
@@ -168,7 +167,6 @@
         mUserInitiated = userInitiated;
         mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
         mBackupRunnerOpToken = backupManagerService.generateRandomIntegerToken();
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
 
         if (backupManagerService.isBackupOperationInProgress()) {
             if (DEBUG) {
@@ -700,11 +698,9 @@
         @Override
         public int preflightFullBackup(PackageInfo pkg, IBackupAgent agent) {
             int result;
-            long fullBackupAgentTimeoutMillis =
-                    mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
             try {
                 backupManagerService.prepareOperationTimeout(
-                        mCurrentOpToken, fullBackupAgentTimeoutMillis, this, OP_TYPE_BACKUP_WAIT);
+                        mCurrentOpToken, TIMEOUT_FULL_BACKUP_INTERVAL, this, OP_TYPE_BACKUP_WAIT);
                 backupManagerService.addBackupTrace("preflighting");
                 if (MORE_DEBUG) {
                     Slog.d(TAG, "Preflighting full payload of " + pkg.packageName);
@@ -717,7 +713,7 @@
                 // timeout had been produced.  In case of a real backstop timeout, mResult
                 // will still contain the value it was constructed with, AGENT_ERROR, which
                 // intentionaly falls into the "just report failure" code.
-                mLatch.await(fullBackupAgentTimeoutMillis, TimeUnit.MILLISECONDS);
+                mLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
 
                 long totalSize = mResult.get();
                 // If preflight timed out, mResult will contain error code as int.
@@ -773,10 +769,8 @@
 
         @Override
         public long getExpectedSizeOrErrorCode() {
-            long fullBackupAgentTimeoutMillis =
-                    mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
             try {
-                mLatch.await(fullBackupAgentTimeoutMillis, TimeUnit.MILLISECONDS);
+                mLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
                 return mResult.get();
             } catch (InterruptedException e) {
                 return BackupTransport.NO_MORE_DATA;
@@ -869,10 +863,8 @@
         // If preflight succeeded, returns positive number - preflight size,
         // otherwise return negative error code.
         long getPreflightResultBlocking() {
-            long fullBackupAgentTimeoutMillis =
-                    mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
             try {
-                mPreflightLatch.await(fullBackupAgentTimeoutMillis, TimeUnit.MILLISECONDS);
+                mPreflightLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
                 if (mIsCancelled) {
                     return BackupManager.ERROR_BACKUP_CANCELLED;
                 }
@@ -887,10 +879,8 @@
         }
 
         int getBackupResultBlocking() {
-            long fullBackupAgentTimeoutMillis =
-                    mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
             try {
-                mBackupLatch.await(fullBackupAgentTimeoutMillis, TimeUnit.MILLISECONDS);
+                mBackupLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
                 if (mIsCancelled) {
                     return BackupManager.ERROR_BACKUP_CANCELLED;
                 }
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index 5886862..136fada 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -19,6 +19,7 @@
 import static com.android.server.backup.BackupManagerService.DEBUG;
 import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
 import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_RESTORE_INTERVAL;
 
 import android.app.backup.RestoreSet;
 import android.content.Intent;
@@ -33,7 +34,6 @@
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
-import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.DataChangedJournal;
@@ -81,12 +81,10 @@
     public static final int MSG_OP_COMPLETE = 21;
 
     private final BackupManagerService backupManagerService;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     public BackupHandler(BackupManagerService backupManagerService, Looper looper) {
         super(looper);
         this.backupManagerService = backupManagerService;
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
     }
 
     public void handleMessage(Message msg) {
@@ -324,8 +322,7 @@
 
                     // Done: reset the session timeout clock
                     removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
-                    sendEmptyMessageDelayed(MSG_RESTORE_SESSION_TIMEOUT,
-                            mAgentTimeoutParameters.getRestoreAgentTimeoutMillis());
+                    sendEmptyMessageDelayed(MSG_RESTORE_SESSION_TIMEOUT, TIMEOUT_RESTORE_INTERVAL);
 
                     params.listener.onFinished(callerLogString);
                 }
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index 0313066..11394e66 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -24,6 +24,7 @@
 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP;
 import static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT;
 import static com.android.server.backup.BackupManagerService.PACKAGE_MANAGER_SENTINEL;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_BACKUP_INTERVAL;
 import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT;
 import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
 
@@ -56,7 +57,6 @@
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.AppWidgetBackupBridge;
 import com.android.server.EventLogTags;
-import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.DataChangedJournal;
 import com.android.server.backup.KeyValueBackupJob;
@@ -142,7 +142,6 @@
     private boolean mFinished;
     private final boolean mUserInitiated;
     private final boolean mNonIncremental;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     private volatile boolean mCancelAll;
 
@@ -163,7 +162,6 @@
         mPendingFullBackups = pendingFullBackups;
         mUserInitiated = userInitiated;
         mNonIncremental = nonIncremental;
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
 
         mStateDir = new File(backupManagerService.getBaseStateDir(), dirName);
         mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
@@ -713,10 +711,8 @@
 
             // Initiate the target's backup pass
             backupManagerService.addBackupTrace("setting timeout");
-            long kvBackupAgentTimeoutMillis =
-                    mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis();
             backupManagerService.prepareOperationTimeout(
-                    mEphemeralOpToken, kvBackupAgentTimeoutMillis, this, OP_TYPE_BACKUP_WAIT);
+                    mEphemeralOpToken, TIMEOUT_BACKUP_INTERVAL, this, OP_TYPE_BACKUP_WAIT);
             backupManagerService.addBackupTrace("calling agent doBackup()");
 
             agent.doBackup(
diff --git a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
index 6175629..e4f3a9d 100644
--- a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
+++ b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
@@ -18,10 +18,10 @@
 
 import static com.android.server.backup.BackupManagerService.DEBUG;
 import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
 
 import android.util.Slog;
 
-import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.BackupRestoreTask;
 
@@ -37,22 +37,18 @@
     private BackupManagerService backupManagerService;
     final CountDownLatch mLatch;
     private final int mCurrentOpToken;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     public AdbRestoreFinishedLatch(BackupManagerService backupManagerService,
             int currentOpToken) {
         this.backupManagerService = backupManagerService;
         mLatch = new CountDownLatch(1);
         mCurrentOpToken = currentOpToken;
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
     }
 
     void await() {
         boolean latched = false;
-        long fullBackupAgentTimeoutMillis =
-                mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
         try {
-            latched = mLatch.await(fullBackupAgentTimeoutMillis, TimeUnit.MILLISECONDS);
+            latched = mLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
         } catch (InterruptedException e) {
             Slog.w(TAG, "Interrupted!");
         }
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index f168afed..c1a1c1d 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -23,6 +23,9 @@
 import static com.android.server.backup.BackupManagerService.OP_TYPE_RESTORE_WAIT;
 import static com.android.server.backup.BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
 import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_RESTORE_INTERVAL;
+import static com.android.server.backup.BackupManagerService
+        .TIMEOUT_SHARED_BACKUP_INTERVAL;
 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
 
 import android.app.ApplicationThreadConstants;
@@ -40,11 +43,10 @@
 import android.util.Slog;
 
 import com.android.server.LocalServices;
-import com.android.server.backup.BackupAgentTimeoutParameters;
-import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.FileMetadata;
 import com.android.server.backup.KeyValueAdbRestoreEngine;
+import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.fullbackup.FullBackupObbConnection;
 import com.android.server.backup.utils.BytesReadListener;
 import com.android.server.backup.utils.FullBackupRestoreObserverUtils;
@@ -119,8 +121,6 @@
 
     final int mEphemeralOpToken;
 
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
-
     public FullRestoreEngine(BackupManagerService backupManagerService,
             BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer,
             IBackupManagerMonitor monitor, PackageInfo onlyPackage, boolean allowApks,
@@ -135,7 +135,6 @@
         mAllowObbs = allowObbs;
         mBuffer = new byte[32 * 1024];
         mBytes = 0;
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
     }
 
     public IBackupAgent getAgent() {
@@ -382,8 +381,8 @@
                         long toCopy = info.size;
                         final boolean isSharedStorage = pkg.equals(SHARED_BACKUP_AGENT_PACKAGE);
                         final long timeout = isSharedStorage ?
-                                mAgentTimeoutParameters.getSharedBackupAgentTimeoutMillis() :
-                                mAgentTimeoutParameters.getRestoreAgentTimeoutMillis();
+                                TIMEOUT_SHARED_BACKUP_INTERVAL :
+                                TIMEOUT_RESTORE_INTERVAL;
                         try {
                             mBackupManagerService.prepareOperationTimeout(token,
                                     timeout,
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 221637c..dacde0b 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -16,6 +16,8 @@
 
 package com.android.server.backup.restore;
 
+import static com.android.server.backup.BackupPasswordManager.PBKDF_CURRENT;
+import static com.android.server.backup.BackupPasswordManager.PBKDF_FALLBACK;
 import static com.android.server.backup.BackupManagerService.BACKUP_FILE_HEADER_MAGIC;
 import static com.android.server.backup.BackupManagerService.BACKUP_FILE_VERSION;
 import static com.android.server.backup.BackupManagerService.BACKUP_MANIFEST_FILENAME;
@@ -26,8 +28,8 @@
 import static com.android.server.backup.BackupManagerService.SETTINGS_PACKAGE;
 import static com.android.server.backup.BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
 import static com.android.server.backup.BackupManagerService.TAG;
-import static com.android.server.backup.BackupPasswordManager.PBKDF_CURRENT;
-import static com.android.server.backup.BackupPasswordManager.PBKDF_FALLBACK;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_RESTORE_INTERVAL;
 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
 
 import android.app.ApplicationThreadConstants;
@@ -47,7 +49,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
-import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.FileMetadata;
 import com.android.server.backup.KeyValueAdbRestoreEngine;
@@ -100,7 +101,6 @@
     private byte[] mWidgetData = null;
 
     private long mBytes;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     // Runner that can be placed on a separate thread to do in-process invocation
     // of the "restore finished" API asynchronously.  Used by adb restore.
@@ -155,7 +155,6 @@
         mAgentPackage = null;
         mTargetApp = null;
         mObbConnection = new FullBackupObbConnection(backupManagerService);
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
 
         // Which packages we've already wiped data on.  We prepopulate this
         // with a whitelist of packages known to be unclearable.
@@ -644,11 +643,9 @@
                     if (okay) {
                         boolean agentSuccess = true;
                         long toCopy = info.size;
-                        long restoreAgentTimeoutMillis =
-                                mAgentTimeoutParameters.getRestoreAgentTimeoutMillis();
                         try {
                             mBackupManagerService.prepareOperationTimeout(
-                                    token, restoreAgentTimeoutMillis, null, OP_TYPE_RESTORE_WAIT);
+                                    token, TIMEOUT_RESTORE_INTERVAL, null, OP_TYPE_RESTORE_WAIT);
 
                             if (FullBackup.OBB_TREE_TOKEN.equals(info.domain)) {
                                 if (DEBUG) {
@@ -823,12 +820,10 @@
                 // In the adb restore case, we do restore-finished here
                 if (doRestoreFinished) {
                     final int token = mBackupManagerService.generateRandomIntegerToken();
-                    long fullBackupAgentTimeoutMillis =
-                            mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
                     final AdbRestoreFinishedLatch latch = new AdbRestoreFinishedLatch(
                             mBackupManagerService, token);
                     mBackupManagerService.prepareOperationTimeout(
-                            token, fullBackupAgentTimeoutMillis, latch, OP_TYPE_RESTORE_WAIT);
+                            token, TIMEOUT_FULL_BACKUP_INTERVAL, latch, OP_TYPE_RESTORE_WAIT);
                     if (mTargetApp.processName.equals("system")) {
                         if (MORE_DEBUG) {
                             Slog.d(TAG, "system agent - restoreFinished on thread");
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 069e3b6..4b467e5 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -23,6 +23,9 @@
 import static com.android.server.backup.BackupManagerService.PACKAGE_MANAGER_SENTINEL;
 import static com.android.server.backup.BackupManagerService.SETTINGS_PACKAGE;
 import static com.android.server.backup.BackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService
+        .TIMEOUT_RESTORE_FINISHED_INTERVAL;
+import static com.android.server.backup.BackupManagerService.TIMEOUT_RESTORE_INTERVAL;
 import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
@@ -56,7 +59,6 @@
 import com.android.server.AppWidgetBackupBridge;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
-import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.BackupUtils;
 import com.android.server.backup.PackageManagerBackupAgent;
@@ -158,7 +160,6 @@
     ParcelFileDescriptor mNewState;
 
     private final int mEphemeralOpToken;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
     // This task can assume that the wakelock is properly held for it and doesn't have to worry
     // about releasing it.
@@ -189,7 +190,6 @@
         mFinished = false;
         mDidLaunch = false;
         mListener = listener;
-        mAgentTimeoutParameters = backupManagerService.getAgentTimeoutParameters();
 
         if (targetPackage != null) {
             // Single package restore
@@ -760,9 +760,8 @@
             // Kick off the restore, checking for hung agents.  The timeout or
             // the operationComplete() callback will schedule the next step,
             // so we do not do that here.
-            long restoreAgentTimeoutMillis = mAgentTimeoutParameters.getRestoreAgentTimeoutMillis();
             backupManagerService.prepareOperationTimeout(
-                    mEphemeralOpToken, restoreAgentTimeoutMillis, this, OP_TYPE_RESTORE_WAIT);
+                    mEphemeralOpToken, TIMEOUT_RESTORE_INTERVAL, this, OP_TYPE_RESTORE_WAIT);
             mAgent.doRestore(mBackupData, appVersionCode, mNewState,
                     mEphemeralOpToken, backupManagerService.getBackupManagerBinder());
         } catch (Exception e) {
@@ -814,11 +813,9 @@
             Slog.d(TAG, "restoreFinished packageName=" + mCurrentPackage.packageName);
         }
         try {
-            long restoreAgentFinishedTimeoutMillis =
-                    mAgentTimeoutParameters.getRestoreAgentFinishedTimeoutMillis();
             backupManagerService
                     .prepareOperationTimeout(mEphemeralOpToken,
-                            restoreAgentFinishedTimeoutMillis, this,
+                            TIMEOUT_RESTORE_FINISHED_INTERVAL, this,
                             OP_TYPE_RESTORE_WAIT);
             mAgent.doRestoreFinished(mEphemeralOpToken,
                     backupManagerService.getBackupManagerBinder());
@@ -1112,10 +1109,9 @@
         } else {
             // We were invoked via an active restore session, not by the Package
             // Manager, so start up the session timeout again.
-            long restoreAgentTimeoutMillis = mAgentTimeoutParameters.getRestoreAgentTimeoutMillis();
             backupManagerService.getBackupHandler().sendEmptyMessageDelayed(
                     MSG_RESTORE_SESSION_TIMEOUT,
-                    restoreAgentTimeoutMillis);
+                    TIMEOUT_RESTORE_INTERVAL);
         }
 
         // Kick off any work that may be needed regarding app widget restores
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 6d773e6..cec4f1a 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -261,6 +261,12 @@
                 // we need to deliver the allow-while-idle alarms for this uid, package
                 unblockAllUnrestrictedAlarms();
             }
+
+            if (!sender.isRunAnyInBackgroundAppOpsAllowed(uid, packageName)) {
+                Slog.v(TAG, "Package " + packageName + "/" + uid
+                        + " toggled into fg service restriction");
+                stopForegroundServicesForUidPackage(uid, packageName);
+            }
         }
 
         /**
@@ -354,6 +360,13 @@
         }
 
         /**
+         * Called when an app goes into forced app standby and its foreground
+         * services need to be removed from that state.
+         */
+        public void stopForegroundServicesForUidPackage(int uid, String packageName) {
+        }
+
+        /**
          * Called when the job restrictions for multiple UIDs might have changed, so the alarm
          * manager should re-evaluate all restrictions for all blocked jobs.
          */
@@ -1057,6 +1070,16 @@
     }
 
     /**
+     * @return whether foreground services should be suppressed in the background
+     * due to forced app standby for the given app
+     */
+    public boolean areForegroundServicesRestricted(int uid, @NonNull String packageName) {
+        synchronized (mLock) {
+            return isRunAnyRestrictedLocked(uid, packageName);
+        }
+    }
+
+    /**
      * @return whether force-app-standby is effective for a UID package-name.
      */
     private boolean isRestricted(int uid, @NonNull String packageName,
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
new file mode 100644
index 0000000..2ed4516
--- /dev/null
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 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;
+
+import android.os.Binder;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.util.Slog;
+
+import com.android.internal.os.BinderCallsStats;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+public class BinderCallsStatsService extends Binder {
+
+    private static final String TAG = "BinderCallsStatsService";
+
+    private static final String PERSIST_SYS_BINDER_CPU_STATS_TRACKING
+            = "persist.sys.binder_cpu_stats_tracking";
+
+    public static void start() {
+        BinderCallsStatsService service = new BinderCallsStatsService();
+        ServiceManager.addService("binder_calls_stats", service);
+        // TODO Enable by default on eng/userdebug builds
+        boolean trackingEnabledDefault = false;
+        boolean trackingEnabled = SystemProperties.getBoolean(PERSIST_SYS_BINDER_CPU_STATS_TRACKING,
+                trackingEnabledDefault);
+
+        if (trackingEnabled) {
+            Slog.i(TAG, "Enabled CPU usage tracking for binder calls. Controlled by "
+                    + PERSIST_SYS_BINDER_CPU_STATS_TRACKING);
+            BinderCallsStats.getInstance().setTrackingEnabled(true);
+        }
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        BinderCallsStats.getInstance().dump(pw);
+    }
+}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 5b57c14..f6ff359 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -3663,16 +3663,21 @@
             }
         }
 
+        boolean reenableMinimumNonAuxSystemImes = false;
         // TODO: The following code should find better place to live.
         if (!resetDefaultEnabledIme) {
             boolean enabledImeFound = false;
+            boolean enabledNonAuxImeFound = false;
             final List<InputMethodInfo> enabledImes = mSettings.getEnabledInputMethodListLocked();
             final int N = enabledImes.size();
             for (int i = 0; i < N; ++i) {
                 final InputMethodInfo imi = enabledImes.get(i);
                 if (mMethodList.contains(imi)) {
                     enabledImeFound = true;
-                    break;
+                    if (!imi.isAuxiliaryIme()) {
+                        enabledNonAuxImeFound = true;
+                        break;
+                    }
                 }
             }
             if (!enabledImeFound) {
@@ -3681,12 +3686,18 @@
                 }
                 resetDefaultEnabledIme = true;
                 resetSelectedInputMethodAndSubtypeLocked("");
+            } else if (!enabledNonAuxImeFound) {
+                if (DEBUG) {
+                    Slog.i(TAG, "All the enabled non-Aux IMEs are gone. Do partial reset.");
+                }
+                reenableMinimumNonAuxSystemImes = true;
             }
         }
 
-        if (resetDefaultEnabledIme) {
+        if (resetDefaultEnabledIme || reenableMinimumNonAuxSystemImes) {
             final ArrayList<InputMethodInfo> defaultEnabledIme =
-                    InputMethodUtils.getDefaultEnabledImes(mContext, mMethodList);
+                    InputMethodUtils.getDefaultEnabledImes(mContext, mMethodList,
+                            reenableMinimumNonAuxSystemImes);
             final int N = defaultEnabledIme.size();
             for (int i = 0; i < N; ++i) {
                 final InputMethodInfo imi =  defaultEnabledIme.get(i);
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 45a4dfb9..d09a161 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -36,6 +36,7 @@
 import android.net.IpSecTransformResponse;
 import android.net.IpSecTunnelInterfaceResponse;
 import android.net.IpSecUdpEncapResponse;
+import android.net.LinkAddress;
 import android.net.Network;
 import android.net.NetworkUtils;
 import android.net.TrafficStats;
@@ -618,10 +619,8 @@
                                 spi,
                                 mConfig.getMarkValue(),
                                 mConfig.getMarkMask());
-            } catch (ServiceSpecificException e) {
-                // FIXME: get the error code and throw is at an IOException from Errno Exception
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to delete SA with ID: " + mResourceId);
+            } catch (RemoteException | ServiceSpecificException e) {
+                Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e);
             }
 
             getResourceTracker().give();
@@ -677,14 +676,14 @@
         @Override
         public void freeUnderlyingResources() {
             try {
-                mSrvConfig
-                        .getNetdInstance()
-                        .ipSecDeleteSecurityAssociation(
-                                mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0);
-            } catch (ServiceSpecificException e) {
-                // FIXME: get the error code and throw is at an IOException from Errno Exception
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId);
+                if (!mOwnedByTransform) {
+                    mSrvConfig
+                            .getNetdInstance()
+                            .ipSecDeleteSecurityAssociation(
+                                    mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0);
+                }
+            } catch (ServiceSpecificException | RemoteException e) {
+                Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e);
             }
 
             mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
@@ -829,15 +828,13 @@
                                         0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff);
                     }
                 }
-            } catch (ServiceSpecificException e) {
-                // FIXME: get the error code and throw is at an IOException from Errno Exception
-            } catch (RemoteException e) {
+            } catch (ServiceSpecificException | RemoteException e) {
                 Log.e(
                         TAG,
                         "Failed to delete VTI with interface name: "
                                 + mInterfaceName
                                 + " and id: "
-                                + mResourceId);
+                                + mResourceId, e);
             }
 
             getResourceTracker().give();
@@ -1319,7 +1316,9 @@
      * from multiple local IP addresses over the same tunnel.
      */
     @Override
-    public synchronized void addAddressToTunnelInterface(int tunnelResourceId, String localAddr) {
+    public synchronized void addAddressToTunnelInterface(
+            int tunnelResourceId, LinkAddress localAddr) {
+        enforceNetworkStackPermission();
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
 
         // Get tunnelInterface record; if no such interface is found, will throw
@@ -1327,8 +1326,21 @@
         TunnelInterfaceRecord tunnelInterfaceInfo =
                 userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
 
-        // TODO: Add calls to netd:
-        //       Add address to TunnelInterface
+        try {
+            // We can assume general validity of the IP address, since we get them as a
+            // LinkAddress, which does some validation.
+            mSrvConfig
+                    .getNetdInstance()
+                    .interfaceAddAddress(
+                            tunnelInterfaceInfo.mInterfaceName,
+                            localAddr.getAddress().getHostAddress(),
+                            localAddr.getPrefixLength());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw.
+            throw new IllegalArgumentException(e);
+        }
     }
 
     /**
@@ -1337,7 +1349,8 @@
      */
     @Override
     public synchronized void removeAddressFromTunnelInterface(
-            int tunnelResourceId, String localAddr) {
+            int tunnelResourceId, LinkAddress localAddr) {
+        enforceNetworkStackPermission();
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
 
         // Get tunnelInterface record; if no such interface is found, will throw
@@ -1345,8 +1358,21 @@
         TunnelInterfaceRecord tunnelInterfaceInfo =
                 userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
 
-        // TODO: Add calls to netd:
-        //       Remove address from TunnelInterface
+        try {
+            // We can assume general validity of the IP address, since we get them as a
+            // LinkAddress, which does some validation.
+            mSrvConfig
+                    .getNetdInstance()
+                    .interfaceDelAddress(
+                            tunnelInterfaceInfo.mInterfaceName,
+                            localAddr.getAddress().getHostAddress(),
+                            localAddr.getPrefixLength());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw.
+            throw new IllegalArgumentException(e);
+        }
     }
 
     /**
@@ -1467,6 +1493,13 @@
         IpSecAlgorithm crypt = c.getEncryption();
         IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption();
 
+        String cryptName;
+        if (crypt == null) {
+            cryptName = (authCrypt == null) ? IpSecAlgorithm.CRYPT_NULL : "";
+        } else {
+            cryptName = crypt.getName();
+        }
+
         mSrvConfig
                 .getNetdInstance()
                 .ipSecAddSecurityAssociation(
@@ -1481,7 +1514,7 @@
                         (auth != null) ? auth.getName() : "",
                         (auth != null) ? auth.getKey() : new byte[] {},
                         (auth != null) ? auth.getTruncationLengthBits() : 0,
-                        (crypt != null) ? crypt.getName() : "",
+                        cryptName,
                         (crypt != null) ? crypt.getKey() : new byte[] {},
                         (crypt != null) ? crypt.getTruncationLengthBits() : 0,
                         (authCrypt != null) ? authCrypt.getName() : "",
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 65e90bad..26b83f5 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
@@ -82,8 +83,6 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.server.location.ActivityRecognitionProxy;
-import com.android.server.location.FlpHardwareProvider;
-import com.android.server.location.FusedProxy;
 import com.android.server.location.GeocoderProxy;
 import com.android.server.location.GeofenceManager;
 import com.android.server.location.GeofenceProxy;
@@ -491,13 +490,6 @@
         if (gpsProvider != null && gpsProvider.isEnabled()) {
             gpsProvider.disable();
         }
-
-        // it is needed to check if FLP HW provider is supported before accessing the instance, this
-        // avoids an exception to be thrown by the singleton factory method
-        if (FlpHardwareProvider.isSupported()) {
-            FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
-            flpHardwareProvider.cleanup();
-        }
     }
 
     /**
@@ -686,27 +678,6 @@
             Slog.e(TAG, "no geocoder provider found");
         }
 
-        // bind to fused hardware provider if supported
-        // in devices without support, requesting an instance of FlpHardwareProvider will raise an
-        // exception, so make sure we only do that when supported
-        FlpHardwareProvider flpHardwareProvider;
-        if (FlpHardwareProvider.isSupported()) {
-            flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
-            FusedProxy fusedProxy = FusedProxy.createAndBind(
-                    mContext,
-                    mLocationHandler,
-                    flpHardwareProvider.getLocationHardware(),
-                    com.android.internal.R.bool.config_enableHardwareFlpOverlay,
-                    com.android.internal.R.string.config_hardwareFlpPackageName,
-                    com.android.internal.R.array.config_locationProviderPackageNames);
-            if (fusedProxy == null) {
-                Slog.d(TAG, "Unable to bind FusedProxy.");
-            }
-        } else {
-            flpHardwareProvider = null;
-            Slog.d(TAG, "FLP HAL not supported");
-        }
-
         // bind to geofence provider
         GeofenceProxy provider = GeofenceProxy.createAndBind(
                 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
@@ -714,7 +685,7 @@
                 com.android.internal.R.array.config_locationProviderPackageNames,
                 mLocationHandler,
                 mGpsGeofenceProxy,
-                flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
+                null);
         if (provider == null) {
             Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
         }
@@ -1161,11 +1132,12 @@
      * Returns the model name of the GNSS hardware.
      */
     @Override
+    @Nullable
     public String getGnssHardwareModelName() {
         if (mGnssSystemInfoProvider != null) {
             return mGnssSystemInfoProvider.getGnssHardwareModelName();
         } else {
-            return LocationManager.GNSS_HARDWARE_MODEL_NAME_UNKNOWN;
+            return null;
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActiveInstrumentation.java b/services/core/java/com/android/server/am/ActiveInstrumentation.java
index 4a65733..ff65951 100644
--- a/services/core/java/com/android/server/am/ActiveInstrumentation.java
+++ b/services/core/java/com/android/server/am/ActiveInstrumentation.java
@@ -24,8 +24,6 @@
 import android.util.PrintWriterPrinter;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.server.am.proto.ActiveInstrumentationProto;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index eb4e32e..e84c5f4 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -56,9 +56,10 @@
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.TransferPipe;
 import com.android.internal.util.FastPrintWriter;
+import com.android.server.AppStateTracker;
+import com.android.server.LocalServices;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
 import com.android.server.am.ActivityManagerService.NeededUriGrants;
-import com.android.server.am.proto.ActiveServicesProto;
 
 import android.app.ActivityManager;
 import android.app.AppGlobals;
@@ -165,6 +166,44 @@
     };
 
     /**
+     * Watch for apps being put into forced app standby, so we can step their fg
+     * services down.
+     */
+    class ForcedStandbyListener extends AppStateTracker.Listener {
+        @Override
+        public void stopForegroundServicesForUidPackage(final int uid, final String packageName) {
+            synchronized (mAm) {
+                final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid));
+                final int N = smap.mServicesByName.size();
+                final ArrayList<ServiceRecord> toStop = new ArrayList<>(N);
+                for (int i = 0; i < N; i++) {
+                    final ServiceRecord r = smap.mServicesByName.valueAt(i);
+                    if (uid == r.serviceInfo.applicationInfo.uid
+                            || packageName.equals(r.serviceInfo.packageName)) {
+                        if (r.isForeground) {
+                            toStop.add(r);
+                        }
+                    }
+                }
+
+                // Now stop them all
+                final int numToStop = toStop.size();
+                if (numToStop > 0 && DEBUG_FOREGROUND_SERVICE) {
+                    Slog.i(TAG, "Package " + packageName + "/" + uid
+                            + " entering FAS with foreground services");
+                }
+                for (int i = 0; i < numToStop; i++) {
+                    final ServiceRecord r = toStop.get(i);
+                    if (DEBUG_FOREGROUND_SERVICE) {
+                        Slog.i(TAG, "  Stopping fg for service " + r);
+                    }
+                    setServiceForegroundInnerLocked(r, 0, null, 0);
+                }
+            }
+        }
+    }
+
+    /**
      * Information about an app that is currently running one or more foreground services.
      * (This maps directly to the running apps we show in the notification.)
      */
@@ -302,6 +341,11 @@
                 ? maxBg : ActivityManager.isLowRamDeviceStatic() ? 1 : 8;
     }
 
+    void systemServicesReady() {
+        AppStateTracker ast = LocalServices.getService(AppStateTracker.class);
+        ast.addListener(new ForcedStandbyListener());
+    }
+
     ServiceRecord getServiceByNameLocked(ComponentName name, int callingUser) {
         // TODO: Deal with global services
         if (DEBUG_MU)
@@ -327,6 +371,12 @@
         return getServiceMapLocked(callingUser).mServicesByName;
     }
 
+    private boolean appRestrictedAnyInBackground(final int uid, final String packageName) {
+        final int mode = mAm.mAppOpsService.checkOperation(
+                AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName);
+        return (mode != AppOpsManager.MODE_ALLOWED);
+    }
+
     ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
             int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
             throws TransactionTooLargeException {
@@ -365,13 +415,24 @@
             return null;
         }
 
+        // If the app has strict background restrictions, we treat any service
+        // start analogously to the legacy-app forced-restrictions case.
+        boolean forcedStandby = false;
+        if (appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
+            if (DEBUG_FOREGROUND_SERVICE) {
+                Slog.d(TAG, "Forcing bg-only service start only for "
+                        + r.name.flattenToShortString());
+            }
+            forcedStandby = true;
+        }
+
         // If this isn't a direct-to-foreground start, check our ability to kick off an
         // arbitrary service
-        if (!r.startRequested && !fgRequired) {
+        if (forcedStandby || (!r.startRequested && !fgRequired)) {
             // Before going further -- if this app is not allowed to start services in the
             // background, then at this point we aren't going to let it period.
             final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
-                    r.appInfo.targetSdkVersion, callingPid, false, false);
+                    r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
             if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                 Slog.w(TAG, "Background start not allowed: service "
                         + service + " to " + r.name.flattenToShortString()
@@ -625,7 +686,7 @@
                 ServiceRecord service = services.mServicesByName.valueAt(i);
                 if (service.appInfo.uid == uid && service.startRequested) {
                     if (mAm.getAppStartModeLocked(service.appInfo.uid, service.packageName,
-                            service.appInfo.targetSdkVersion, -1, false, false)
+                            service.appInfo.targetSdkVersion, -1, false, false, false)
                             != ActivityManager.APP_START_MODE_NORMAL) {
                         if (stopping == null) {
                             stopping = new ArrayList<>();
@@ -1019,7 +1080,10 @@
         }
     }
 
-    private void setServiceForegroundInnerLocked(ServiceRecord r, int id,
+    /**
+     * @param id Notification ID.  Zero === exit foreground state for the given service.
+     */
+    private void setServiceForegroundInnerLocked(final ServiceRecord r, int id,
             Notification notification, int flags) {
         if (id != 0) {
             if (notification == null) {
@@ -1061,44 +1125,56 @@
                 mAm.mHandler.removeMessages(
                         ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
             }
-            if (r.foregroundId != id) {
-                cancelForegroundNotificationLocked(r);
-                r.foregroundId = id;
-            }
-            notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
-            r.foregroundNoti = notification;
-            if (!r.isForeground) {
-                final ServiceMap smap = getServiceMapLocked(r.userId);
-                if (smap != null) {
-                    ActiveForegroundApp active = smap.mActiveForegroundApps.get(r.packageName);
-                    if (active == null) {
-                        active = new ActiveForegroundApp();
-                        active.mPackageName = r.packageName;
-                        active.mUid = r.appInfo.uid;
-                        active.mShownWhileScreenOn = mScreenOn;
-                        if (r.app != null) {
-                            active.mAppOnTop = active.mShownWhileTop =
-                                    r.app.uidRecord.curProcState
-                                            <= ActivityManager.PROCESS_STATE_TOP;
-                        }
-                        active.mStartTime = active.mStartVisibleTime
-                                = SystemClock.elapsedRealtime();
-                        smap.mActiveForegroundApps.put(r.packageName, active);
-                        requestUpdateActiveForegroundAppsLocked(smap, 0);
-                    }
-                    active.mNumActive++;
+
+            // Apps under strict background restrictions simply don't get to have foreground
+            // services, so now that we've enforced the startForegroundService() contract
+            // we only do the machinery of making the service foreground when the app
+            // is not restricted.
+            if (!appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
+                if (r.foregroundId != id) {
+                    cancelForegroundNotificationLocked(r);
+                    r.foregroundId = id;
                 }
-                r.isForeground = true;
-                StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
-                        StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
+                notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
+                r.foregroundNoti = notification;
+                if (!r.isForeground) {
+                    final ServiceMap smap = getServiceMapLocked(r.userId);
+                    if (smap != null) {
+                        ActiveForegroundApp active = smap.mActiveForegroundApps.get(r.packageName);
+                        if (active == null) {
+                            active = new ActiveForegroundApp();
+                            active.mPackageName = r.packageName;
+                            active.mUid = r.appInfo.uid;
+                            active.mShownWhileScreenOn = mScreenOn;
+                            if (r.app != null) {
+                                active.mAppOnTop = active.mShownWhileTop =
+                                        r.app.uidRecord.curProcState
+                                        <= ActivityManager.PROCESS_STATE_TOP;
+                            }
+                            active.mStartTime = active.mStartVisibleTime
+                                    = SystemClock.elapsedRealtime();
+                            smap.mActiveForegroundApps.put(r.packageName, active);
+                            requestUpdateActiveForegroundAppsLocked(smap, 0);
+                        }
+                        active.mNumActive++;
+                    }
+                    r.isForeground = true;
+                    StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
+                            r.appInfo.uid, r.shortName,
+                            StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
+                }
+                r.postNotification();
+                if (r.app != null) {
+                    updateServiceForegroundLocked(r.app, true);
+                }
+                getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r);
+                mAm.notifyPackageUse(r.serviceInfo.packageName,
+                        PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
+            } else {
+                if (DEBUG_FOREGROUND_SERVICE) {
+                    Slog.d(TAG, "Suppressing startForeground() for FAS " + r);
+                }
             }
-            r.postNotification();
-            if (r.app != null) {
-                updateServiceForegroundLocked(r.app, true);
-            }
-            getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r);
-            mAm.notifyPackageUse(r.serviceInfo.packageName,
-                                 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
         } else {
             if (r.isForeground) {
                 final ServiceMap smap = getServiceMapLocked(r.userId);
@@ -1106,7 +1182,8 @@
                     decActiveForegroundAppLocked(smap, r);
                 }
                 r.isForeground = false;
-                StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
+                StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
+                        r.appInfo.uid, r.shortName,
                         StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
                 if (r.app != null) {
                     mAm.updateLruProcessLocked(r.app, false, null);
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 4498077..4a8bc87 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -35,9 +35,9 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.proto.ActivityDisplayProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.proto.ActivityDisplayProto.STACKS;
-import static com.android.server.am.proto.ActivityDisplayProto.ID;
+import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityDisplayProto.STACKS;
+import static com.android.server.am.ActivityDisplayProto.ID;
 
 import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index fb8f749..457564b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -123,7 +123,6 @@
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
-
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
@@ -205,7 +204,6 @@
 import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
-
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
@@ -390,8 +388,8 @@
 import android.view.RemoteAnimationDefinition;
 import android.view.View;
 import android.view.WindowManager;
-
 import android.view.autofill.AutofillManagerInternal;
+
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -443,19 +441,19 @@
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.am.MemoryStatUtil.MemoryStat;
-import com.android.server.am.proto.ActivityManagerServiceProto;
-import com.android.server.am.proto.ActivityManagerServiceDumpActivitiesProto;
-import com.android.server.am.proto.ActivityManagerServiceDumpBroadcastsProto;
-import com.android.server.am.proto.ActivityManagerServiceDumpProcessesProto;
-import com.android.server.am.proto.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
-import com.android.server.am.proto.ActivityManagerServiceDumpServicesProto;
-import com.android.server.am.proto.GrantUriProto;
-import com.android.server.am.proto.ImportanceTokenProto;
-import com.android.server.am.proto.MemInfoDumpProto;
-import com.android.server.am.proto.NeededUriGrantsProto;
-import com.android.server.am.proto.ProcessOomProto;
-import com.android.server.am.proto.ProcessToGcProto;
-import com.android.server.am.proto.StickyBroadcastProto;
+import com.android.server.am.ActivityManagerServiceProto;
+import com.android.server.am.ActivityManagerServiceDumpActivitiesProto;
+import com.android.server.am.ActivityManagerServiceDumpBroadcastsProto;
+import com.android.server.am.ActivityManagerServiceDumpProcessesProto;
+import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
+import com.android.server.am.ActivityManagerServiceDumpServicesProto;
+import com.android.server.am.GrantUriProto;
+import com.android.server.am.ImportanceTokenProto;
+import com.android.server.am.MemInfoDumpProto;
+import com.android.server.am.NeededUriGrantsProto;
+import com.android.server.am.ProcessOomProto;
+import com.android.server.am.ProcessToGcProto;
+import com.android.server.am.StickyBroadcastProto;
 import com.android.server.firewall.IntentFirewall;
 import com.android.server.job.JobSchedulerInternal;
 import com.android.server.pm.Installer;
@@ -2853,6 +2851,7 @@
         public void onBootPhase(int phase) {
             if (phase == PHASE_SYSTEM_SERVICES_READY) {
                 mService.mBatteryStatsService.systemServicesReady();
+                mService.mServices.systemServicesReady();
             }
         }
 
@@ -9118,7 +9117,7 @@
 
     public boolean isAppStartModeDisabled(int uid, String packageName) {
         synchronized (this) {
-            return getAppStartModeLocked(uid, packageName, 0, -1, false, true)
+            return getAppStartModeLocked(uid, packageName, 0, -1, false, true, false)
                     == ActivityManager.APP_START_MODE_DISABLED;
         }
     }
@@ -9194,12 +9193,12 @@
     }
 
     int getAppStartModeLocked(int uid, String packageName, int packageTargetSdk,
-            int callingPid, boolean alwaysRestrict, boolean disabledOnly) {
+            int callingPid, boolean alwaysRestrict, boolean disabledOnly, boolean forcedStandby) {
         UidRecord uidRec = mActiveUids.get(uid);
         if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid + " pkg="
                 + packageName + " rec=" + uidRec + " always=" + alwaysRestrict + " idle="
                 + (uidRec != null ? uidRec.idle : false));
-        if (uidRec == null || alwaysRestrict || uidRec.idle) {
+        if (uidRec == null || alwaysRestrict || forcedStandby || uidRec.idle) {
             boolean ephemeral;
             if (uidRec == null) {
                 ephemeral = getPackageManagerInternalLocked().isPackageEphemeral(
@@ -17093,8 +17092,8 @@
 
             if (mRunningVoice != null) {
                 final long vrToken = proto.start(ActivityManagerServiceDumpProcessesProto.RUNNING_VOICE);
-                proto.write(ActivityManagerServiceDumpProcessesProto.VoiceProto.SESSION, mRunningVoice.toString());
-                mVoiceWakeLock.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.VoiceProto.WAKELOCK);
+                proto.write(ActivityManagerServiceDumpProcessesProto.Voice.SESSION, mRunningVoice.toString());
+                mVoiceWakeLock.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.Voice.WAKELOCK);
                 proto.end(vrToken);
             }
 
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 19ca3be..ccc17a3 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -112,16 +112,16 @@
 import static com.android.server.am.TaskPersister.DEBUG;
 import static com.android.server.am.TaskPersister.IMAGE_EXTENSION;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
-import static com.android.server.am.proto.ActivityRecordProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.proto.ActivityRecordProto.FRONT_OF_TASK;
-import static com.android.server.am.proto.ActivityRecordProto.IDENTIFIER;
-import static com.android.server.am.proto.ActivityRecordProto.PROC_ID;
-import static com.android.server.am.proto.ActivityRecordProto.STATE;
-import static com.android.server.am.proto.ActivityRecordProto.VISIBLE;
+import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
+import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
+import static com.android.server.am.ActivityRecordProto.PROC_ID;
+import static com.android.server.am.ActivityRecordProto.STATE;
+import static com.android.server.am.ActivityRecordProto.VISIBLE;
 import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
-import static com.android.server.wm.proto.IdentifierProto.HASH_CODE;
-import static com.android.server.wm.proto.IdentifierProto.TITLE;
-import static com.android.server.wm.proto.IdentifierProto.USER_ID;
+import static com.android.server.wm.IdentifierProto.HASH_CODE;
+import static com.android.server.wm.IdentifierProto.TITLE;
+import static com.android.server.wm.IdentifierProto.USER_ID;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -2738,11 +2738,6 @@
         } else {
             service.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this);
             setState(PAUSED, "relaunchActivityLocked");
-            // if the app is relaunched when it's stopped, and we're not resuming,
-            // put it back into stopped state.
-            if (stopped) {
-                getStack().addToStopping(this, true /* scheduleIdle */, false /* idleDelayed */);
-            }
         }
 
         configChangeFlags = 0;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 1f5320a..20b938b 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -82,13 +82,13 @@
 import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
-import static com.android.server.am.proto.ActivityStackProto.BOUNDS;
-import static com.android.server.am.proto.ActivityStackProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.proto.ActivityStackProto.DISPLAY_ID;
-import static com.android.server.am.proto.ActivityStackProto.FULLSCREEN;
-import static com.android.server.am.proto.ActivityStackProto.ID;
-import static com.android.server.am.proto.ActivityStackProto.RESUMED_ACTIVITY;
-import static com.android.server.am.proto.ActivityStackProto.TASKS;
+import static com.android.server.am.ActivityStackProto.BOUNDS;
+import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
+import static com.android.server.am.ActivityStackProto.FULLSCREEN;
+import static com.android.server.am.ActivityStackProto.ID;
+import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
+import static com.android.server.am.ActivityStackProto.TASKS;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
 import static android.view.WindowManager.TRANSIT_NONE;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index e4695b6..265e4fa 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -90,12 +90,12 @@
 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
 import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
 import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
-import static com.android.server.am.proto.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.proto.ActivityStackSupervisorProto.DISPLAYS;
-import static com.android.server.am.proto.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
-import static com.android.server.am.proto.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
-import static com.android.server.am.proto.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
-import static com.android.server.am.proto.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
+import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
+import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
+import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
+import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
+import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
 import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 
 import static java.lang.Integer.MAX_VALUE;
@@ -1199,6 +1199,12 @@
         for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
             final int displayId = mTmpOrderedDisplayIds.get(i);
             final ActivityDisplay display = mActivityDisplays.get(displayId);
+
+            // If WindowManagerService has encountered the display before we have, ignore as there
+            // will be no stacks present and therefore no activities.
+            if (display == null) {
+                continue;
+            }
             for (int j = display.getChildCount() - 1; j >= 0; --j) {
                 final ActivityStack stack = display.getChildAt(j);
                 if (stack != focusedStack && stack.isTopStackOnDisplay() && stack.isFocusable()) {
diff --git a/services/core/java/com/android/server/am/AppBindRecord.java b/services/core/java/com/android/server/am/AppBindRecord.java
index 972a692..4eaebd0 100644
--- a/services/core/java/com/android/server/am/AppBindRecord.java
+++ b/services/core/java/com/android/server/am/AppBindRecord.java
@@ -19,8 +19,6 @@
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.server.am.proto.AppBindRecordProto;
-
 import java.io.PrintWriter;
 
 /**
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index ed09879..b2872e4 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -22,7 +22,6 @@
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.server.RescueParty;
 import com.android.server.Watchdog;
-import com.android.server.am.proto.AppErrorsProto;
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
diff --git a/services/core/java/com/android/server/am/AppTimeTracker.java b/services/core/java/com/android/server/am/AppTimeTracker.java
index d96364a..772865d 100644
--- a/services/core/java/com/android/server/am/AppTimeTracker.java
+++ b/services/core/java/com/android/server/am/AppTimeTracker.java
@@ -28,8 +28,6 @@
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
 
-import com.android.server.am.proto.AppTimeTrackerProto;
-
 import java.io.PrintWriter;
 
 /**
diff --git a/services/core/java/com/android/server/am/BroadcastFilter.java b/services/core/java/com/android/server/am/BroadcastFilter.java
index 7ff227f..8e2ca06 100644
--- a/services/core/java/com/android/server/am/BroadcastFilter.java
+++ b/services/core/java/com/android/server/am/BroadcastFilter.java
@@ -21,8 +21,6 @@
 import android.util.Printer;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.server.am.proto.BroadcastFilterProto;
-
 import java.io.PrintWriter;
 
 final class BroadcastFilter extends IntentFilter {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 9a7634e..cc3a887 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -55,8 +55,6 @@
 
 import static com.android.server.am.ActivityManagerDebugConfig.*;
 
-import com.android.server.am.proto.BroadcastQueueProto;
-
 /**
  * BROADCASTS
  *
@@ -1258,7 +1256,7 @@
             if (!skip) {
                 final int allowed = mService.getAppStartModeLocked(
                         info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
-                        info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false);
+                        info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);
                 if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                     // We won't allow this receiver to be launched if the app has been
                     // completely disabled from launches, or it was not explicitly sent
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 5b3b2a8..574ca4a 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -32,8 +32,6 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.server.am.proto.BroadcastRecordProto;
-
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index a8e9ad9..679024ee 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -22,8 +22,6 @@
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
 
-import com.android.server.am.proto.ConnectionRecordProto;
-
 import java.io.PrintWriter;
 
 /**
diff --git a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
index 5bf5020..328426d 100644
--- a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
@@ -36,9 +36,11 @@
 
     private static final String TAG = "GlobalSettingsToPropertiesMapper";
 
+    // List mapping entries in the following format:
+    // {Settings.Global.SETTING_NAME, "system_property_name"}
+    // Important: Property being added should be whitelisted by SELinux policy or have one of the
+    // already whitelisted prefixes in system_server.te, e.g. sys.
     private static final String[][] sGlobalSettingsMapping = new String[][] {
-    //  List mapping entries in the following format:
-    //  {Settings.Global.SETTING_NAME, "system_property_name"},
         {Settings.Global.SYS_VDSO, "sys.vdso"},
         {Settings.Global.FPS_DEVISOR, ThreadedRenderer.DEBUG_FPS_DIVISOR},
         {Settings.Global.DISPLAY_PANEL_LPM, "sys.display_panel_lpm"},
diff --git a/services/core/java/com/android/server/am/IntentBindRecord.java b/services/core/java/com/android/server/am/IntentBindRecord.java
index 3457a80..839b6e1 100644
--- a/services/core/java/com/android/server/am/IntentBindRecord.java
+++ b/services/core/java/com/android/server/am/IntentBindRecord.java
@@ -23,9 +23,6 @@
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.server.am.proto.AppBindRecordProto;
-import com.android.server.am.proto.IntentBindRecordProto;
-
 import java.io.PrintWriter;
 
 /**
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 0d7eab6..b67dd0d 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -25,8 +25,8 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.am.proto.KeyguardControllerProto.KEYGUARD_OCCLUDED;
-import static com.android.server.am.proto.KeyguardControllerProto.KEYGUARD_SHOWING;
+import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED;
+import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
new file mode 100644
index 0000000..9964053
--- /dev/null
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -0,0 +1,4 @@
+per-file GlobalSettingsToPropertiesMapper.java=fkupolov@google.com
+per-file GlobalSettingsToPropertiesMapper.java=omakoto@google.com
+per-file GlobalSettingsToPropertiesMapper.java=svetoslavganov@google.com
+per-file GlobalSettingsToPropertiesMapper.java=yamasani@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 0bf2691..e348bf4 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -27,7 +27,6 @@
 import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.app.procstats.ProcessState;
 import com.android.internal.os.BatteryStatsImpl;
-import com.android.server.am.proto.ProcessRecordProto;
 
 import android.app.ActivityManager;
 import android.app.Dialog;
diff --git a/services/core/java/com/android/server/am/ReceiverList.java b/services/core/java/com/android/server/am/ReceiverList.java
index eee924f..5e31b2e 100644
--- a/services/core/java/com/android/server/am/ReceiverList.java
+++ b/services/core/java/com/android/server/am/ReceiverList.java
@@ -25,7 +25,6 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.server.IntentResolver;
-import com.android.server.am.proto.ReceiverListProto;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 49a55cb..f296c60 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -19,7 +19,6 @@
 import com.android.internal.app.procstats.ServiceState;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.server.LocalServices;
-import com.android.server.am.proto.ServiceRecordProto;
 import com.android.server.notification.NotificationManagerInternal;
 
 import android.app.INotificationManager;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index c7b89d3..034cb2e 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -62,19 +62,19 @@
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.am.proto.TaskRecordProto.ACTIVITIES;
-import static com.android.server.am.proto.TaskRecordProto.BOUNDS;
-import static com.android.server.am.proto.TaskRecordProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.proto.TaskRecordProto.FULLSCREEN;
-import static com.android.server.am.proto.TaskRecordProto.ID;
-import static com.android.server.am.proto.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
-import static com.android.server.am.proto.TaskRecordProto.MIN_HEIGHT;
-import static com.android.server.am.proto.TaskRecordProto.MIN_WIDTH;
-import static com.android.server.am.proto.TaskRecordProto.ORIG_ACTIVITY;
-import static com.android.server.am.proto.TaskRecordProto.REAL_ACTIVITY;
-import static com.android.server.am.proto.TaskRecordProto.RESIZE_MODE;
-import static com.android.server.am.proto.TaskRecordProto.STACK_ID;
-import static com.android.server.am.proto.TaskRecordProto.ACTIVITY_TYPE;
+import static com.android.server.am.TaskRecordProto.ACTIVITIES;
+import static com.android.server.am.TaskRecordProto.BOUNDS;
+import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.TaskRecordProto.FULLSCREEN;
+import static com.android.server.am.TaskRecordProto.ID;
+import static com.android.server.am.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
+import static com.android.server.am.TaskRecordProto.MIN_HEIGHT;
+import static com.android.server.am.TaskRecordProto.MIN_WIDTH;
+import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY;
+import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
+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.ACTIVITY_TYPE;
 
 import static java.lang.Integer.MAX_VALUE;
 
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index d49f3ba..3b859ed 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -28,7 +28,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.am.proto.UidRecordProto;
 
 /**
  * Overall information about a uid that has actively running processes.
diff --git a/services/core/java/com/android/server/am/UriPermissionOwner.java b/services/core/java/com/android/server/am/UriPermissionOwner.java
index fc07c1a..8eda38e 100644
--- a/services/core/java/com/android/server/am/UriPermissionOwner.java
+++ b/services/core/java/com/android/server/am/UriPermissionOwner.java
@@ -22,8 +22,6 @@
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.server.am.proto.UriPermissionOwnerProto;
-
 import com.google.android.collect.Sets;
 
 import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index af1ab83..0d125e0 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -95,7 +95,6 @@
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemServiceManager;
-import com.android.server.am.proto.UserControllerProto;
 import com.android.server.pm.UserManagerService;
 import com.android.server.wm.WindowManagerService;
 
diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java
index 00597e2..4f5c59c 100644
--- a/services/core/java/com/android/server/am/UserState.java
+++ b/services/core/java/com/android/server/am/UserState.java
@@ -27,7 +27,6 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.ProgressReporter;
-import com.android.server.am.proto.UserStateProto;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/am/VrController.java b/services/core/java/com/android/server/am/VrController.java
index 9d34a80..45410d7 100644
--- a/services/core/java/com/android/server/am/VrController.java
+++ b/services/core/java/com/android/server/am/VrController.java
@@ -24,7 +24,6 @@
 import android.util.proto.ProtoUtils;
 
 import com.android.server.LocalServices;
-import com.android.server.am.proto.ActivityManagerServiceDumpProcessesProto.VrControllerProto;
 import com.android.server.vr.VrManagerInternal;
 
 /**
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 171f40e..88df195 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -25,12 +25,14 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ParceledListSlice;
+import android.database.ContentObserver;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.hardware.display.AmbientBrightnessDayStats;
 import android.hardware.display.BrightnessChangeEvent;
+import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Environment;
 import android.os.Handler;
@@ -110,6 +112,8 @@
 
     private static final int MSG_BACKGROUND_START = 0;
     private static final int MSG_BRIGHTNESS_CHANGED = 1;
+    private static final int MSG_STOP_SENSOR_LISTENER = 2;
+    private static final int MSG_START_SENSOR_LISTENER = 3;
 
     // Lock held while accessing mEvents, is held while writing events to flash.
     private final Object mEventsLock = new Object();
@@ -127,9 +131,14 @@
     private final Context mContext;
     private final ContentResolver mContentResolver;
     private Handler mBgHandler;
-    // mBroadcastReceiver and mSensorListener should only be used on the mBgHandler thread.
+
+    // mBroadcastReceiver,  mSensorListener, mSettingsObserver and mSensorRegistered
+    // should only be used on the mBgHandler thread.
     private BroadcastReceiver mBroadcastReceiver;
     private SensorListener mSensorListener;
+    private SettingsObserver mSettingsObserver;
+    private boolean mSensorRegistered;
+
     private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL;
 
     // Lock held while collecting data related to brightness changes.
@@ -178,10 +187,9 @@
 
         mSensorListener = new SensorListener();
 
-
-        if (mInjector.isInteractive(mContext)) {
-            mInjector.registerSensorListener(mContext, mSensorListener, mBgHandler);
-        }
+        mSettingsObserver = new SettingsObserver(mBgHandler);
+        mInjector.registerBrightnessModeObserver(mContentResolver, mSettingsObserver);
+        startSensorListener();
 
         final IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_SHUTDOWN);
@@ -205,10 +213,11 @@
             Slog.d(TAG, "Stop");
         }
         mBgHandler.removeMessages(MSG_BACKGROUND_START);
+        stopSensorListener();
         mInjector.unregisterSensorListener(mContext, mSensorListener);
+        mInjector.unregisterBrightnessModeObserver(mContext, mSettingsObserver);
         mInjector.unregisterReceiver(mContext, mBroadcastReceiver);
         mInjector.cancelIdleJob(mContext);
-        mAmbientBrightnessStatsTracker.stop();
 
         synchronized (mDataCollectionLock) {
             mStarted = false;
@@ -366,6 +375,25 @@
         }
     }
 
+    private void startSensorListener() {
+        if (!mSensorRegistered
+                && mInjector.isInteractive(mContext)
+                && mInjector.isBrightnessModeAutomatic(mContentResolver)) {
+            mAmbientBrightnessStatsTracker.start();
+            mSensorRegistered = true;
+            mInjector.registerSensorListener(mContext, mSensorListener,
+                    mInjector.getBackgroundHandler());
+        }
+    }
+
+    private void stopSensorListener() {
+        if (mSensorRegistered) {
+            mAmbientBrightnessStatsTracker.stop();
+            mInjector.unregisterSensorListener(mContext, mSensorListener);
+            mSensorRegistered = false;
+        }
+    }
+
     private void scheduleWriteBrightnessTrackerState() {
         if (!mWriteBrightnessTrackerStateScheduled) {
             mBgHandler.post(() -> {
@@ -724,6 +752,24 @@
         }
     }
 
+    private final class SettingsObserver extends ContentObserver {
+        public SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            if (DEBUG) {
+                Slog.v(TAG, "settings change " + uri);
+            }
+            if (mInjector.isBrightnessModeAutomatic(mContentResolver)) {
+                mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget();
+            } else {
+                mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget();
+            }
+        }
+    }
+
     private final class Receiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -741,12 +787,9 @@
                     batteryLevelChanged(level, scale);
                 }
             } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
-                mAmbientBrightnessStatsTracker.stop();
-                mInjector.unregisterSensorListener(mContext, mSensorListener);
+                mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget();
             } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
-                mAmbientBrightnessStatsTracker.start();
-                mInjector.registerSensorListener(mContext, mSensorListener,
-                        mInjector.getBackgroundHandler());
+                mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget();
             }
         }
     }
@@ -767,6 +810,12 @@
                             values.powerBrightnessFactor, values.isUserSetBrightness,
                             values.isDefaultBrightnessConfig);
                     break;
+                case MSG_START_SENSOR_LISTENER:
+                    startSensorListener();
+                    break;
+                case MSG_STOP_SENSOR_LISTENER:
+                    stopSensorListener();
+                    break;
             }
         }
     }
@@ -801,6 +850,18 @@
             sensorManager.unregisterListener(sensorListener);
         }
 
+        public void registerBrightnessModeObserver(ContentResolver resolver,
+                ContentObserver settingsObserver) {
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.SCREEN_BRIGHTNESS_MODE),
+                    false, settingsObserver, UserHandle.USER_ALL);
+        }
+
+        public void unregisterBrightnessModeObserver(Context context,
+                ContentObserver settingsObserver) {
+            context.getContentResolver().unregisterContentObserver(settingsObserver);
+        }
+
         public void registerReceiver(Context context,
                 BroadcastReceiver receiver, IntentFilter filter) {
             context.registerReceiver(receiver, filter);
@@ -815,6 +876,12 @@
             return BackgroundThread.getHandler();
         }
 
+        public boolean isBrightnessModeAutomatic(ContentResolver resolver) {
+            return Settings.System.getIntForUser(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE,
+                    Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT)
+                    == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
+        }
+
         public int getSecureIntForUser(ContentResolver resolver, String setting, int defaultValue,
                 int userId) {
             return Settings.Secure.getIntForUser(resolver, setting, defaultValue, userId);
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 0b1f9a6..66817fa 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -29,6 +29,7 @@
 import android.app.job.IJobScheduler;
 import android.app.job.JobInfo;
 import android.app.job.JobParameters;
+import android.app.job.JobProtoEnums;
 import android.app.job.JobScheduler;
 import android.app.job.JobService;
 import android.app.job.JobWorkItem;
@@ -880,7 +881,8 @@
             startTrackingJobLocked(jobStatus, toCancel);
             StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED,
                     uId, null, jobStatus.getBatteryName(),
-                    StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__SCHEDULED);
+                    StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__SCHEDULED,
+                    JobProtoEnums.STOP_REASON_CANCELLED);
 
             // If the job is immediately ready to run, then we can just immediately
             // put it in the pending list and try to schedule it.  This is especially
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 578a32c..a1e066e 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -95,11 +95,18 @@
     public static final long MIN_TRIGGER_MAX_DELAY = 1000;
 
     final JobInfo job;
-    /** Uid of the package requesting this job. */
+    /**
+     * Uid of the package requesting this job.  This can differ from the "source"
+     * uid when the job was scheduled on the app's behalf, such as with the jobs
+     * that underly Sync Manager operation.
+     */
     final int callingUid;
     final int targetSdkVersion;
     final String batteryName;
 
+    /**
+     * Identity of the app in which the job is hosted.
+     */
     final String sourcePackageName;
     final int sourceUserId;
     final int sourceUid;
@@ -263,6 +270,31 @@
         return callingUid;
     }
 
+    /**
+     * Core constructor for JobStatus instances.  All other ctors funnel down to this one.
+     *
+     * @param job The actual requested parameters for the job
+     * @param callingUid Identity of the app that is scheduling the job.  This may not be the
+     *     app in which the job is implemented; such as with sync jobs.
+     * @param targetSdkVersion The targetSdkVersion of the app in which the job will run.
+     * @param sourcePackageName The package name of the app in which the job will run.
+     * @param sourceUserId The user in which the job will run
+     * @param standbyBucket The standby bucket that the source package is currently assigned to,
+     *     cached here for speed of handling during runnability evaluations (and updated when bucket
+     *     assignments are changed)
+     * @param heartbeat Timestamp of when the job was created, in the standby-related
+     *     timebase.
+     * @param tag A string associated with the job for debugging/logging purposes.
+     * @param numFailures Count of how many times this job has requested a reschedule because
+     *     its work was not yet finished.
+     * @param earliestRunTimeElapsedMillis Milestone: earliest point in time at which the job
+     *     is to be considered runnable
+     * @param latestRunTimeElapsedMillis Milestone: point in time at which the job will be
+     *     considered overdue
+     * @param lastSuccessfulRunTime When did we last run this job to completion?
+     * @param lastFailedRunTime When did we last run this job only to have it stop incomplete?
+     * @param internalFlags Non-API property flags about this job
+     */
     private JobStatus(JobInfo job, int callingUid, int targetSdkVersion, String sourcePackageName,
             int sourceUserId, int standbyBucket, long heartbeat, String tag, int numFailures,
             long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
@@ -399,8 +431,8 @@
     /**
      * Create a newly scheduled job.
      * @param callingUid Uid of the package that scheduled this job.
-     * @param sourcePkg Package name on whose behalf this job is scheduled. Null indicates
-     *                          the calling package is the source.
+     * @param sourcePkg Package name of the app that will actually run the job.  Null indicates
+     *     that the calling package is the source.
      * @param sourceUserId User id for whom this job is scheduled. -1 indicates this is same as the
      *     caller.
      */
diff --git a/services/core/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java
deleted file mode 100644
index 5c9b0ea..0000000
--- a/services/core/java/com/android/server/location/FlpHardwareProvider.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 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.location;
-
-import android.content.Context;
-import android.hardware.location.IFusedLocationHardware;
-import android.location.IFusedGeofenceHardware;
-import android.util.Log;
-
-/**
- * This class was an interop layer for JVM types and the JNI code that interacted
- * with the FLP HAL implementation.
- *
- * Now, after Treble FLP & GNSS HAL simplification, it is a thin shell that acts like the
- * pre-existing cases where there was no FLP Hardware support, to keep legacy users of this
- * class operating.
- *
- * {@hide}
- * {@Deprecated}
- */
-public class FlpHardwareProvider {
-    private static FlpHardwareProvider sSingletonInstance = null;
-
-    private final static String TAG = "FlpHardwareProvider";
-
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    public static FlpHardwareProvider getInstance(Context context) {
-        if (sSingletonInstance == null) {
-            sSingletonInstance = new FlpHardwareProvider();
-            if (DEBUG) Log.d(TAG, "getInstance() created empty provider");
-        }
-        return sSingletonInstance;
-    }
-
-    private FlpHardwareProvider() {
-    }
-
-    public static boolean isSupported() {
-        if (DEBUG) Log.d(TAG, "isSupported() returning false");
-        return false;
-    }
-
-    /**
-     * Interface implementations for services built on top of this functionality.
-     */
-    public static final String LOCATION = "Location";
-
-    public IFusedLocationHardware getLocationHardware() {
-        return null;
-    }
-
-    public IFusedGeofenceHardware getGeofenceHardware() {
-        return null;
-    }
-
-    public void cleanup() {
-        if (DEBUG) Log.d(TAG, "empty cleanup()");
-    }
-}
diff --git a/services/core/java/com/android/server/location/FusedLocationHardwareSecure.java b/services/core/java/com/android/server/location/FusedLocationHardwareSecure.java
deleted file mode 100644
index a08d326..0000000
--- a/services/core/java/com/android/server/location/FusedLocationHardwareSecure.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2013 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.location;
-
-import android.content.Context;
-import android.hardware.location.IFusedLocationHardware;
-import android.hardware.location.IFusedLocationHardwareSink;
-import android.location.FusedBatchOptions;
-import android.os.RemoteException;
-
-/**
- * FusedLocationHardware decorator that adds permission checking.
- * @hide
- */
-public class FusedLocationHardwareSecure extends IFusedLocationHardware.Stub {
-    private final IFusedLocationHardware mLocationHardware;
-    private final Context mContext;
-    private final String mPermissionId;
-
-    public FusedLocationHardwareSecure(
-            IFusedLocationHardware locationHardware,
-            Context context,
-            String permissionId) {
-        mLocationHardware = locationHardware;
-        mContext = context;
-        mPermissionId = permissionId;
-    }
-
-    private void checkPermissions() {
-        mContext.enforceCallingPermission(
-                mPermissionId,
-                String.format(
-                        "Permission '%s' not granted to access FusedLocationHardware",
-                        mPermissionId));
-    }
-
-    @Override
-    public void registerSink(IFusedLocationHardwareSink eventSink) throws RemoteException {
-        checkPermissions();
-        mLocationHardware.registerSink(eventSink);
-    }
-
-    @Override
-    public void unregisterSink(IFusedLocationHardwareSink eventSink) throws RemoteException {
-        checkPermissions();
-        mLocationHardware.unregisterSink(eventSink);
-    }
-
-    @Override
-    public int getSupportedBatchSize() throws RemoteException {
-        checkPermissions();
-        return mLocationHardware.getSupportedBatchSize();
-    }
-
-    @Override
-    public void startBatching(int id, FusedBatchOptions batchOptions) throws RemoteException {
-        checkPermissions();
-        mLocationHardware.startBatching(id, batchOptions);
-    }
-
-    @Override
-    public void stopBatching(int id) throws RemoteException {
-        checkPermissions();
-        mLocationHardware.stopBatching(id);
-    }
-
-    @Override
-    public void updateBatchingOptions(
-            int id,
-            FusedBatchOptions batchoOptions
-            ) throws RemoteException {
-        checkPermissions();
-        mLocationHardware.updateBatchingOptions(id, batchoOptions);
-    }
-
-    @Override
-    public void requestBatchOfLocations(int batchSizeRequested) throws RemoteException {
-        checkPermissions();
-        mLocationHardware.requestBatchOfLocations(batchSizeRequested);
-    }
-
-    @Override
-    public boolean supportsDiagnosticDataInjection() throws RemoteException {
-        checkPermissions();
-        return mLocationHardware.supportsDiagnosticDataInjection();
-    }
-
-    @Override
-    public void injectDiagnosticData(String data) throws RemoteException {
-        checkPermissions();
-        mLocationHardware.injectDiagnosticData(data);
-    }
-
-    @Override
-    public boolean supportsDeviceContextInjection() throws RemoteException {
-        checkPermissions();
-        return mLocationHardware.supportsDeviceContextInjection();
-    }
-
-    @Override
-    public void injectDeviceContext(int deviceEnabledContext) throws RemoteException {
-        checkPermissions();
-        mLocationHardware.injectDeviceContext(deviceEnabledContext);
-    }
-
-    @Override
-    public void flushBatchedLocations() throws RemoteException {
-        checkPermissions();
-        mLocationHardware.flushBatchedLocations();
-    }
-
-    @Override
-    public int getVersion() throws RemoteException {
-        checkPermissions();
-        return mLocationHardware.getVersion();
-    }
-}
diff --git a/services/core/java/com/android/server/location/FusedProxy.java b/services/core/java/com/android/server/location/FusedProxy.java
deleted file mode 100644
index b90f037..0000000
--- a/services/core/java/com/android/server/location/FusedProxy.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2013 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 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.location;
-
-import com.android.server.ServiceWatcher;
-
-import android.Manifest;
-import android.content.Context;
-import android.hardware.location.IFusedLocationHardware;
-import android.location.IFusedProvider;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * Proxy that helps bind GCore FusedProvider implementations to the Fused Hardware instances.
- *
- * @hide
- */
-public final class FusedProxy {
-    private final String TAG = "FusedProxy";
-    private final ServiceWatcher mServiceWatcher;
-    private final FusedLocationHardwareSecure mLocationHardware;
-
-    /**
-     * Constructor of the class.
-     * This is private as the class follows a factory pattern for construction.
-     *
-     * @param context           The context needed for construction.
-     * @param handler           The handler needed for construction.
-     * @param locationHardware  The instance of the Fused location hardware assigned to the proxy.
-     */
-    private FusedProxy(
-            Context context,
-            Handler handler,
-            IFusedLocationHardware locationHardware,
-            int overlaySwitchResId,
-            int defaultServicePackageNameResId,
-            int initialPackageNameResId) {
-        mLocationHardware = new FusedLocationHardwareSecure(
-                locationHardware,
-                context,
-                Manifest.permission.LOCATION_HARDWARE);
-        Runnable newServiceWork = new Runnable() {
-            @Override
-            public void run() {
-                bindProvider(mLocationHardware);
-            }
-        };
-
-        // prepare the connection to the provider
-        mServiceWatcher = new ServiceWatcher(
-                context,
-                TAG,
-                "com.android.location.service.FusedProvider",
-                overlaySwitchResId,
-                defaultServicePackageNameResId,
-                initialPackageNameResId,
-                newServiceWork,
-                handler);
-    }
-
-    /**
-     * Creates an instance of the proxy and binds it to the appropriate FusedProvider.
-     *
-     * @param context           The context needed for construction.
-     * @param handler           The handler needed for construction.
-     * @param locationHardware  The instance of the Fused location hardware assigned to the proxy.
-     *
-     * @return An instance of the proxy if it could be bound, null otherwise.
-     */
-    public static FusedProxy createAndBind(
-            Context context,
-            Handler handler,
-            IFusedLocationHardware locationHardware,
-            int overlaySwitchResId,
-            int defaultServicePackageNameResId,
-            int initialPackageNameResId) {
-        FusedProxy fusedProxy = new FusedProxy(
-                context,
-                handler,
-                locationHardware,
-                overlaySwitchResId,
-                defaultServicePackageNameResId,
-                initialPackageNameResId);
-
-        // try to bind the Fused provider
-        if (!fusedProxy.mServiceWatcher.start()) {
-            return null;
-        }
-
-        return fusedProxy;
-    }
-
-    /**
-     * Helper function to bind the FusedLocationHardware to the appropriate FusedProvider instance.
-     *
-     * @param locationHardware  The FusedLocationHardware instance to use for the binding operation.
-     */
-    private void bindProvider(IFusedLocationHardware locationHardware) {
-        if (!mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                IFusedProvider provider = IFusedProvider.Stub.asInterface(binder);
-                try {
-                    provider.onFusedLocationHardwareChange(locationHardware);
-                } catch (RemoteException e) {
-                    Log.e(TAG, e.toString());
-                }
-            }
-        })) {
-            Log.e(TAG, "No instance of FusedProvider found on FusedLocationHardware connected.");
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index e02feec..8f0e1da 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -470,7 +470,7 @@
 
     // Volatile for simple inter-thread sync on these values.
     private volatile int mHardwareYear = 0;
-    private volatile String mHardwareModelName = LocationManager.GNSS_HARDWARE_MODEL_NAME_UNKNOWN;
+    private volatile String mHardwareModelName;
 
     // Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
     // stops output right at 600m/s, depriving this of the information of a device that reaches
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index f46657c..a87adbd 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -255,9 +255,6 @@
             }
         }
 
-        // TODO: make sure the same counter id is used during recovery and remove temporary fix.
-        counterId = 1L;
-
         byte[] vaultParams = KeySyncUtils.packVaultParams(
                 publicKey,
                 counterId,
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 5b10add..e03e86f1 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -416,8 +416,8 @@
      * @param vaultChallenge Challenge issued by vault service.
      * @param secrets Lock-screen hashes. For now only a single secret is supported.
      * @return Encrypted bytes of recovery claim. This can then be issued to the vault service.
-     * @deprecated Use {@link #startRecoverySessionWithCertPath(String, RecoveryCertPath, byte[],
-     *         byte[], List)} instead.
+     * @deprecated Use {@link #startRecoverySessionWithCertPath(String, String, RecoveryCertPath,
+     *         byte[], byte[], List)} instead.
      *
      * @hide
      */
@@ -457,6 +457,7 @@
                 uid,
                 new RecoverySessionStorage.Entry(sessionId, kfHash, keyClaimant, vaultParams));
 
+        Log.i(TAG, "Received VaultParams for recovery: " + HexDump.toHexString(vaultParams));
         try {
             byte[] thmKfHash = KeySyncUtils.calculateThmKfHash(kfHash);
             return KeySyncUtils.encryptRecoveryClaim(
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 052f239..26e9a9a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10355,7 +10355,7 @@
 
         if (Build.IS_DEBUGGABLE &&
                 pkg.isPrivileged() &&
-                !SystemProperties.getBoolean("pm.dexopt.priv-apps", true)) {
+                !SystemProperties.getBoolean(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB, true)) {
             PackageManagerServiceUtils.logPackageHasUncompressedCode(pkg);
         }
 
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index cf88bd5..eca6f9f 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -16,8 +16,8 @@
 
 package com.android.server.policy;
 
-import static com.android.server.wm.proto.BarControllerProto.STATE;
-import static com.android.server.wm.proto.BarControllerProto.TRANSIENT_STATE;
+import static com.android.server.wm.BarControllerProto.STATE;
+import static com.android.server.wm.BarControllerProto.TRANSIENT_STATE;
 
 import android.app.StatusBarManager;
 import android.graphics.Rect;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 61b1eb4..6b70f5c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -128,26 +128,26 @@
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.FOCUSED_APP_TOKEN;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.FOCUSED_WINDOW;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.FORCE_STATUS_BAR;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.FORCE_STATUS_BAR_FROM_KEYGUARD;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.KEYGUARD_DELEGATE;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.KEYGUARD_DRAW_COMPLETE;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.KEYGUARD_OCCLUDED;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.KEYGUARD_OCCLUDED_CHANGED;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.KEYGUARD_OCCLUDED_PENDING;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.LAST_SYSTEM_UI_FLAGS;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.NAVIGATION_BAR;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.ORIENTATION;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.ORIENTATION_LISTENER;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.ROTATION;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.ROTATION_MODE;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.SCREEN_ON_FULLY;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.STATUS_BAR;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.TOP_FULLSCREEN_OPAQUE_OR_DIMMING_WINDOW;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.TOP_FULLSCREEN_OPAQUE_WINDOW;
-import static com.android.server.wm.proto.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW_COMPLETE;
+import static com.android.server.wm.WindowManagerPolicyProto.FOCUSED_APP_TOKEN;
+import static com.android.server.wm.WindowManagerPolicyProto.FOCUSED_WINDOW;
+import static com.android.server.wm.WindowManagerPolicyProto.FORCE_STATUS_BAR;
+import static com.android.server.wm.WindowManagerPolicyProto.FORCE_STATUS_BAR_FROM_KEYGUARD;
+import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DELEGATE;
+import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DRAW_COMPLETE;
+import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_OCCLUDED;
+import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_OCCLUDED_CHANGED;
+import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_OCCLUDED_PENDING;
+import static com.android.server.wm.WindowManagerPolicyProto.LAST_SYSTEM_UI_FLAGS;
+import static com.android.server.wm.WindowManagerPolicyProto.NAVIGATION_BAR;
+import static com.android.server.wm.WindowManagerPolicyProto.ORIENTATION;
+import static com.android.server.wm.WindowManagerPolicyProto.ORIENTATION_LISTENER;
+import static com.android.server.wm.WindowManagerPolicyProto.ROTATION;
+import static com.android.server.wm.WindowManagerPolicyProto.ROTATION_MODE;
+import static com.android.server.wm.WindowManagerPolicyProto.SCREEN_ON_FULLY;
+import static com.android.server.wm.WindowManagerPolicyProto.STATUS_BAR;
+import static com.android.server.wm.WindowManagerPolicyProto.TOP_FULLSCREEN_OPAQUE_OR_DIMMING_WINDOW;
+import static com.android.server.wm.WindowManagerPolicyProto.TOP_FULLSCREEN_OPAQUE_WINDOW;
+import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW_COMPLETE;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 6674e18..ec0521d 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -488,7 +488,7 @@
         boolean canAcquireSleepToken();
 
         /**
-         * Writes {@link com.android.server.wm.proto.IdentifierProto} to stream.
+         * Writes {@link com.android.server.wm.IdentifierProto} to stream.
          */
         void writeIdentifierToProto(ProtoOutputStream proto, long fieldId);
     }
@@ -1626,7 +1626,7 @@
 
     /**
      * Write the WindowManagerPolicy's state into the protocol buffer.
-     * The message is described in {@link com.android.server.wm.proto.WindowManagerPolicyProto}
+     * The message is described in {@link com.android.server.wm.WindowManagerPolicyProto}
      *
      * @param proto The protocol buffer output stream to write to.
      */
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index 48a196d..1508c9e 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -16,8 +16,8 @@
 
 package com.android.server.policy;
 
-import static com.android.server.wm.proto.WindowOrientationListenerProto.ENABLED;
-import static com.android.server.wm.proto.WindowOrientationListenerProto.ROTATION;
+import static com.android.server.wm.WindowOrientationListenerProto.ENABLED;
+import static com.android.server.wm.WindowOrientationListenerProto.ROTATION;
 
 import android.content.Context;
 import android.hardware.Sensor;
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 58e8f77..062b154 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -1,11 +1,11 @@
 package com.android.server.policy.keyguard;
 
 import static android.view.Display.INVALID_DISPLAY;
-import static com.android.server.wm.proto.KeyguardServiceDelegateProto.INTERACTIVE_STATE;
-import static com.android.server.wm.proto.KeyguardServiceDelegateProto.OCCLUDED;
-import static com.android.server.wm.proto.KeyguardServiceDelegateProto.SCREEN_STATE;
-import static com.android.server.wm.proto.KeyguardServiceDelegateProto.SECURE;
-import static com.android.server.wm.proto.KeyguardServiceDelegateProto.SHOWING;
+import static com.android.server.wm.KeyguardServiceDelegateProto.INTERACTIVE_STATE;
+import static com.android.server.wm.KeyguardServiceDelegateProto.OCCLUDED;
+import static com.android.server.wm.KeyguardServiceDelegateProto.SCREEN_STATE;
+import static com.android.server.wm.KeyguardServiceDelegateProto.SECURE;
+import static com.android.server.wm.KeyguardServiceDelegateProto.SHOWING;
 
 import android.app.ActivityManager;
 import android.content.ComponentName;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 40a94a7..dd88cd1 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -896,7 +896,7 @@
         mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger(
                 com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff);
         mDozeAfterScreenOff = resources.getBoolean(
-                com.android.internal.R.bool.config_dozeAfterScreenOff);
+                com.android.internal.R.bool.config_dozeAfterScreenOffByDefault);
         mMinimumScreenOffTimeoutConfig = resources.getInteger(
                 com.android.internal.R.integer.config_minimumScreenOffTimeout);
         mMaximumScreenDimDurationConfig = resources.getInteger(
@@ -1723,7 +1723,7 @@
 
                 // Update wireless dock detection state.
                 final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
-                        mIsPowered, mPlugType, mBatteryLevel);
+                        mIsPowered, mPlugType);
 
                 // Treat plugging and unplugging the devices as a user activity.
                 // Users find it disconcerting when they plug or unplug the device
diff --git a/services/core/java/com/android/server/power/WirelessChargerDetector.java b/services/core/java/com/android/server/power/WirelessChargerDetector.java
index 54487e3..18e5ce4 100644
--- a/services/core/java/com/android/server/power/WirelessChargerDetector.java
+++ b/services/core/java/com/android/server/power/WirelessChargerDetector.java
@@ -84,10 +84,6 @@
     // The minimum number of samples that must be collected.
     private static final int MIN_SAMPLES = 3;
 
-    // Upper bound on the battery charge percentage in order to consider turning
-    // the screen on when the device starts charging wirelessly.
-    private static final int WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT = 95;
-
     // To detect movement, we compute the angle between the gravity vector
     // at rest and the current gravity vector.  This field specifies the
     // cosine of the maximum angle variance that we tolerate while at rest.
@@ -214,11 +210,10 @@
      *
      * @param isPowered True if the device is powered.
      * @param plugType The current plug type.
-     * @param batteryLevel The current battery level.
      * @return True if the device is determined to have just been docked on a wireless
      * charger, after suppressing spurious docking or undocking signals.
      */
-    public boolean update(boolean isPowered, int plugType, int batteryLevel) {
+    public boolean update(boolean isPowered, int plugType) {
         synchronized (mLock) {
             final boolean wasPoweredWirelessly = mPoweredWirelessly;
 
@@ -249,13 +244,9 @@
             }
 
             // Report that the device has been docked only if the device just started
-            // receiving power wirelessly, has a high enough battery level that we
-            // can be assured that charging was not delayed due to the battery previously
-            // having been full, and the device is not known to already be at rest
+            // receiving power wirelessly and the device is not known to already be at rest
             // on the wireless charger from earlier.
-            return mPoweredWirelessly && !wasPoweredWirelessly
-                    && batteryLevel < WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT
-                    && !mAtRest;
+            return mPoweredWirelessly && !wasPoweredWirelessly && !mAtRest;
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 93ca4dc..41ae48a 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -70,8 +70,8 @@
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
-import static com.android.server.wm.proto.AppTransitionProto.APP_TRANSITION_STATE;
-import static com.android.server.wm.proto.AppTransitionProto.LAST_USED_APP_TRANSITION;
+import static com.android.server.wm.AppTransitionProto.APP_TRANSITION_STATE;
+import static com.android.server.wm.AppTransitionProto.LAST_USED_APP_TRANSITION;
 
 import android.annotation.DrawableRes;
 import android.annotation.Nullable;
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 3cd3e8b..ad92f81 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -20,9 +20,9 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
-import static com.android.server.wm.proto.AppWindowThumbnailProto.HEIGHT;
-import static com.android.server.wm.proto.AppWindowThumbnailProto.SURFACE_ANIMATOR;
-import static com.android.server.wm.proto.AppWindowThumbnailProto.WIDTH;
+import static com.android.server.wm.AppWindowThumbnailProto.HEIGHT;
+import static com.android.server.wm.AppWindowThumbnailProto.SURFACE_ANIMATOR;
+import static com.android.server.wm.AppWindowThumbnailProto.WIDTH;
 
 import android.graphics.GraphicBuffer;
 import android.graphics.PixelFormat;
@@ -119,7 +119,7 @@
 
     /**
      * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
-     * com.android.server.wm.proto.AppWindowThumbnailProto}.
+     * com.android.server.wm.AppWindowThumbnailProto}.
      *
      * @param proto Stream to write the AppWindowThumbnail object to.
      * @param fieldId Field Id of the AppWindowThumbnail as defined in the parent message.
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index f8a4540..a76857e 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -51,29 +51,29 @@
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.logWithStack;
-import static com.android.server.wm.proto.AppWindowTokenProto.ALL_DRAWN;
-import static com.android.server.wm.proto.AppWindowTokenProto.APP_STOPPED;
-import static com.android.server.wm.proto.AppWindowTokenProto.CLIENT_HIDDEN;
-import static com.android.server.wm.proto.AppWindowTokenProto.DEFER_HIDING_CLIENT;
-import static com.android.server.wm.proto.AppWindowTokenProto.FILLS_PARENT;
-import static com.android.server.wm.proto.AppWindowTokenProto.FROZEN_BOUNDS;
-import static com.android.server.wm.proto.AppWindowTokenProto.HIDDEN_REQUESTED;
-import static com.android.server.wm.proto.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
-import static com.android.server.wm.proto.AppWindowTokenProto.IS_REALLY_ANIMATING;
-import static com.android.server.wm.proto.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
-import static com.android.server.wm.proto.AppWindowTokenProto.LAST_ALL_DRAWN;
-import static com.android.server.wm.proto.AppWindowTokenProto.LAST_SURFACE_SHOWING;
-import static com.android.server.wm.proto.AppWindowTokenProto.NAME;
-import static com.android.server.wm.proto.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
-import static com.android.server.wm.proto.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
-import static com.android.server.wm.proto.AppWindowTokenProto.REMOVED;
-import static com.android.server.wm.proto.AppWindowTokenProto.REPORTED_DRAWN;
-import static com.android.server.wm.proto.AppWindowTokenProto.REPORTED_VISIBLE;
-import static com.android.server.wm.proto.AppWindowTokenProto.STARTING_DISPLAYED;
-import static com.android.server.wm.proto.AppWindowTokenProto.STARTING_MOVED;
-import static com.android.server.wm.proto.AppWindowTokenProto.STARTING_WINDOW;
-import static com.android.server.wm.proto.AppWindowTokenProto.THUMBNAIL;
-import static com.android.server.wm.proto.AppWindowTokenProto.WINDOW_TOKEN;
+import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
+import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
+import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
+import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
+import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
+import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
+import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
+import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
+import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
+import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
+import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
+import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
+import static com.android.server.wm.AppWindowTokenProto.NAME;
+import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
+import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
+import static com.android.server.wm.AppWindowTokenProto.REMOVED;
+import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
+import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
+import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
+import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
+import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
+import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
+import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
 
 import android.annotation.CallSuper;
 import android.app.Activity;
@@ -1482,11 +1482,13 @@
 
     void layoutLetterbox(WindowState winHint) {
         final WindowState w = findMainWindow();
-        if (w != winHint && winHint != null && w != null) {
+        if (w == null || winHint != null && w != winHint) {
             return;
         }
-        final boolean needsLetterbox = w != null && w.isLetterboxedAppWindow()
-                && fillsParent() && w.hasDrawnLw();
+        final boolean surfaceReady = w.hasDrawnLw()  // Regular case
+                || w.mWinAnimator.mSurfaceDestroyDeferred  // The preserved surface is still ready.
+                || w.isDragResizeChanged();  // Waiting for relayoutWindow to call preserveSurface.
+        final boolean needsLetterbox = w.isLetterboxedAppWindow() && fillsParent() && surfaceReady;
         if (needsLetterbox) {
             if (mLetterbox == null) {
                 mLetterbox = new Letterbox(() -> makeChildSurface(null));
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 2c2389b..627c629 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -29,9 +29,9 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.activityTypeToString;
 import static android.app.WindowConfiguration.windowingModeToString;
-import static com.android.server.wm.proto.ConfigurationContainerProto.FULL_CONFIGURATION;
-import static com.android.server.wm.proto.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION;
-import static com.android.server.wm.proto.ConfigurationContainerProto.OVERRIDE_CONFIGURATION;
+import static com.android.server.wm.ConfigurationContainerProto.FULL_CONFIGURATION;
+import static com.android.server.wm.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION;
+import static com.android.server.wm.ConfigurationContainerProto.OVERRIDE_CONFIGURATION;
 
 import android.annotation.CallSuper;
 import android.app.WindowConfiguration;
@@ -470,7 +470,7 @@
 
     /**
      * Write to a protocol buffer output stream. Protocol buffer message definition is at
-     * {@link com.android.server.wm.proto.ConfigurationContainerProto}.
+     * {@link com.android.server.wm.ConfigurationContainerProto}.
      *
      * @param proto    Stream to write the ConfigurationContainer object to.
      * @param fieldId  Field Id of the ConfigurationContainer as defined in the parent
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 5c62987..d000bb6 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -16,10 +16,10 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.proto.AlphaAnimationSpecProto.DURATION;
-import static com.android.server.wm.proto.AlphaAnimationSpecProto.FROM;
-import static com.android.server.wm.proto.AlphaAnimationSpecProto.TO;
-import static com.android.server.wm.proto.AnimationSpecProto.ALPHA;
+import static com.android.server.wm.AlphaAnimationSpecProto.DURATION;
+import static com.android.server.wm.AlphaAnimationSpecProto.FROM;
+import static com.android.server.wm.AlphaAnimationSpecProto.TO;
+import static com.android.server.wm.AnimationSpecProto.ALPHA;
 
 import android.graphics.Rect;
 import android.util.proto.ProtoOutputStream;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e2e1690..2094755 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -101,19 +101,19 @@
 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
-import static com.android.server.wm.proto.DisplayProto.ABOVE_APP_WINDOWS;
-import static com.android.server.wm.proto.DisplayProto.BELOW_APP_WINDOWS;
-import static com.android.server.wm.proto.DisplayProto.DISPLAY_FRAMES;
-import static com.android.server.wm.proto.DisplayProto.DISPLAY_INFO;
-import static com.android.server.wm.proto.DisplayProto.DOCKED_STACK_DIVIDER_CONTROLLER;
-import static com.android.server.wm.proto.DisplayProto.DPI;
-import static com.android.server.wm.proto.DisplayProto.ID;
-import static com.android.server.wm.proto.DisplayProto.IME_WINDOWS;
-import static com.android.server.wm.proto.DisplayProto.PINNED_STACK_CONTROLLER;
-import static com.android.server.wm.proto.DisplayProto.ROTATION;
-import static com.android.server.wm.proto.DisplayProto.SCREEN_ROTATION_ANIMATION;
-import static com.android.server.wm.proto.DisplayProto.STACKS;
-import static com.android.server.wm.proto.DisplayProto.WINDOW_CONTAINER;
+import static com.android.server.wm.DisplayProto.ABOVE_APP_WINDOWS;
+import static com.android.server.wm.DisplayProto.BELOW_APP_WINDOWS;
+import static com.android.server.wm.DisplayProto.DISPLAY_FRAMES;
+import static com.android.server.wm.DisplayProto.DISPLAY_INFO;
+import static com.android.server.wm.DisplayProto.DOCKED_STACK_DIVIDER_CONTROLLER;
+import static com.android.server.wm.DisplayProto.DPI;
+import static com.android.server.wm.DisplayProto.ID;
+import static com.android.server.wm.DisplayProto.IME_WINDOWS;
+import static com.android.server.wm.DisplayProto.PINNED_STACK_CONTROLLER;
+import static com.android.server.wm.DisplayProto.ROTATION;
+import static com.android.server.wm.DisplayProto.SCREEN_ROTATION_ANIMATION;
+import static com.android.server.wm.DisplayProto.STACKS;
+import static com.android.server.wm.DisplayProto.WINDOW_CONTAINER;
 
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index 57693ac..dc6b491 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -19,7 +19,7 @@
 import static android.view.Surface.ROTATION_180;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
-import static com.android.server.wm.proto.DisplayFramesProto.STABLE_BOUNDS;
+import static com.android.server.wm.DisplayFramesProto.STABLE_BOUNDS;
 
 import android.annotation.NonNull;
 import android.graphics.Rect;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index b99e85f..5e2bb10 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -34,7 +34,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED;
 import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM;
-import static com.android.server.wm.proto.DockedStackDividerControllerProto.MINIMIZED_DOCK;
+import static com.android.server.wm.DockedStackDividerControllerProto.MINIMIZED_DOCK;
 
 import android.content.Context;
 import android.content.res.Configuration;
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
index 3f1fde9..529aacc 100644
--- a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -16,8 +16,8 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.proto.AnimationAdapterProto.LOCAL;
-import static com.android.server.wm.proto.LocalAnimationAdapterProto.ANIMATION_SPEC;
+import static com.android.server.wm.AnimationAdapterProto.LOCAL;
+import static com.android.server.wm.LocalAnimationAdapterProto.ANIMATION_SPEC;
 
 import android.os.SystemClock;
 import android.util.proto.ProtoOutputStream;
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 2293fb2..5f1916d 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -22,8 +22,8 @@
 
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.proto.PinnedStackControllerProto.DEFAULT_BOUNDS;
-import static com.android.server.wm.proto.PinnedStackControllerProto.MOVEMENT_BOUNDS;
+import static com.android.server.wm.PinnedStackControllerProto.DEFAULT_BOUNDS;
+import static com.android.server.wm.PinnedStackControllerProto.MOVEMENT_BOUNDS;
 
 import android.app.RemoteAction;
 import android.content.pm.ParceledListSlice;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 3e72a71..19d6691 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -26,8 +26,8 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING;
-import static com.android.server.wm.proto.RemoteAnimationAdapterWrapperProto.TARGET;
-import static com.android.server.wm.proto.AnimationAdapterProto.REMOTE;
+import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
+import static com.android.server.wm.AnimationAdapterProto.REMOTE;
 
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.WindowConfiguration;
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index d645110..d7f480b 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -19,8 +19,8 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.proto.AnimationAdapterProto.REMOTE;
-import static com.android.server.wm.proto.RemoteAnimationAdapterWrapperProto.TARGET;
+import static com.android.server.wm.AnimationAdapterProto.REMOTE;
+import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
 
 import android.graphics.Point;
 import android.graphics.Rect;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 32ae523..52d8177 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -84,9 +84,9 @@
 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
-import static com.android.server.wm.proto.RootWindowContainerProto.DISPLAYS;
-import static com.android.server.wm.proto.RootWindowContainerProto.WINDOWS;
-import static com.android.server.wm.proto.RootWindowContainerProto.WINDOW_CONTAINER;
+import static com.android.server.wm.RootWindowContainerProto.DISPLAYS;
+import static com.android.server.wm.RootWindowContainerProto.WINDOWS;
+import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
 
 /** Root {@link WindowContainer} for the device. */
 class RootWindowContainer extends WindowContainer<DisplayContent> {
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 235f63e..fa8a5c6 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -23,8 +23,8 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
 import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER;
-import static com.android.server.wm.proto.ScreenRotationAnimationProto.ANIMATION_RUNNING;
-import static com.android.server.wm.proto.ScreenRotationAnimationProto.STARTED;
+import static com.android.server.wm.ScreenRotationAnimationProto.ANIMATION_RUNNING;
+import static com.android.server.wm.ScreenRotationAnimationProto.STARTED;
 
 import android.content.Context;
 import android.graphics.Matrix;
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index f10ff8c..e5928b1 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -19,9 +19,9 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.proto.SurfaceAnimatorProto.ANIMATION_ADAPTER;
-import static com.android.server.wm.proto.SurfaceAnimatorProto.ANIMATION_START_DELAYED;
-import static com.android.server.wm.proto.SurfaceAnimatorProto.LEASH;
+import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_ADAPTER;
+import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_START_DELAYED;
+import static com.android.server.wm.SurfaceAnimatorProto.LEASH;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -310,7 +310,7 @@
 
     /**
      * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
-     * com.android.server.wm.proto.SurfaceAnimatorProto}.
+     * com.android.server.wm.SurfaceAnimatorProto}.
      *
      * @param proto Stream to write the SurfaceAnimator object to.
      * @param fieldId Field Id of the SurfaceAnimator as defined in the parent message.
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a403e6f2..e4722f9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -26,13 +26,13 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.proto.TaskProto.APP_WINDOW_TOKENS;
-import static com.android.server.wm.proto.TaskProto.BOUNDS;
-import static com.android.server.wm.proto.TaskProto.DEFER_REMOVAL;
-import static com.android.server.wm.proto.TaskProto.FILLS_PARENT;
-import static com.android.server.wm.proto.TaskProto.ID;
-import static com.android.server.wm.proto.TaskProto.TEMP_INSET_BOUNDS;
-import static com.android.server.wm.proto.TaskProto.WINDOW_CONTAINER;
+import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS;
+import static com.android.server.wm.TaskProto.BOUNDS;
+import static com.android.server.wm.TaskProto.DEFER_REMOVAL;
+import static com.android.server.wm.TaskProto.FILLS_PARENT;
+import static com.android.server.wm.TaskProto.ID;
+import static com.android.server.wm.TaskProto.TEMP_INSET_BOUNDS;
+import static com.android.server.wm.TaskProto.WINDOW_CONTAINER;
 
 import android.annotation.CallSuper;
 import android.app.ActivityManager.TaskDescription;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 460edec..900e2df 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -35,18 +35,18 @@
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.proto.StackProto.ADJUSTED_BOUNDS;
-import static com.android.server.wm.proto.StackProto.ADJUSTED_FOR_IME;
-import static com.android.server.wm.proto.StackProto.ADJUST_DIVIDER_AMOUNT;
-import static com.android.server.wm.proto.StackProto.ADJUST_IME_AMOUNT;
-import static com.android.server.wm.proto.StackProto.ANIMATION_BACKGROUND_SURFACE_IS_DIMMING;
-import static com.android.server.wm.proto.StackProto.BOUNDS;
-import static com.android.server.wm.proto.StackProto.DEFER_REMOVAL;
-import static com.android.server.wm.proto.StackProto.FILLS_PARENT;
-import static com.android.server.wm.proto.StackProto.ID;
-import static com.android.server.wm.proto.StackProto.MINIMIZE_AMOUNT;
-import static com.android.server.wm.proto.StackProto.TASKS;
-import static com.android.server.wm.proto.StackProto.WINDOW_CONTAINER;
+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;
+import static com.android.server.wm.StackProto.ADJUST_IME_AMOUNT;
+import static com.android.server.wm.StackProto.ANIMATION_BACKGROUND_SURFACE_IS_DIMMING;
+import static com.android.server.wm.StackProto.BOUNDS;
+import static com.android.server.wm.StackProto.DEFER_REMOVAL;
+import static com.android.server.wm.StackProto.FILLS_PARENT;
+import static com.android.server.wm.StackProto.ID;
+import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT;
+import static com.android.server.wm.StackProto.TASKS;
+import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
 
 import android.annotation.CallSuper;
 import android.content.res.Configuration;
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index a41eba8..7b7cb30 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -19,8 +19,8 @@
 import static com.android.server.wm.AnimationAdapter.STATUS_BAR_TRANSITION_DURATION;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
-import static com.android.server.wm.proto.AnimationSpecProto.WINDOW;
-import static com.android.server.wm.proto.WindowAnimationSpecProto.ANIMATION;
+import static com.android.server.wm.AnimationSpecProto.WINDOW;
+import static com.android.server.wm.WindowAnimationSpecProto.ANIMATION;
 
 import android.graphics.Point;
 import android.graphics.Rect;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 5ae4dc5..28fdaae 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -23,10 +23,10 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.proto.WindowContainerProto.CONFIGURATION_CONTAINER;
-import static com.android.server.wm.proto.WindowContainerProto.ORIENTATION;
-import static com.android.server.wm.proto.WindowContainerProto.SURFACE_ANIMATOR;
-import static com.android.server.wm.proto.WindowContainerProto.VISIBLE;
+import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
+import static com.android.server.wm.WindowContainerProto.ORIENTATION;
+import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
+import static com.android.server.wm.WindowContainerProto.VISIBLE;
 
 import android.annotation.CallSuper;
 import android.content.res.Configuration;
@@ -285,7 +285,14 @@
         }
 
         if (mSurfaceControl != null) {
-            getPendingTransaction().destroy(mSurfaceControl);
+            mPendingTransaction.destroy(mSurfaceControl);
+
+            // Merge to parent transaction to ensure the transactions on this WindowContainer are
+            // applied in native even if WindowContainer is removed.
+            if (mParent != null) {
+                mParent.getPendingTransaction().merge(mPendingTransaction);
+            }
+
             mSurfaceControl = null;
             scheduleAnimation();
         }
@@ -980,7 +987,7 @@
 
     /**
      * Write to a protocol buffer output stream. Protocol buffer message definition is at
-     * {@link com.android.server.wm.proto.WindowContainerProto}.
+     * {@link com.android.server.wm.WindowContainerProto}.
      *
      * @param proto     Stream to write the WindowContainer object to.
      * @param fieldId   Field Id of the WindowContainer as defined in the parent message.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5f0769d..a22bb00 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -97,15 +97,15 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.proto.WindowManagerServiceDumpProto.APP_TRANSITION;
-import static com.android.server.wm.proto.WindowManagerServiceDumpProto.DISPLAY_FROZEN;
-import static com.android.server.wm.proto.WindowManagerServiceDumpProto.FOCUSED_APP;
-import static com.android.server.wm.proto.WindowManagerServiceDumpProto.FOCUSED_WINDOW;
-import static com.android.server.wm.proto.WindowManagerServiceDumpProto.INPUT_METHOD_WINDOW;
-import static com.android.server.wm.proto.WindowManagerServiceDumpProto.LAST_ORIENTATION;
-import static com.android.server.wm.proto.WindowManagerServiceDumpProto.POLICY;
-import static com.android.server.wm.proto.WindowManagerServiceDumpProto.ROOT_WINDOW_CONTAINER;
-import static com.android.server.wm.proto.WindowManagerServiceDumpProto.ROTATION;
+import static com.android.server.wm.WindowManagerServiceDumpProto.APP_TRANSITION;
+import static com.android.server.wm.WindowManagerServiceDumpProto.DISPLAY_FROZEN;
+import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_APP;
+import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_WINDOW;
+import static com.android.server.wm.WindowManagerServiceDumpProto.INPUT_METHOD_WINDOW;
+import static com.android.server.wm.WindowManagerServiceDumpProto.LAST_ORIENTATION;
+import static com.android.server.wm.WindowManagerServiceDumpProto.POLICY;
+import static com.android.server.wm.WindowManagerServiceDumpProto.ROOT_WINDOW_CONTAINER;
+import static com.android.server.wm.WindowManagerServiceDumpProto.ROTATION;
 
 import android.Manifest;
 import android.Manifest.permission;
@@ -6179,7 +6179,7 @@
 
     /**
      * Write to a protocol buffer output stream. Protocol buffer message definition is at
-     * {@link com.android.server.wm.proto.WindowManagerServiceDumpProto}.
+     * {@link com.android.server.wm.WindowManagerServiceDumpProto}.
      *
      * @param proto     Stream to write the WindowContainer object to.
      * @param trim      If true, reduce the amount of data written.
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index eebf2fd..993556f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -107,50 +107,50 @@
 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
-import static com.android.server.wm.proto.IdentifierProto.HASH_CODE;
-import static com.android.server.wm.proto.IdentifierProto.TITLE;
-import static com.android.server.wm.proto.IdentifierProto.USER_ID;
-import static com.android.server.wm.proto.AnimationSpecProto.MOVE;
-import static com.android.server.wm.proto.MoveAnimationSpecProto.DURATION;
-import static com.android.server.wm.proto.MoveAnimationSpecProto.FROM;
-import static com.android.server.wm.proto.MoveAnimationSpecProto.TO;
-import static com.android.server.wm.proto.WindowStateProto.ANIMATING_EXIT;
-import static com.android.server.wm.proto.WindowStateProto.ANIMATOR;
-import static com.android.server.wm.proto.WindowStateProto.ATTRIBUTES;
-import static com.android.server.wm.proto.WindowStateProto.CHILD_WINDOWS;
-import static com.android.server.wm.proto.WindowStateProto.CONTAINING_FRAME;
-import static com.android.server.wm.proto.WindowStateProto.CONTENT_FRAME;
-import static com.android.server.wm.proto.WindowStateProto.CONTENT_INSETS;
-import static com.android.server.wm.proto.WindowStateProto.CUTOUT;
-import static com.android.server.wm.proto.WindowStateProto.DECOR_FRAME;
-import static com.android.server.wm.proto.WindowStateProto.DESTROYING;
-import static com.android.server.wm.proto.WindowStateProto.DISPLAY_FRAME;
-import static com.android.server.wm.proto.WindowStateProto.DISPLAY_ID;
-import static com.android.server.wm.proto.WindowStateProto.FRAME;
-import static com.android.server.wm.proto.WindowStateProto.GIVEN_CONTENT_INSETS;
-import static com.android.server.wm.proto.WindowStateProto.HAS_SURFACE;
-import static com.android.server.wm.proto.WindowStateProto.IDENTIFIER;
-import static com.android.server.wm.proto.WindowStateProto.IS_ON_SCREEN;
-import static com.android.server.wm.proto.WindowStateProto.IS_READY_FOR_DISPLAY;
-import static com.android.server.wm.proto.WindowStateProto.IS_VISIBLE;
-import static com.android.server.wm.proto.WindowStateProto.OUTSETS;
-import static com.android.server.wm.proto.WindowStateProto.OUTSET_FRAME;
-import static com.android.server.wm.proto.WindowStateProto.OVERSCAN_FRAME;
-import static com.android.server.wm.proto.WindowStateProto.OVERSCAN_INSETS;
-import static com.android.server.wm.proto.WindowStateProto.PARENT_FRAME;
-import static com.android.server.wm.proto.WindowStateProto.REMOVED;
-import static com.android.server.wm.proto.WindowStateProto.REMOVE_ON_EXIT;
-import static com.android.server.wm.proto.WindowStateProto.REQUESTED_HEIGHT;
-import static com.android.server.wm.proto.WindowStateProto.REQUESTED_WIDTH;
-import static com.android.server.wm.proto.WindowStateProto.STABLE_INSETS;
-import static com.android.server.wm.proto.WindowStateProto.STACK_ID;
-import static com.android.server.wm.proto.WindowStateProto.SURFACE_INSETS;
-import static com.android.server.wm.proto.WindowStateProto.SURFACE_POSITION;
-import static com.android.server.wm.proto.WindowStateProto.SYSTEM_UI_VISIBILITY;
-import static com.android.server.wm.proto.WindowStateProto.VIEW_VISIBILITY;
-import static com.android.server.wm.proto.WindowStateProto.VISIBLE_FRAME;
-import static com.android.server.wm.proto.WindowStateProto.VISIBLE_INSETS;
-import static com.android.server.wm.proto.WindowStateProto.WINDOW_CONTAINER;
+import static com.android.server.wm.IdentifierProto.HASH_CODE;
+import static com.android.server.wm.IdentifierProto.TITLE;
+import static com.android.server.wm.IdentifierProto.USER_ID;
+import static com.android.server.wm.AnimationSpecProto.MOVE;
+import static com.android.server.wm.MoveAnimationSpecProto.DURATION;
+import static com.android.server.wm.MoveAnimationSpecProto.FROM;
+import static com.android.server.wm.MoveAnimationSpecProto.TO;
+import static com.android.server.wm.WindowStateProto.ANIMATING_EXIT;
+import static com.android.server.wm.WindowStateProto.ANIMATOR;
+import static com.android.server.wm.WindowStateProto.ATTRIBUTES;
+import static com.android.server.wm.WindowStateProto.CHILD_WINDOWS;
+import static com.android.server.wm.WindowStateProto.CONTAINING_FRAME;
+import static com.android.server.wm.WindowStateProto.CONTENT_FRAME;
+import static com.android.server.wm.WindowStateProto.CONTENT_INSETS;
+import static com.android.server.wm.WindowStateProto.CUTOUT;
+import static com.android.server.wm.WindowStateProto.DECOR_FRAME;
+import static com.android.server.wm.WindowStateProto.DESTROYING;
+import static com.android.server.wm.WindowStateProto.DISPLAY_FRAME;
+import static com.android.server.wm.WindowStateProto.DISPLAY_ID;
+import static com.android.server.wm.WindowStateProto.FRAME;
+import static com.android.server.wm.WindowStateProto.GIVEN_CONTENT_INSETS;
+import static com.android.server.wm.WindowStateProto.HAS_SURFACE;
+import static com.android.server.wm.WindowStateProto.IDENTIFIER;
+import static com.android.server.wm.WindowStateProto.IS_ON_SCREEN;
+import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
+import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
+import static com.android.server.wm.WindowStateProto.OUTSETS;
+import static com.android.server.wm.WindowStateProto.OUTSET_FRAME;
+import static com.android.server.wm.WindowStateProto.OVERSCAN_FRAME;
+import static com.android.server.wm.WindowStateProto.OVERSCAN_INSETS;
+import static com.android.server.wm.WindowStateProto.PARENT_FRAME;
+import static com.android.server.wm.WindowStateProto.REMOVED;
+import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT;
+import static com.android.server.wm.WindowStateProto.REQUESTED_HEIGHT;
+import static com.android.server.wm.WindowStateProto.REQUESTED_WIDTH;
+import static com.android.server.wm.WindowStateProto.STABLE_INSETS;
+import static com.android.server.wm.WindowStateProto.STACK_ID;
+import static com.android.server.wm.WindowStateProto.SURFACE_INSETS;
+import static com.android.server.wm.WindowStateProto.SURFACE_POSITION;
+import static com.android.server.wm.WindowStateProto.SYSTEM_UI_VISIBILITY;
+import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
+import static com.android.server.wm.WindowStateProto.VISIBLE_FRAME;
+import static com.android.server.wm.WindowStateProto.VISIBLE_INSETS;
+import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
 
 import android.annotation.CallSuper;
 import android.app.AppOpsManager;
@@ -859,10 +859,12 @@
         // If the task has temp inset bounds set, we have to make sure all its windows uses
         // the temp inset frame. Otherwise different display frames get applied to the main
         // window and the child window, making them misaligned.
-        if (inFullscreenContainer || isLetterboxedAppWindow()) {
-            mInsetFrame.setEmpty();
-        } else if (task != null && isInMultiWindowMode()) {
+        // Otherwise we need to clear the inset frame, to avoid using a stale frame after leaving
+        // multi window mode.
+        if (task != null && isInMultiWindowMode()) {
             task.getTempInsetBounds(mInsetFrame);
+        } else {
+            mInsetFrame.setEmpty();
         }
 
         // Denotes the actual frame used to calculate the insets and to perform the layout. When
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0c2b075..e92d460 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -41,10 +41,10 @@
 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
 import static com.android.server.wm.WindowManagerService.logWithStack;
 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
-import static com.android.server.wm.proto.WindowStateAnimatorProto.DRAW_STATE;
-import static com.android.server.wm.proto.WindowStateAnimatorProto.LAST_CLIP_RECT;
-import static com.android.server.wm.proto.WindowStateAnimatorProto.SURFACE;
-import static com.android.server.wm.proto.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
+import static com.android.server.wm.WindowStateAnimatorProto.DRAW_STATE;
+import static com.android.server.wm.WindowStateAnimatorProto.LAST_CLIP_RECT;
+import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
+import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
 
 import android.content.Context;
 import android.graphics.Matrix;
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index f6c0a54..66c8cca 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -25,8 +25,8 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.proto.WindowSurfaceControllerProto.LAYER;
-import static com.android.server.wm.proto.WindowSurfaceControllerProto.SHOWN;
+import static com.android.server.wm.WindowSurfaceControllerProto.LAYER;
+import static com.android.server.wm.WindowSurfaceControllerProto.SHOWN;
 
 import android.graphics.Point;
 import android.graphics.PointF;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 172efdc..f727296 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -23,12 +23,12 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import static com.android.server.wm.proto.WindowTokenProto.HASH_CODE;
-import static com.android.server.wm.proto.WindowTokenProto.HIDDEN;
-import static com.android.server.wm.proto.WindowTokenProto.PAUSED;
-import static com.android.server.wm.proto.WindowTokenProto.WAITING_TO_SHOW;
-import static com.android.server.wm.proto.WindowTokenProto.WINDOWS;
-import static com.android.server.wm.proto.WindowTokenProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowTokenProto.HASH_CODE;
+import static com.android.server.wm.WindowTokenProto.HIDDEN;
+import static com.android.server.wm.WindowTokenProto.PAUSED;
+import static com.android.server.wm.WindowTokenProto.WAITING_TO_SHOW;
+import static com.android.server.wm.WindowTokenProto.WINDOWS;
+import static com.android.server.wm.WindowTokenProto.WINDOW_CONTAINER;
 
 import android.annotation.CallSuper;
 import android.os.Debug;
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index a299781..8fa56bb 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -17,13 +17,13 @@
 package com.android.server.wm;
 
 import static android.os.Build.IS_USER;
-import static com.android.server.wm.proto.WindowManagerTraceFileProto.ENTRY;
-import static com.android.server.wm.proto.WindowManagerTraceFileProto.MAGIC_NUMBER;
-import static com.android.server.wm.proto.WindowManagerTraceFileProto.MAGIC_NUMBER_H;
-import static com.android.server.wm.proto.WindowManagerTraceFileProto.MAGIC_NUMBER_L;
-import static com.android.server.wm.proto.WindowManagerTraceProto.ELAPSED_REALTIME_NANOS;
-import static com.android.server.wm.proto.WindowManagerTraceProto.WHERE;
-import static com.android.server.wm.proto.WindowManagerTraceProto.WINDOW_MANAGER_SERVICE;
+import static com.android.server.wm.WindowManagerTraceFileProto.ENTRY;
+import static com.android.server.wm.WindowManagerTraceFileProto.MAGIC_NUMBER;
+import static com.android.server.wm.WindowManagerTraceFileProto.MAGIC_NUMBER_H;
+import static com.android.server.wm.WindowManagerTraceFileProto.MAGIC_NUMBER_L;
+import static com.android.server.wm.WindowManagerTraceProto.ELAPSED_REALTIME_NANOS;
+import static com.android.server.wm.WindowManagerTraceProto.WHERE;
+import static com.android.server.wm.WindowManagerTraceProto.WINDOW_MANAGER_SERVICE;
 
 import android.content.Context;
 import android.os.ShellCommand;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6a9b862..884f348 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -107,7 +107,9 @@
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.app.admin.SystemUpdateInfo;
 import android.app.admin.SystemUpdatePolicy;
+import android.app.backup.BackupManager;
 import android.app.backup.IBackupManager;
+import android.app.backup.ISelectBackupTransportCallback;
 import android.app.trust.TrustManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.BroadcastReceiver;
@@ -252,6 +254,7 @@
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Function;
@@ -11997,20 +12000,32 @@
     }
 
     @Override
-    public void setMandatoryBackupTransport(
-            ComponentName admin, ComponentName backupTransportComponent) {
+    public boolean setMandatoryBackupTransport(
+            ComponentName admin,
+            ComponentName backupTransportComponent) {
         if (!mHasFeature) {
-            return;
+            return false;
         }
         Preconditions.checkNotNull(admin);
         synchronized (this) {
-            ActiveAdmin activeAdmin =
-                    getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
-            if (!Objects.equals(backupTransportComponent, activeAdmin.mandatoryBackupTransport)) {
-                activeAdmin.mandatoryBackupTransport = backupTransportComponent;
-                saveSettingsLocked(UserHandle.USER_SYSTEM);
-            }
+            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
         }
+
+        final int callingUid = mInjector.binderGetCallingUid();
+        final AtomicBoolean success = new AtomicBoolean(false);
+        final CountDownLatch countDownLatch = new CountDownLatch(1);
+        final ISelectBackupTransportCallback selectBackupTransportCallbackInternal =
+                new ISelectBackupTransportCallback.Stub() {
+                    public void onSuccess(String transportName) {
+                        saveMandatoryBackupTransport(admin, callingUid, backupTransportComponent);
+                        success.set(true);
+                        countDownLatch.countDown();
+                    }
+
+                    public void onFailure(int reason) {
+                        countDownLatch.countDown();
+                    }
+                };
         final long identity = mInjector.binderClearCallingIdentity();
         try {
             IBackupManager ibm = mInjector.getIBackupManager();
@@ -12018,14 +12033,39 @@
                 if (!ibm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
                     ibm.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
                 }
-                ibm.selectBackupTransportAsync(backupTransportComponent, null);
-                ibm.setBackupEnabled(true);
+                ibm.selectBackupTransportAsync(
+                        backupTransportComponent, selectBackupTransportCallbackInternal);
+                countDownLatch.await();
+                if (success.get()) {
+                    ibm.setBackupEnabled(true);
+                }
+            } else if (backupTransportComponent == null) {
+                saveMandatoryBackupTransport(admin, callingUid, backupTransportComponent);
+                success.set(true);
             }
         } catch (RemoteException e) {
             throw new IllegalStateException("Failed to set mandatory backup transport.", e);
+        } catch (InterruptedException e) {
+            throw new IllegalStateException("Failed to set mandatory backup transport.", e);
         } finally {
             mInjector.binderRestoreCallingIdentity(identity);
         }
+        return success.get();
+    }
+
+    synchronized private void saveMandatoryBackupTransport(
+            ComponentName admin, int callingUid, ComponentName backupTransportComponent) {
+        ActiveAdmin activeAdmin =
+                getActiveAdminWithPolicyForUidLocked(
+                        admin,
+                        DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
+                        callingUid);
+        if (!Objects.equals(backupTransportComponent,
+                activeAdmin.mandatoryBackupTransport)) {
+            activeAdmin.mandatoryBackupTransport =
+                    backupTransportComponent;
+            saveSettingsLocked(UserHandle.USER_SYSTEM);
+        }
     }
 
     @Override
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index d165a45..6f50ee2 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -705,6 +705,11 @@
             mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
             traceEnd();
         }
+
+        // Tracks cpu time spent in binder calls
+        traceBeginAndSlog("StartBinderCallsStatsService");
+        BinderCallsStatsService.start();
+        traceEnd();
     }
 
     /**
diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
index d0398ad..f603a09 100644
--- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
@@ -148,22 +148,16 @@
         Looper backupLooper = startBackupThreadAndGetLooper();
         mShadowBackupLooper = shadowOf(backupLooper);
         mBackupHandler = new BackupHandler(mBackupManagerService, backupLooper);
-        Handler mainHandler = new Handler(Looper.getMainLooper());
 
         mBackupManager = spy(FakeIBackupManager.class);
 
-        BackupAgentTimeoutParameters agentTimeoutParameters =
-                new BackupAgentTimeoutParameters(mainHandler, application.getContentResolver());
-        agentTimeoutParameters.start();
-
         setUpBackupManagerServiceBasics(
                 mBackupManagerService,
                 application,
                 mTransportManager,
                 packageManager,
                 mBackupHandler,
-                mWakeLock,
-                agentTimeoutParameters);
+                mWakeLock);
         when(mBackupManagerService.getBaseStateDir()).thenReturn(mBaseStateDir);
         when(mBackupManagerService.getDataDir()).thenReturn(dataDir);
         when(mBackupManagerService.getBackupManagerBinder()).thenReturn(mBackupManager);
diff --git a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
index 869c50b..03792b1 100644
--- a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
+++ b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -41,14 +41,12 @@
 import android.app.backup.RestoreSet;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
-import android.os.Handler;
 import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.EventLogTags;
-import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.TransportManager;
 import com.android.server.backup.internal.BackupHandler;
@@ -117,15 +115,6 @@
 
         Looper backupLooper = startBackupThreadAndGetLooper();
         mShadowBackupLooper = shadowOf(backupLooper);
-
-        Handler mainHandler = new Handler(Looper.getMainLooper());
-        BackupAgentTimeoutParameters agentTimeoutParameters =
-                new BackupAgentTimeoutParameters(mainHandler, application.getContentResolver());
-        agentTimeoutParameters.start();
-
-        // We need to mock BMS timeout parameters before initializing the BackupHandler since
-        // the constructor of BackupHandler relies on the timeout parameters.
-        when(mBackupManagerService.getAgentTimeoutParameters()).thenReturn(agentTimeoutParameters);
         BackupHandler backupHandler = new BackupHandler(mBackupManagerService, backupLooper);
 
         mWakeLock = createBackupWakeLock(application);
@@ -136,8 +125,7 @@
                 mTransportManager,
                 application.getPackageManager(),
                 backupHandler,
-                mWakeLock,
-                agentTimeoutParameters);
+                mWakeLock);
         when(mBackupManagerService.getPendingRestores()).thenReturn(new ArrayDeque<>());
     }
 
diff --git a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
index 5a886e3..c210fde 100644
--- a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
@@ -28,7 +28,6 @@
 import android.os.PowerManager;
 import android.util.SparseArray;
 
-import com.android.server.backup.BackupAgentTimeoutParameters;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.TransportManager;
 import com.android.server.backup.internal.BackupHandler;
@@ -44,8 +43,7 @@
             TransportManager transportManager,
             PackageManager packageManager,
             BackupHandler backupHandler,
-            PowerManager.WakeLock wakeLock,
-            BackupAgentTimeoutParameters agentTimeoutParameters) {
+            PowerManager.WakeLock wakeLock) {
         when(backupManagerService.getContext()).thenReturn(context);
         when(backupManagerService.getTransportManager()).thenReturn(transportManager);
         when(backupManagerService.getPackageManager()).thenReturn(packageManager);
@@ -55,7 +53,6 @@
         when(backupManagerService.getCurrentOperations()).thenReturn(new SparseArray<>());
         when(backupManagerService.getActivityManager()).thenReturn(mock(IActivityManager.class));
         when(backupManagerService.getWakelock()).thenReturn(wakeLock);
-        when(backupManagerService.getAgentTimeoutParameters()).thenReturn(agentTimeoutParameters);
     }
 
     public static PowerManager.WakeLock createBackupWakeLock(Application application) {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 8721d9c..b452ea5 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -22,6 +22,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -33,18 +34,27 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.ArgumentMatchers.any;
+
 import android.app.ActivityManager;
 import android.app.WaitResult;
 import android.content.ComponentName;
+import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.util.SparseIntArray;
 
 import org.junit.runner.RunWith;
 import org.junit.Before;
 import org.junit.Test;
 
+import org.mockito.invocation.InvocationOnMock;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -238,4 +248,21 @@
         verify(stack, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked(
                 null /* target */, null /* targetOptions */);
     }
+
+    @Test
+    public void testTopRunningActivityLockedWithNonExistentDisplay() throws Exception {
+        // Create display that ActivityManagerService does not know about
+        final int unknownDisplayId = 100;
+
+        doAnswer((InvocationOnMock invocationOnMock) -> {
+            final SparseIntArray displayIds = invocationOnMock.<SparseIntArray>getArgument(0);
+            displayIds.put(0, unknownDisplayId);
+            return null;
+        }).when(mSupervisor.mWindowManager).getDisplaysInFocusOrder(any());
+
+        mSupervisor.mFocusedStack = mock(ActivityStack.class);
+
+        // Supervisor should skip over the non-existent display.
+        assertEquals(null, mSupervisor.topRunningActivityLocked());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index d2fb1ca..43490d3 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -57,6 +57,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.PasswordMetrics;
+import android.app.backup.ISelectBackupTransportCallback;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -2264,6 +2265,21 @@
         assertEquals(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE,
                 intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
 
+        // Make the backup transport selection succeed
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                ISelectBackupTransportCallback callback =
+                    (ISelectBackupTransportCallback) invocation.getArguments()[1];
+                if (callback != null) {
+                    callback.onSuccess("");
+                }
+                return null;
+            }
+        }).when(getServices().ibackupManager).selectBackupTransportAsync(
+                any(ComponentName.class), any(ISelectBackupTransportCallback.class));
+
+
         // Backups are not mandatory
         intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_MANDATORY_BACKUPS);
         assertNull(intent);
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index b4f8474..92cc537 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -30,6 +30,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.database.ContentObserver;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.display.BrightnessChangeEvent;
@@ -101,20 +102,24 @@
         assertNull(mInjector.mSensorListener);
         assertNotNull(mInjector.mBroadcastReceiver);
         assertTrue(mInjector.mIdleScheduled);
-        Intent onIntent = new Intent();
-        onIntent.setAction(Intent.ACTION_SCREEN_ON);
-        mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
-                onIntent);
+        mInjector.sendScreenChange(/*screen on */ true);
         assertNotNull(mInjector.mSensorListener);
 
-        Intent offIntent = new Intent();
-        offIntent.setAction(Intent.ACTION_SCREEN_OFF);
-        mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
-                offIntent);
+        mInjector.sendScreenChange(/*screen on */ false);
         assertNull(mInjector.mSensorListener);
 
-        mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
-                onIntent);
+        // Turn screen on while brightness mode is manual
+        mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ false);
+        mInjector.sendScreenChange(/*screen on */ true);
+        assertNull(mInjector.mSensorListener);
+
+        // Set brightness mode to automatic while screen is off.
+        mInjector.sendScreenChange(/*screen on */ false);
+        mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ true);
+        assertNull(mInjector.mSensorListener);
+
+        // Turn on screen while brightness mode is automatic.
+        mInjector.sendScreenChange(/*screen on */ true);
         assertNotNull(mInjector.mSensorListener);
 
         mTracker.stop();
@@ -124,6 +129,37 @@
     }
 
     @Test
+    public void testAdaptiveOnOff() {
+        mInjector.mInteractive = true;
+        mInjector.mIsBrightnessModeAutomatic = false;
+        startTracker(mTracker);
+        assertNull(mInjector.mSensorListener);
+        assertNotNull(mInjector.mBroadcastReceiver);
+        assertNotNull(mInjector.mContentObserver);
+        assertTrue(mInjector.mIdleScheduled);
+
+        mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
+        assertNotNull(mInjector.mSensorListener);
+
+        SensorEventListener listener = mInjector.mSensorListener;
+        mInjector.mSensorListener = null;
+        // Duplicate notification
+        mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
+        // Sensor shouldn't have been registered as it was already registered.
+        assertNull(mInjector.mSensorListener);
+        mInjector.mSensorListener = listener;
+
+        mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ false);
+        assertNull(mInjector.mSensorListener);
+
+        mTracker.stop();
+        assertNull(mInjector.mSensorListener);
+        assertNull(mInjector.mBroadcastReceiver);
+        assertNull(mInjector.mContentObserver);
+        assertFalse(mInjector.mIdleScheduled);
+    }
+
+    @Test
     public void testBrightnessEvent() {
         final int brightness = 20;
 
@@ -618,16 +654,39 @@
         boolean mIdleScheduled;
         boolean mInteractive = true;
         int[] mProfiles;
+        ContentObserver mContentObserver;
+        boolean mIsBrightnessModeAutomatic = true;
 
         public TestInjector(Handler handler) {
             mHandler = handler;
         }
 
-        public void incrementTime(long timeMillis) {
+        void incrementTime(long timeMillis) {
             mCurrentTimeMillis += timeMillis;
             mElapsedRealtimeNanos += TimeUnit.MILLISECONDS.toNanos(timeMillis);
         }
 
+        void setBrightnessMode(boolean isBrightnessModeAutomatic) {
+          mIsBrightnessModeAutomatic = isBrightnessModeAutomatic;
+          mContentObserver.dispatchChange(false, null);
+          waitForHandler();
+        }
+
+        void sendScreenChange(boolean screenOn) {
+            mInteractive = screenOn;
+            Intent intent = new Intent();
+            intent.setAction(screenOn ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF);
+            mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(), intent);
+            waitForHandler();
+        }
+
+        void waitForHandler() {
+            Idle idle = new Idle();
+            mHandler.getLooper().getQueue().addIdleHandler(idle);
+            mHandler.post(() -> {});
+            idle.waitForIdle();
+        }
+
         @Override
         public void registerSensorListener(Context context,
                 SensorEventListener sensorListener, Handler handler) {
@@ -641,6 +700,18 @@
         }
 
         @Override
+        public void registerBrightnessModeObserver(ContentResolver resolver,
+                ContentObserver settingsObserver) {
+            mContentObserver = settingsObserver;
+        }
+
+        @Override
+        public void unregisterBrightnessModeObserver(Context context,
+                ContentObserver settingsObserver) {
+            mContentObserver = null;
+        }
+
+        @Override
         public void registerReceiver(Context context,
                 BroadcastReceiver shutdownReceiver, IntentFilter shutdownFilter) {
             mBroadcastReceiver = shutdownReceiver;
@@ -658,11 +729,9 @@
             return mHandler;
         }
 
-        public void waitForHandler() {
-            Idle idle = new Idle();
-            mHandler.getLooper().getQueue().addIdleHandler(idle);
-            mHandler.post(() -> {});
-            idle.waitForIdle();
+        @Override
+        public boolean isBrightnessModeAutomatic(ContentResolver resolver) {
+            return mIsBrightnessModeAutomatic;
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 69796b3..25747b8 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -296,7 +296,6 @@
                 keyDerivationParams.getSalt(),
                 TEST_CREDENTIAL);
         Long counterId = mRecoverableKeyStoreDb.getCounterId(TEST_USER_ID, TEST_RECOVERY_AGENT_UID);
-        counterId = 1L; // TODO: use value from the database.
         assertThat(counterId).isNotNull();
         byte[] recoveryKey = decryptThmEncryptedKey(
                 lockScreenHash,
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
index a3ade1e..5085254 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
@@ -36,7 +36,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.Preconditions;
-import com.android.server.wm.proto.WindowManagerTraceProto;
+import com.android.server.wm.WindowManagerTraceProto;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
index c4a688b..0f2e56b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
@@ -367,6 +367,28 @@
     }
 
     @Test
+    public void testActionsMoreOptionsThanChoices() {
+        PendingIntent intent1 = mock(PendingIntent.class);
+        PendingIntent intent2 = mock(PendingIntent.class);
+        Icon icon = mock(Icon.class);
+
+        Notification n1 = new Notification.Builder(mContext, "test")
+                .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent1).build())
+                .addAction(new Notification.Action.Builder(icon, "TEXT 2", intent1)
+                        .addRemoteInput(new RemoteInput.Builder("a")
+                                .setChoices(new CharSequence[] {"i", "m"})
+                                .build())
+                        .build())
+                .build();
+        Notification n2 = new Notification.Builder(mContext, "test")
+                .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent2).build())
+                .addAction(new Notification.Action.Builder(icon, "TEXT 2", intent1).build())
+                .build();
+
+        assertTrue(Notification.areActionsVisiblyDifferent(n1, n2));
+    }
+
+    @Test
     public void testActionsDifferentRemoteInputs() {
         PendingIntent intent = mock(PendingIntent.class);
         Icon icon = mock(Icon.class);
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 73243d2..1c0e260 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -881,7 +881,7 @@
          */
         @IntDef(prefix = { "HANDOVER_" },
                 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
-                HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERG_CALL,
+                HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
                 HANDOVER_FAILURE_UNKNOWN})
         @Retention(RetentionPolicy.SOURCE)
         public @interface HandoverFailureErrors {}
@@ -939,7 +939,7 @@
          * For more information on call handovers, see
          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4;
+        public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
 
         /**
          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index eebe2a1..c79eec0 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2227,7 +2227,9 @@
     /**
      * Gets the configuration values for a particular subscription, which is associated with a
      * specific SIM card. If an invalid subId is used, the returned config will contain default
-     * values.
+     * values. After using this method to get the configuration bundle,
+     * {@link #isConfigForIdentifiedCarrier(PersistableBundle)} should be called to confirm whether
+     * any carrier specific configuration has been applied.
      *
      * <p>Requires Permission:
      * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -2254,7 +2256,9 @@
     }
 
     /**
-     * Gets the configuration values for the default subscription.
+     * Gets the configuration values for the default subscription. After using this method to get
+     * the configuration bundle, {@link #isConfigForIdentifiedCarrier(PersistableBundle)} should be
+     * called to confirm whether any carrier specific configuration has been applied.
      *
      * <p>Requires Permission:
      * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -2283,6 +2287,9 @@
      * <p>
      * After using {@link #getConfig()} or {@link #getConfigForSubId(int)} an app should always
      * use this method to confirm whether any carrier specific configuration has been applied.
+     * Especially when an app misses the broadcast {@link #ACTION_CARRIER_CONFIG_CHANGED} but it
+     * still needs to get the current configuration, it must use this method to verify whether the
+     * configuration is default or carrier overridden.
      * </p>
      *
      * @param bundle the configuration bundle to be checked.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0b15191..c5386ef 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -111,6 +111,13 @@
             BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY;
 
     /**
+     * The process name of the Phone app as well as many other apps that use this process name, such
+     * as settings and vendor components.
+     * @hide
+     */
+    public static final String PHONE_PROCESS_NAME = "com.android.phone";
+
+    /**
      * The allowed states of Wi-Fi calling.
      *
      * @hide
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index c073d1a..aaf1a1cf8 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -139,34 +139,44 @@
 
         @Override
         public int queryCapabilityStatus() throws RemoteException {
-            return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+            synchronized (mLock) {
+                return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+            }
         }
 
         @Override
         public void addCapabilityCallback(IImsCapabilityCallback c) {
+            // no need to lock, structure already handles multithreading.
             MmTelFeature.this.addCapabilityCallback(c);
         }
 
         @Override
         public void removeCapabilityCallback(IImsCapabilityCallback c) {
+            // no need to lock, structure already handles multithreading.
             MmTelFeature.this.removeCapabilityCallback(c);
         }
 
         @Override
         public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
                 IImsCapabilityCallback c) throws RemoteException {
-            MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+            synchronized (mLock) {
+                MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+            }
         }
 
         @Override
         public void queryCapabilityConfiguration(int capability, int radioTech,
                 IImsCapabilityCallback c) {
-            queryCapabilityConfigurationInternal(capability, radioTech, c);
+            synchronized (mLock) {
+                queryCapabilityConfigurationInternal(capability, radioTech, c);
+            }
         }
 
         @Override
         public void setSmsListener(IImsSmsListener l) throws RemoteException {
-            MmTelFeature.this.setSmsListener(l);
+            synchronized (mLock) {
+                MmTelFeature.this.setSmsListener(l);
+            }
         }
 
         @Override
diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java
index cc3366f..0ca20de 100644
--- a/tests/net/java/android/net/IpSecManagerTest.java
+++ b/tests/net/java/android/net/IpSecManagerTest.java
@@ -50,13 +50,18 @@
 
     private static final int TEST_UDP_ENCAP_PORT = 34567;
     private static final int DROID_SPI = 0xD1201D;
+    private static final int DUMMY_RESOURCE_ID = 0x1234;
 
     private static final InetAddress GOOGLE_DNS_4;
+    private static final String VTI_INTF_NAME = "ipsec_test";
+    private static final InetAddress VTI_LOCAL_ADDRESS;
+    private static final LinkAddress VTI_INNER_ADDRESS = new LinkAddress("10.0.1.1/24");
 
     static {
         try {
             // Google Public DNS Addresses;
             GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
+            VTI_LOCAL_ADDRESS = InetAddress.getByName("8.8.4.4");
         } catch (UnknownHostException e) {
             throw new RuntimeException("Could not resolve DNS Addresses", e);
         }
@@ -77,9 +82,8 @@
      */
     @Test
     public void testAllocSpi() throws Exception {
-        int resourceId = 1;
         IpSecSpiResponse spiResp =
-                new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
+                new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
         when(mMockIpSecService.allocateSecurityParameterIndex(
                         eq(GOOGLE_DNS_4.getHostAddress()),
                         eq(DROID_SPI),
@@ -92,14 +96,13 @@
 
         droidSpi.close();
 
-        verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId);
+        verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
     }
 
     @Test
     public void testAllocRandomSpi() throws Exception {
-        int resourceId = 1;
         IpSecSpiResponse spiResp =
-                new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
+                new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
         when(mMockIpSecService.allocateSecurityParameterIndex(
                         eq(GOOGLE_DNS_4.getHostAddress()),
                         eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX),
@@ -113,7 +116,7 @@
 
         randomSpi.close();
 
-        verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId);
+        verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
     }
 
     /*
@@ -165,11 +168,10 @@
 
     @Test
     public void testOpenEncapsulationSocket() throws Exception {
-        int resourceId = 1;
         IpSecUdpEncapResponse udpEncapResp =
                 new IpSecUdpEncapResponse(
                         IpSecManager.Status.OK,
-                        resourceId,
+                        DUMMY_RESOURCE_ID,
                         TEST_UDP_ENCAP_PORT,
                         Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
         when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject()))
@@ -182,16 +184,15 @@
 
         encapSocket.close();
 
-        verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId);
+        verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
     }
 
     @Test
     public void testOpenEncapsulationSocketOnRandomPort() throws Exception {
-        int resourceId = 1;
         IpSecUdpEncapResponse udpEncapResp =
                 new IpSecUdpEncapResponse(
                         IpSecManager.Status.OK,
-                        resourceId,
+                        DUMMY_RESOURCE_ID,
                         TEST_UDP_ENCAP_PORT,
                         Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
 
@@ -206,7 +207,7 @@
 
         encapSocket.close();
 
-        verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId);
+        verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
     }
 
     @Test
@@ -219,4 +220,45 @@
     }
 
     // TODO: add test when applicable transform builder interface is available
-}
+
+    private IpSecManager.IpSecTunnelInterface createAndValidateVti(int resourceId, String intfName)
+            throws Exception {
+        IpSecTunnelInterfaceResponse dummyResponse =
+                new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
+        when(mMockIpSecService.createTunnelInterface(
+                eq(VTI_LOCAL_ADDRESS.getHostAddress()), eq(GOOGLE_DNS_4.getHostAddress()),
+                anyObject(), anyObject()))
+                        .thenReturn(dummyResponse);
+
+        IpSecManager.IpSecTunnelInterface tunnelIntf = mIpSecManager.createIpSecTunnelInterface(
+                VTI_LOCAL_ADDRESS, GOOGLE_DNS_4, mock(Network.class));
+
+        assertNotNull(tunnelIntf);
+        return tunnelIntf;
+    }
+
+    @Test
+    public void testCreateVti() throws Exception {
+        IpSecManager.IpSecTunnelInterface tunnelIntf =
+                createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
+
+        assertEquals(VTI_INTF_NAME, tunnelIntf.getInterfaceName());
+
+        tunnelIntf.close();
+        verify(mMockIpSecService).deleteTunnelInterface(eq(DUMMY_RESOURCE_ID));
+    }
+
+    @Test
+    public void testAddRemoveAddressesFromVti() throws Exception {
+        IpSecManager.IpSecTunnelInterface tunnelIntf =
+                createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
+
+        tunnelIntf.addAddress(VTI_INNER_ADDRESS);
+        verify(mMockIpSecService)
+                .addAddressToTunnelInterface(eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS));
+
+        tunnelIntf.removeAddress(VTI_INNER_ADDRESS);
+        verify(mMockIpSecService)
+                .addAddressToTunnelInterface(eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS));
+    }
+}
\ No newline at end of file
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 3e1ff6d..410f754 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -17,11 +17,13 @@
 package com.android.server;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -32,6 +34,9 @@
 import android.net.IpSecManager;
 import android.net.IpSecSpiResponse;
 import android.net.IpSecTransformResponse;
+import android.net.IpSecTunnelInterfaceResponse;
+import android.net.LinkAddress;
+import android.net.Network;
 import android.net.NetworkUtils;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
@@ -56,10 +61,15 @@
 
     private final String mDestinationAddr;
     private final String mSourceAddr;
+    private final LinkAddress mLocalInnerAddress;
 
     @Parameterized.Parameters
     public static Collection ipSecConfigs() {
-        return Arrays.asList(new Object[][] {{"1.2.3.4", "8.8.4.4"}, {"2601::2", "2601::10"}});
+        return Arrays.asList(
+                new Object[][] {
+                {"1.2.3.4", "8.8.4.4", "10.0.1.1/24"},
+                {"2601::2", "2601::10", "2001:db8::1/64"}
+        });
     }
 
     private static final byte[] AEAD_KEY = {
@@ -86,6 +96,7 @@
     INetd mMockNetd;
     IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
     IpSecService mIpSecService;
+    Network fakeNetwork = new Network(0xAB);
 
     private static final IpSecAlgorithm AUTH_ALGO =
             new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
@@ -94,9 +105,11 @@
     private static final IpSecAlgorithm AEAD_ALGO =
             new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
 
-    public IpSecServiceParameterizedTest(String sourceAddr, String destAddr) {
+    public IpSecServiceParameterizedTest(
+            String sourceAddr, String destAddr, String localInnerAddr) {
         mSourceAddr = sourceAddr;
         mDestinationAddr = destAddr;
+        mLocalInnerAddress = new LinkAddress(localInnerAddr);
     }
 
     @Before
@@ -308,6 +321,30 @@
     }
 
     @Test
+    public void testReleaseOwnedSpi() throws Exception {
+        IpSecConfig ipSecConfig = new IpSecConfig();
+        addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
+        addAuthAndCryptToIpSecConfig(ipSecConfig);
+
+        IpSecTransformResponse createTransformResp =
+                mIpSecService.createTransform(ipSecConfig, new Binder());
+        IpSecService.UserRecord userRecord =
+                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
+        mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
+        verify(mMockNetd, times(0))
+                .ipSecDeleteSecurityAssociation(
+                        eq(createTransformResp.resourceId),
+                        anyString(),
+                        anyString(),
+                        eq(TEST_SPI),
+                        anyInt(),
+                        anyInt());
+        // quota is not released until the SPI is released by the Transform
+        assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
+    }
+
+    @Test
     public void testDeleteTransform() throws Exception {
         IpSecConfig ipSecConfig = new IpSecConfig();
         addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
@@ -317,7 +354,7 @@
                 mIpSecService.createTransform(ipSecConfig, new Binder());
         mIpSecService.deleteTransform(createTransformResp.resourceId);
 
-        verify(mMockNetd)
+        verify(mMockNetd, times(1))
                 .ipSecDeleteSecurityAssociation(
                         eq(createTransformResp.resourceId),
                         anyString(),
@@ -330,6 +367,21 @@
         IpSecService.UserRecord userRecord =
                 mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
         assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent);
+        assertEquals(1, userRecord.mSpiQuotaTracker.mCurrent);
+
+        mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId());
+        // Verify that ipSecDeleteSa was not called when the SPI was released because the
+        // ownedByTransform property should prevent it; (note, the called count is cumulative).
+        verify(mMockNetd, times(1))
+                .ipSecDeleteSecurityAssociation(
+                        anyInt(),
+                        anyString(),
+                        anyString(),
+                        anyInt(),
+                        anyInt(),
+                        anyInt());
+        assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent);
+
         try {
             userRecord.mTransformRecords.getRefcountedResourceOrThrow(
                     createTransformResp.resourceId);
@@ -406,4 +458,103 @@
 
         verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
     }
+
+    private IpSecTunnelInterfaceResponse createAndValidateTunnel(
+            String localAddr, String remoteAddr) {
+        IpSecTunnelInterfaceResponse createTunnelResp =
+                mIpSecService.createTunnelInterface(
+                        mSourceAddr, mDestinationAddr, fakeNetwork, new Binder());
+
+        assertNotNull(createTunnelResp);
+        assertEquals(IpSecManager.Status.OK, createTunnelResp.status);
+        return createTunnelResp;
+    }
+
+    @Test
+    public void testCreateTunnelInterface() throws Exception {
+        IpSecTunnelInterfaceResponse createTunnelResp =
+                createAndValidateTunnel(mSourceAddr, mDestinationAddr);
+
+        // Check that we have stored the tracking object, and retrieve it
+        IpSecService.UserRecord userRecord =
+                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.RefcountedResource refcountedRecord =
+                userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
+                        createTunnelResp.resourceId);
+
+        assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent);
+        verify(mMockNetd)
+                .addVirtualTunnelInterface(
+                        eq(createTunnelResp.interfaceName),
+                        eq(mSourceAddr),
+                        eq(mDestinationAddr),
+                        anyInt(),
+                        anyInt());
+    }
+
+    @Test
+    public void testDeleteTunnelInterface() throws Exception {
+        IpSecTunnelInterfaceResponse createTunnelResp =
+                createAndValidateTunnel(mSourceAddr, mDestinationAddr);
+
+        IpSecService.UserRecord userRecord =
+                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+
+        mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId);
+
+        // Verify quota and RefcountedResource objects cleaned up
+        assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
+        verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
+        try {
+            userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
+                    createTunnelResp.resourceId);
+            fail("Expected IllegalArgumentException on attempt to access deleted resource");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testTunnelInterfaceBinderDeath() throws Exception {
+        IpSecTunnelInterfaceResponse createTunnelResp =
+                createAndValidateTunnel(mSourceAddr, mDestinationAddr);
+
+        IpSecService.UserRecord userRecord =
+                mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
+        IpSecService.RefcountedResource refcountedRecord =
+                userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
+                        createTunnelResp.resourceId);
+
+        refcountedRecord.binderDied();
+
+        // Verify quota and RefcountedResource objects cleaned up
+        assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
+        verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
+        try {
+            userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
+                    createTunnelResp.resourceId);
+            fail("Expected IllegalArgumentException on attempt to access deleted resource");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testAddRemoveAddressFromTunnelInterface() throws Exception {
+        IpSecTunnelInterfaceResponse createTunnelResp =
+                createAndValidateTunnel(mSourceAddr, mDestinationAddr);
+
+        mIpSecService.addAddressToTunnelInterface(createTunnelResp.resourceId, mLocalInnerAddress);
+        verify(mMockNetd)
+                .interfaceAddAddress(
+                        eq(createTunnelResp.interfaceName),
+                        eq(mLocalInnerAddress.getAddress().getHostAddress()),
+                        eq(mLocalInnerAddress.getPrefixLength()));
+
+        mIpSecService.removeAddressFromTunnelInterface(
+                createTunnelResp.resourceId, mLocalInnerAddress);
+        verify(mMockNetd)
+                .interfaceDelAddress(
+                        eq(createTunnelResp.interfaceName),
+                        eq(mLocalInnerAddress.getAddress().getHostAddress()),
+                        eq(mLocalInnerAddress.getPrefixLength()));
+    }
 }