Merge "Move FlickerTests to frameworks/base/tests 2/2"
diff --git a/Android.bp b/Android.bp
index 21b8404..6815a0d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -94,6 +94,7 @@
         "core/java/android/app/trust/IStrongAuthTracker.aidl",
         "core/java/android/app/trust/ITrustManager.aidl",
         "core/java/android/app/trust/ITrustListener.aidl",
+        "core/java/android/app/backup/IBackupCallback.aidl",
         "core/java/android/app/backup/IBackupManager.aidl",
         "core/java/android/app/backup/IBackupObserver.aidl",
         "core/java/android/app/backup/IBackupManagerMonitor.aidl",
diff --git a/Android.mk b/Android.mk
index f81f756..edbb94d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -171,15 +171,17 @@
     -hidePackage com.android.server
 
 # Convert an sdk level to a "since" argument.
-since-arg = -since $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(1)/public/api/android.*) $(1)
+since-arg = -since $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(1)/public/api/android.$(2)) $(1)
 
-finalized_sdks := $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.xml,%,\
-    $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.xml))
-finalized_sdks += $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.txt,%,\
-    $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.txt))
-finalized_sdks := $(call numerically_sort,$(finalized_sdks))
+finalized_xml_sdks := $(call numerically_sort,\
+    $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.xml,%,\
+    $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.xml)))
+finalized_txt_sdks := $(call numerically_sort,\
+     $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.txt,%,\
+    $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.txt)))
 
-framework_docs_LOCAL_DROIDDOC_OPTIONS += $(foreach sdk,$(finalized_sdks),$(call since-arg,$(sdk)))
+framework_docs_LOCAL_DROIDDOC_OPTIONS += $(foreach sdk,$(finalized_xml_sdks),$(call since-arg,$(sdk),xml))
+framework_docs_LOCAL_DROIDDOC_OPTIONS += $(foreach sdk,$(finalized_txt_sdks),$(call since-arg,$(sdk),txt))
 ifneq ($(PLATFORM_VERSION_CODENAME),REL)
   framework_docs_LOCAL_DROIDDOC_OPTIONS += \
       -since ./frameworks/base/api/current.txt $(PLATFORM_VERSION_CODENAME)
@@ -361,8 +363,8 @@
 LOCAL_SRC_GREYLIST := frameworks/base/config/hiddenapi-light-greylist.txt
 LOCAL_SRC_VENDOR_LIST := frameworks/base/config/hiddenapi-vendor-list.txt
 LOCAL_SRC_FORCE_BLACKLIST := frameworks/base/config/hiddenapi-force-blacklist.txt
-LOCAL_SRC_PUBLIC_API := $(INTERNAL_PLATFORM_DEX_API_FILE)
-LOCAL_SRC_PRIVATE_API := $(INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE)
+LOCAL_SRC_PUBLIC_API := $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST)
+LOCAL_SRC_PRIVATE_API := $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST)
 LOCAL_SRC_REMOVED_API := $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE)
 
 LOCAL_SRC_ALL := \
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
index 05293a2..66a2600d 100644
--- a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -48,7 +48,7 @@
 
     @Before
     public void setUp() {
-        mBinderCallsStats = new BinderCallsStats(new Random());
+        mBinderCallsStats = new BinderCallsStats(new BinderCallsStats.Injector());
     }
 
     @After
diff --git a/api/system-current.txt b/api/system-current.txt
index 924d3af..01f4709 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4524,9 +4524,11 @@
   public abstract class AutofillFieldClassificationService extends android.app.Service {
     method public android.os.IBinder onBind(android.content.Intent);
     method public float[][] onGetScores(java.lang.String, android.os.Bundle, java.util.List<android.view.autofill.AutofillValue>, java.util.List<java.lang.String>);
+    field public static final java.lang.String RESOURCE_AVAILABLE_ALGORITHMS = "autofill_field_classification_available_algorithms";
+    field public static final java.lang.String RESOURCE_DEFAULT_ALGORITHM = "autofill_field_classification_default_algorithm";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
-    field public static final java.lang.String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.autofill.field_classification.available_algorithms";
-    field public static final java.lang.String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm";
+    field public static final deprecated java.lang.String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.autofill.field_classification.available_algorithms";
+    field public static final deprecated java.lang.String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm";
   }
 
 }
@@ -4665,6 +4667,7 @@
     field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
     field public static final java.lang.String KEY_PEOPLE = "key_people";
     field public static final java.lang.String KEY_SMART_ACTIONS = "key_smart_actions";
+    field public static final java.lang.String KEY_SMART_REPLIES = "key_smart_replies";
     field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
     field public static final java.lang.String KEY_USER_SENTIMENT = "key_user_sentiment";
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 462d22e..1d08da5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1044,6 +1044,7 @@
     field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
     field public static final java.lang.String KEY_PEOPLE = "key_people";
     field public static final java.lang.String KEY_SMART_ACTIONS = "key_smart_actions";
+    field public static final java.lang.String KEY_SMART_REPLIES = "key_smart_replies";
     field public static final java.lang.String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
     field public static final java.lang.String KEY_USER_SENTIMENT = "key_user_sentiment";
   }
diff --git a/config/hiddenapi-force-blacklist.txt b/config/hiddenapi-force-blacklist.txt
index 3a9e2d1..dca3b52 100644
--- a/config/hiddenapi-force-blacklist.txt
+++ b/config/hiddenapi-force-blacklist.txt
@@ -1,38 +1,38 @@
 Ldalvik/system/VMRuntime;->setHiddenApiExemptions([Ljava/lang/String;)V
 Ljava/lang/invoke/MethodHandles$Lookup;->IMPL_LOOKUP:Ljava/lang/invoke/MethodHandles$Lookup;
 Ljava/lang/invoke/VarHandle;->acquireFence()V
-Ljava/lang/invoke/VarHandle;->compareAndExchange([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->compareAndExchangeAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->compareAndExchangeRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->compareAndSet([[Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->compareAndExchange([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->compareAndExchangeAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->compareAndExchangeRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->compareAndSet([Ljava/lang/Object;)Z
 Ljava/lang/invoke/VarHandle;->fullFence()V
-Ljava/lang/invoke/VarHandle;->get([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndAdd([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndAddAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndAddRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseAnd([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseAndAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseAndRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseOr([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseOrAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseOrRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseXor([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseXorAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndBitwiseXorRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndSet([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndSetAcquire([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getAndSetRelease([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getOpaque([[Ljava/lang/Object;)Ljava/lang/Object;
-Ljava/lang/invoke/VarHandle;->getVolatile([[Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->get([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndAdd([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndAddAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndAddRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseAnd([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseAndAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseAndRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseOr([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseOrAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseOrRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseXor([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseXorAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndBitwiseXorRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndSet([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndSetAcquire([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getAndSetRelease([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getOpaque([Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/invoke/VarHandle;->getVolatile([Ljava/lang/Object;)Ljava/lang/Object;
 Ljava/lang/invoke/VarHandle;->loadLoadFence()V
 Ljava/lang/invoke/VarHandle;->releaseFence()V
-Ljava/lang/invoke/VarHandle;->set([[Ljava/lang/Object;)V
-Ljava/lang/invoke/VarHandle;->setOpaque([[Ljava/lang/Object;)V
-Ljava/lang/invoke/VarHandle;->setRelease([[Ljava/lang/Object;)V
-Ljava/lang/invoke/VarHandle;->setVolatile([[Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->set([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->setOpaque([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->setRelease([Ljava/lang/Object;)V
+Ljava/lang/invoke/VarHandle;->setVolatile([Ljava/lang/Object;)V
 Ljava/lang/invoke/VarHandle;->storeStoreFence()V
-Ljava/lang/invoke/VarHandle;->weakCompareAndSet([[Ljava/lang/Object;)Z
-Ljava/lang/invoke/VarHandle;->weakCompareAndSetAcquire([[Ljava/lang/Object;)Z
-Ljava/lang/invoke/VarHandle;->weakCompareAndSetPlain([[Ljava/lang/Object;)Z
-Ljava/lang/invoke/VarHandle;->weakCompareAndSetRelease([[Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSet([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSetAcquire([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSetPlain([Ljava/lang/Object;)Z
+Ljava/lang/invoke/VarHandle;->weakCompareAndSetRelease([Ljava/lang/Object;)Z
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index b936fe7..0b94c27 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1,6 +1,3 @@
-Landroid/accessibilityservice/AccessibilityService;->mInfo:Landroid/accessibilityservice/AccessibilityServiceInfo;
-Landroid/accessibilityservice/AccessibilityService;->mWindowToken:Landroid/os/IBinder;
-Landroid/accessibilityservice/AccessibilityServiceInfo;->setCapabilities(I)V
 Landroid/accessibilityservice/IAccessibilityServiceConnection$Stub;-><init>()V
 Landroid/accessibilityservice/IAccessibilityServiceConnection$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accessibilityservice/IAccessibilityServiceConnection;
 Landroid/accounts/Account;->accessId:Ljava/lang/String;
@@ -51,13 +48,6 @@
 Landroid/accounts/IAccountManagerResponse$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountManagerResponse;
 Landroid/accounts/IAccountManagerResponse;->onError(ILjava/lang/String;)V
 Landroid/accounts/IAccountManagerResponse;->onResult(Landroid/os/Bundle;)V
-Landroid/animation/Animator;->reverse()V
-Landroid/animation/ArgbEvaluator;->getInstance()Landroid/animation/ArgbEvaluator;
-Landroid/animation/LayoutTransition;->cancel()V
-Landroid/animation/LayoutTransition;->cancel(I)V
-Landroid/animation/ValueAnimator;->animateValue(F)V
-Landroid/animation/ValueAnimator;->mDuration:J
-Landroid/animation/ValueAnimator;->sDurationScale:F
 Landroid/app/ActionBar;->collapseActionView()Z
 Landroid/app/ActionBar;->DISPLAY_TITLE_MULTIPLE_LINES:I
 Landroid/app/ActionBar;->setShowHideAnimationEnabled(Z)V
@@ -533,7 +523,7 @@
 Landroid/app/DownloadManager$Request;->mUri:Landroid/net/Uri;
 Landroid/app/DownloadManager;->getWhereArgsForIds([J)[Ljava/lang/String;
 Landroid/app/DownloadManager;->getWhereClauseForIds([J)Ljava/lang/String;
-Landroid/app/DownloadManager;->restartDownload([[J)V
+Landroid/app/DownloadManager;->restartDownload([J)V
 Landroid/app/DownloadManager;->setAccessAllDownloads(Z)V
 Landroid/app/DownloadManager;->setAccessFilename(Z)V
 Landroid/app/DownloadManager;->UNDERLYING_COLUMNS:[Ljava/lang/String;
@@ -1049,7 +1039,6 @@
 Landroid/bluetooth/BluetoothClass;->doesClassMatch(I)Z
 Landroid/bluetooth/BluetoothClass;->PROFILE_A2DP:I
 Landroid/bluetooth/BluetoothClass;->PROFILE_HEADSET:I
-Landroid/bluetooth/BluetoothCodecConfig;
 Landroid/bluetooth/BluetoothCodecConfig;-><init>(IIIIIJJJJ)V
 Landroid/bluetooth/BluetoothCodecConfig;->BITS_PER_SAMPLE_16:I
 Landroid/bluetooth/BluetoothCodecConfig;->BITS_PER_SAMPLE_24:I
@@ -1085,7 +1074,6 @@
 Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_LDAC:I
 Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_MAX:I
 Landroid/bluetooth/BluetoothCodecConfig;->SOURCE_CODEC_TYPE_SBC:I
-Landroid/bluetooth/BluetoothCodecStatus;
 Landroid/bluetooth/BluetoothCodecStatus;->EXTRA_CODEC_STATUS:Ljava/lang/String;
 Landroid/bluetooth/BluetoothCodecStatus;->getCodecConfig()Landroid/bluetooth/BluetoothCodecConfig;
 Landroid/bluetooth/BluetoothCodecStatus;->getCodecsLocalCapabilities()[Landroid/bluetooth/BluetoothCodecConfig;
@@ -1453,10 +1441,15 @@
 Landroid/content/pm/ComponentInfo;->getComponentName()Landroid/content/ComponentName;
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->onRemoveCompleted(Ljava/lang/String;Z)V
 Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver;
+Landroid/content/pm/IPackageDataObserver$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/content/pm/IPackageDataObserver$Stub;->TRANSACTION_onRemoveCompleted:I
 Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V
 Landroid/content/pm/IPackageDeleteObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
+Landroid/content/pm/IPackageDeleteObserver$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/content/pm/IPackageDeleteObserver$Stub;->TRANSACTION_packageDeleted:I
 Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageDeleteObserver2$Stub;-><init>()V
@@ -1555,6 +1548,8 @@
 Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageStatsObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageStatsObserver;
+Landroid/content/pm/IPackageStatsObserver$Stub;->DESCRIPTOR:Ljava/lang/String;
+Landroid/content/pm/IPackageStatsObserver$Stub;->TRANSACTION_onGetStatsCompleted:I
 Landroid/content/pm/IShortcutService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IShortcutService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IShortcutService;
 Landroid/content/pm/LauncherActivityInfo;->mActivityInfo:Landroid/content/pm/ActivityInfo;
@@ -2025,8 +2020,6 @@
 Landroid/database/sqlite/SqliteWrapper;->checkSQLiteException(Landroid/content/Context;Landroid/database/sqlite/SQLiteException;)V
 Landroid/database/sqlite/SqliteWrapper;->delete(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I
 Landroid/database/sqlite/SqliteWrapper;->update(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I
-Landroid/ddm/DdmHandleAppName;->getAppName()Ljava/lang/String;
-Landroid/ddm/DdmHandleAppName;->setAppName(Ljava/lang/String;I)V
 Landroid/filterfw/core/Filter;-><init>(Ljava/lang/String;)V
 Landroid/filterfw/core/Filter;->isAvailable(Ljava/lang/String;)Z
 Landroid/filterfw/core/Filter;->setInputValue(Ljava/lang/String;Ljava/lang/Object;)V
@@ -2093,268 +2086,7 @@
 Landroid/filterfw/GraphEnvironment;-><init>()V
 Landroid/filterfw/GraphEnvironment;->getRunner(II)Landroid/filterfw/core/GraphRunner;
 Landroid/filterfw/GraphEnvironment;->loadGraph(Landroid/content/Context;I)I
-Landroid/graphics/BaseCanvas;->mNativeCanvasWrapper:J
-Landroid/graphics/Bitmap$Config;->nativeInt:I
-Landroid/graphics/Bitmap$Config;->nativeToConfig(I)Landroid/graphics/Bitmap$Config;
-Landroid/graphics/Bitmap;-><init>(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;)V
-Landroid/graphics/Bitmap;->createAshmemBitmap()Landroid/graphics/Bitmap;
-Landroid/graphics/Bitmap;->createAshmemBitmap(Landroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;
-Landroid/graphics/Bitmap;->getDefaultDensity()I
-Landroid/graphics/Bitmap;->mHeight:I
-Landroid/graphics/Bitmap;->mNativePtr:J
-Landroid/graphics/Bitmap;->mNinePatchChunk:[B
-Landroid/graphics/Bitmap;->mNinePatchInsets:Landroid/graphics/NinePatch$InsetStruct;
-Landroid/graphics/Bitmap;->mWidth:I
-Landroid/graphics/Bitmap;->nativeReconfigure(JIIIZ)V
-Landroid/graphics/Bitmap;->reinit(IIZ)V
-Landroid/graphics/Bitmap;->scaleFromDensity(III)I
-Landroid/graphics/Bitmap;->setDefaultDensity(I)V
-Landroid/graphics/Bitmap;->setNinePatchChunk([B)V
-Landroid/graphics/BitmapFactory;->nativeDecodeAsset(JLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapFactory;->nativeDecodeByteArray([BIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapFactory;->nativeDecodeFileDescriptor(Ljava/io/FileDescriptor;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapFactory;->nativeDecodeStream(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapRegionDecoder;-><init>(J)V
-Landroid/graphics/BitmapRegionDecoder;->nativeNewInstance([BIIZ)Landroid/graphics/BitmapRegionDecoder;
-Landroid/graphics/BitmapShader;->mBitmap:Landroid/graphics/Bitmap;
-Landroid/graphics/BitmapShader;->mTileX:I
-Landroid/graphics/BitmapShader;->mTileY:I
-Landroid/graphics/Camera;->native_instance:J
-Landroid/graphics/Canvas;-><init>(J)V
-Landroid/graphics/Canvas;->freeCaches()V
-Landroid/graphics/Canvas;->freeTextLayoutCaches()V
-Landroid/graphics/Canvas;->getGL()Ljavax/microedition/khronos/opengles/GL;
-Landroid/graphics/Canvas;->getNativeCanvasWrapper()J
-Landroid/graphics/Canvas;->mBitmap:Landroid/graphics/Bitmap;
-Landroid/graphics/Canvas;->release()V
-Landroid/graphics/Canvas;->setScreenDensity(I)V
-Landroid/graphics/CanvasProperty;->createFloat(F)Landroid/graphics/CanvasProperty;
-Landroid/graphics/CanvasProperty;->createPaint(Landroid/graphics/Paint;)Landroid/graphics/CanvasProperty;
-Landroid/graphics/ColorMatrixColorFilter;->mMatrix:Landroid/graphics/ColorMatrix;
-Landroid/graphics/ColorMatrixColorFilter;->setColorMatrix(Landroid/graphics/ColorMatrix;)V
-Landroid/graphics/ColorMatrixColorFilter;->setColorMatrixArray([F)V
-Landroid/graphics/drawable/AnimatedImageDrawable;->onAnimationEnd()V
-Landroid/graphics/drawable/AnimatedRotateDrawable;->setFramesCount(I)V
-Landroid/graphics/drawable/AnimatedRotateDrawable;->setFramesDuration(I)V
-Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;->mStateIds:Landroid/util/SparseIntArray;
-Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;->mTransitions:Landroid/util/LongSparseLongArray;
-Landroid/graphics/drawable/AnimatedStateListDrawable;->mState:Landroid/graphics/drawable/AnimatedStateListDrawable$AnimatedStateListState;
-Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;->callOnFinished(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V
-Landroid/graphics/drawable/AnimatedVectorDrawable;->forceAnimationOnUI()V
-Landroid/graphics/drawable/AnimatedVectorDrawable;->mAnimatedVectorState:Landroid/graphics/drawable/AnimatedVectorDrawable$AnimatedVectorDrawableState;
-Landroid/graphics/drawable/AnimatedVectorDrawable;->mAnimatorSet:Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;
-Landroid/graphics/drawable/AnimationDrawable;->mCurFrame:I
-Landroid/graphics/drawable/BitmapDrawable;->getTint()Landroid/content/res/ColorStateList;
-Landroid/graphics/drawable/BitmapDrawable;->getTintMode()Landroid/graphics/PorterDuff$Mode;
-Landroid/graphics/drawable/BitmapDrawable;->mBitmapState:Landroid/graphics/drawable/BitmapDrawable$BitmapState;
-Landroid/graphics/drawable/BitmapDrawable;->mTargetDensity:I
-Landroid/graphics/drawable/BitmapDrawable;->setBitmap(Landroid/graphics/Bitmap;)V
-Landroid/graphics/drawable/ClipDrawable;->mState:Landroid/graphics/drawable/ClipDrawable$ClipState;
-Landroid/graphics/drawable/ColorDrawable$ColorState;->mUseColor:I
-Landroid/graphics/drawable/ColorDrawable;->mPaint:Landroid/graphics/Paint;
-Landroid/graphics/drawable/Drawable;->inflateWithAttributes(Landroid/content/res/Resources;Lorg/xmlpull/v1/XmlPullParser;Landroid/content/res/TypedArray;I)V
-Landroid/graphics/drawable/Drawable;->mCallback:Ljava/lang/ref/WeakReference;
-Landroid/graphics/drawable/Drawable;->mSrcDensityOverride:I
-Landroid/graphics/drawable/Drawable;->parseTintMode(ILandroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuff$Mode;
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;-><init>(Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;Landroid/graphics/drawable/DrawableContainer;Landroid/content/res/Resources;)V
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mConstantPadding:Landroid/graphics/Rect;
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mDrawables:[Landroid/graphics/drawable/Drawable;
-Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;->mHasColorFilter:Z
-Landroid/graphics/drawable/DrawableContainer;->mDrawableContainerState:Landroid/graphics/drawable/DrawableContainer$DrawableContainerState;
-Landroid/graphics/drawable/DrawableContainer;->mLastDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/graphics/drawable/DrawableInflater;->mClassLoader:Ljava/lang/ClassLoader;
-Landroid/graphics/drawable/DrawableWrapper;->mState:Landroid/graphics/drawable/DrawableWrapper$DrawableWrapperState;
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mAngle:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mGradient:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mGradientColors:[I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mHeight:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mInnerRadius:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mInnerRadiusRatio:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mOrientation:Landroid/graphics/drawable/GradientDrawable$Orientation;
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mPadding:Landroid/graphics/Rect;
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mPositions:[F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mRadius:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mRadiusArray:[F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mShape:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mSolidColors:Landroid/content/res/ColorStateList;
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mStrokeDashGap:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mStrokeDashWidth:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mStrokeWidth:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mThickness:I
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mThicknessRatio:F
-Landroid/graphics/drawable/GradientDrawable$GradientState;->mWidth:I
-Landroid/graphics/drawable/GradientDrawable;->mFillPaint:Landroid/graphics/Paint;
-Landroid/graphics/drawable/GradientDrawable;->mGradientState:Landroid/graphics/drawable/GradientDrawable$GradientState;
-Landroid/graphics/drawable/GradientDrawable;->mPadding:Landroid/graphics/Rect;
-Landroid/graphics/drawable/GradientDrawable;->mStrokePaint:Landroid/graphics/Paint;
-Landroid/graphics/drawable/Icon;->createWithResource(Landroid/content/res/Resources;I)Landroid/graphics/drawable/Icon;
-Landroid/graphics/drawable/Icon;->getBitmap()Landroid/graphics/Bitmap;
-Landroid/graphics/drawable/Icon;->getDataBytes()[B
-Landroid/graphics/drawable/Icon;->getDataLength()I
-Landroid/graphics/drawable/Icon;->getDataOffset()I
-Landroid/graphics/drawable/Icon;->getResources()Landroid/content/res/Resources;
-Landroid/graphics/drawable/Icon;->hasTint()Z
-Landroid/graphics/drawable/Icon;->mString1:Ljava/lang/String;
-Landroid/graphics/drawable/Icon;->mType:I
-Landroid/graphics/drawable/InsetDrawable;->mState:Landroid/graphics/drawable/InsetDrawable$InsetState;
-Landroid/graphics/drawable/LayerDrawable$ChildDrawable;->mDrawable:Landroid/graphics/drawable/Drawable;
-Landroid/graphics/drawable/LayerDrawable$LayerState;->mChildren:[Landroid/graphics/drawable/LayerDrawable$ChildDrawable;
-Landroid/graphics/drawable/LayerDrawable;->addLayer(Landroid/graphics/drawable/LayerDrawable$ChildDrawable;)I
-Landroid/graphics/drawable/LayerDrawable;->ensurePadding()V
-Landroid/graphics/drawable/LayerDrawable;->mLayerState:Landroid/graphics/drawable/LayerDrawable$LayerState;
-Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;->mNinePatch:Landroid/graphics/NinePatch;
-Landroid/graphics/drawable/NinePatchDrawable;->mNinePatchState:Landroid/graphics/drawable/NinePatchDrawable$NinePatchState;
-Landroid/graphics/drawable/RippleDrawable$RippleState;->mColor:Landroid/content/res/ColorStateList;
-Landroid/graphics/drawable/RippleDrawable;->getRipplePaint()Landroid/graphics/Paint;
-Landroid/graphics/drawable/RippleDrawable;->mDensity:I
-Landroid/graphics/drawable/RippleDrawable;->mState:Landroid/graphics/drawable/RippleDrawable$RippleState;
-Landroid/graphics/drawable/RippleDrawable;->setForceSoftware(Z)V
-Landroid/graphics/drawable/RotateDrawable;->mState:Landroid/graphics/drawable/RotateDrawable$RotateState;
-Landroid/graphics/drawable/ScaleDrawable;->mState:Landroid/graphics/drawable/ScaleDrawable$ScaleState;
-Landroid/graphics/drawable/StateListDrawable$StateListState;->addStateSet([ILandroid/graphics/drawable/Drawable;)I
-Landroid/graphics/drawable/StateListDrawable;->extractStateSet(Landroid/util/AttributeSet;)[I
-Landroid/graphics/drawable/StateListDrawable;->mStateListState:Landroid/graphics/drawable/StateListDrawable$StateListState;
-Landroid/graphics/drawable/StateListDrawable;->updateStateFromTypedArray(Landroid/content/res/TypedArray;)V
-Landroid/graphics/drawable/TransitionDrawable;->mAlpha:I
-Landroid/graphics/drawable/TransitionDrawable;->mCrossFade:Z
-Landroid/graphics/drawable/TransitionDrawable;->mTo:I
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setPivotX(F)V
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setPivotY(F)V
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setRotation(F)V
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setTranslateX(F)V
-Landroid/graphics/drawable/VectorDrawable$VGroup;->setTranslateY(F)V
-Landroid/graphics/drawable/VectorDrawable;->getTargetByName(Ljava/lang/String;)Ljava/lang/Object;
-Landroid/graphics/drawable/VectorDrawable;->mTintFilter:Landroid/graphics/PorterDuffColorFilter;
-Landroid/graphics/drawable/VectorDrawable;->setAllowCaching(Z)V
-Landroid/graphics/FontFamily;-><init>()V
-Landroid/graphics/FontFamily;-><init>([Ljava/lang/String;I)V
-Landroid/graphics/FontFamily;->abortCreation()V
-Landroid/graphics/FontFamily;->addFontFromAssetManager(Landroid/content/res/AssetManager;Ljava/lang/String;IZIII[Landroid/graphics/fonts/FontVariationAxis;)Z
-Landroid/graphics/FontFamily;->addFontFromBuffer(Ljava/nio/ByteBuffer;I[Landroid/graphics/fonts/FontVariationAxis;II)Z
-Landroid/graphics/FontFamily;->freeze()Z
-Landroid/graphics/FontFamily;->mNativePtr:J
-Landroid/graphics/FontListParser;->parse(Ljava/io/InputStream;)Landroid/text/FontConfig;
-Landroid/graphics/fonts/FontVariationAxis;->mStyleValue:F
-Landroid/graphics/fonts/FontVariationAxis;->mTag:I
-Landroid/graphics/GraphicBuffer;-><init>(IIIIJ)V
-Landroid/graphics/GraphicBuffer;->createFromExisting(IIIIJ)Landroid/graphics/GraphicBuffer;
-Landroid/graphics/GraphicBuffer;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/graphics/GraphicBuffer;->mNativeObject:J
-Landroid/graphics/ImageDecoder;->postProcessAndRelease(Landroid/graphics/Canvas;)I
-Landroid/graphics/ImageFormat;->Y8:I
-Landroid/graphics/LightingColorFilter;->setColorAdd(I)V
-Landroid/graphics/LightingColorFilter;->setColorMultiply(I)V
-Landroid/graphics/LinearGradient;->mColor0:I
-Landroid/graphics/LinearGradient;->mColor1:I
-Landroid/graphics/LinearGradient;->mColors:[I
-Landroid/graphics/LinearGradient;->mPositions:[F
-Landroid/graphics/LinearGradient;->mTileMode:Landroid/graphics/Shader$TileMode;
-Landroid/graphics/LinearGradient;->mX0:F
-Landroid/graphics/LinearGradient;->mX1:F
-Landroid/graphics/LinearGradient;->mY0:F
-Landroid/graphics/LinearGradient;->mY1:F
-Landroid/graphics/Matrix;->IDENTITY_MATRIX:Landroid/graphics/Matrix;
-Landroid/graphics/Matrix;->native_instance:J
-Landroid/graphics/Movie;-><init>(J)V
-Landroid/graphics/Movie;->mNativeMovie:J
-Landroid/graphics/NinePatch$InsetStruct;-><init>(IIIIIIIIFIF)V
-Landroid/graphics/NinePatch;->mBitmap:Landroid/graphics/Bitmap;
-Landroid/graphics/NinePatch;->mNativeChunk:J
-Landroid/graphics/Outline;->mRect:Landroid/graphics/Rect;
-Landroid/graphics/Paint;->getNativeInstance()J
-Landroid/graphics/Paint;->getTextRunAdvances([CIIIIZ[FI)F
-Landroid/graphics/Paint;->getTextRunCursor([CIIIII)I
-Landroid/graphics/Paint;->mNativePaint:J
-Landroid/graphics/Paint;->mTypeface:Landroid/graphics/Typeface;
-Landroid/graphics/Paint;->setCompatibilityScaling(F)V
-Landroid/graphics/Paint;->setHyphenEdit(I)V
-Landroid/graphics/Path;->isSimplePath:Z
-Landroid/graphics/Path;->rects:Landroid/graphics/Region;
-Landroid/graphics/pdf/PdfRenderer;->doClose()V
-Landroid/graphics/pdf/PdfRenderer;->mCurrentPage:Landroid/graphics/pdf/PdfRenderer$Page;
-Landroid/graphics/Picture;->mNativePicture:J
-Landroid/graphics/PorterDuff$Mode;->nativeInt:I
-Landroid/graphics/PorterDuffColorFilter;->getColor()I
-Landroid/graphics/PorterDuffColorFilter;->getMode()Landroid/graphics/PorterDuff$Mode;
-Landroid/graphics/RadialGradient;->mCenterColor:I
-Landroid/graphics/RadialGradient;->mColors:[I
-Landroid/graphics/RadialGradient;->mEdgeColor:I
-Landroid/graphics/RadialGradient;->mPositions:[F
-Landroid/graphics/RadialGradient;->mRadius:F
-Landroid/graphics/RadialGradient;->mTileMode:Landroid/graphics/Shader$TileMode;
-Landroid/graphics/RadialGradient;->mX:F
-Landroid/graphics/RadialGradient;->mY:F
-Landroid/graphics/Rect;->printShortString(Ljava/io/PrintWriter;)V
-Landroid/graphics/Rect;->scale(F)V
-Landroid/graphics/Region$Op;->nativeInt:I
-Landroid/graphics/Region;-><init>(JI)V
-Landroid/graphics/Region;->mNativeRegion:J
-Landroid/graphics/Region;->recycle()V
-Landroid/graphics/Region;->scale(F)V
-Landroid/graphics/Shader$TileMode;->nativeInt:I
-Landroid/graphics/SurfaceTexture;->mFrameAvailableListener:J
-Landroid/graphics/SurfaceTexture;->mOnFrameAvailableHandler:Landroid/os/Handler;
-Landroid/graphics/SurfaceTexture;->mProducer:J
-Landroid/graphics/SurfaceTexture;->mSurfaceTexture:J
-Landroid/graphics/SurfaceTexture;->nativeDetachFromGLContext()I
-Landroid/graphics/SurfaceTexture;->postEventFromNative(Ljava/lang/ref/WeakReference;)V
-Landroid/graphics/SweepGradient;->mColor0:I
-Landroid/graphics/SweepGradient;->mColor1:I
-Landroid/graphics/SweepGradient;->mColors:[I
-Landroid/graphics/SweepGradient;->mCx:F
-Landroid/graphics/SweepGradient;->mCy:F
-Landroid/graphics/SweepGradient;->mPositions:[F
-Landroid/graphics/TableMaskFilter;->CreateClipTable(II)Landroid/graphics/TableMaskFilter;
-Landroid/graphics/TemporaryBuffer;->obtain(I)[C
-Landroid/graphics/TemporaryBuffer;->recycle([C)V
-Landroid/graphics/Typeface;-><init>(J)V
-Landroid/graphics/Typeface;->createFromFamilies([Landroid/graphics/FontFamily;)Landroid/graphics/Typeface;
-Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;II)Landroid/graphics/Typeface;
-Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;Ljava/lang/String;II)Landroid/graphics/Typeface;
-Landroid/graphics/Typeface;->mStyle:I
-Landroid/graphics/Typeface;->nativeCreateFromArray([JII)J
-Landroid/graphics/Typeface;->nativeCreateWeightAlias(JI)J
-Landroid/graphics/Typeface;->native_instance:J
-Landroid/graphics/Typeface;->sDefaults:[Landroid/graphics/Typeface;
-Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V
-Landroid/graphics/Typeface;->sSystemFallbackMap:Ljava/util/Map;
-Landroid/graphics/Typeface;->sSystemFontMap:Ljava/util/Map;
-Landroid/graphics/Xfermode;->porterDuffMode:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_GOOD:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_IMAGER_DIRTY:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_INSUFFICIENT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_PARTIAL:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_TOO_FAST:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_TOO_SLOW:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_CANCELED:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_HW_NOT_PRESENT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_HW_UNAVAILABLE:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_LOCKOUT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_LOCKOUT_PERMANENT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_NO_BIOMETRICS:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_NO_SPACE:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_TIMEOUT:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_UNABLE_TO_PROCESS:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_USER_CANCELED:I
-Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_VENDOR:I
 Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ERROR_VENDOR_BASE:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_GOOD:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_IMAGER_DIRTY:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_INSUFFICIENT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_PARTIAL:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_TOO_FAST:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ACQUIRED_TOO_SLOW:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_CANCELED:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_HW_NOT_PRESENT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_HW_UNAVAILABLE:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_LOCKOUT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_LOCKOUT_PERMANENT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_NO_FINGERPRINTS:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_NO_SPACE:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_TIMEOUT:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_UNABLE_TO_PROCESS:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_USER_CANCELED:I
-Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_VENDOR:I
 Landroid/hardware/biometrics/BiometricFingerprintConstants;->FINGERPRINT_ERROR_VENDOR_BASE:I
 Landroid/hardware/Camera$Parameters;->copyFrom(Landroid/hardware/Camera$Parameters;)V
 Landroid/hardware/Camera$Parameters;->dump()V
@@ -2615,7 +2347,6 @@
 Landroid/icu/text/Transliterator;->transliterate(Landroid/icu/text/Replaceable;Landroid/icu/text/Transliterator$Position;Ljava/lang/String;)V
 Landroid/icu/text/Transliterator;->transliterate(Ljava/lang/String;)Ljava/lang/String;
 Landroid/icu/text/UFormat;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/UForwardCharacterIterator;->DONE:I
 Landroid/icu/util/Calendar;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
 Landroid/icu/util/PersianCalendar;-><init>(Ljava/util/Locale;)V
 Landroid/icu/util/UResourceBundle;->getBundleInstance(Ljava/lang/String;Landroid/icu/util/ULocale;)Landroid/icu/util/UResourceBundle;
@@ -2624,26 +2355,6 @@
 Landroid/icu/util/UResourceBundle;->getType()I
 Landroid/icu/util/UResourceBundleIterator;->hasNext()Z
 Landroid/icu/util/UResourceBundleIterator;->next()Landroid/icu/util/UResourceBundle;
-Landroid/inputmethodservice/InputMethodService$SettingsObserver;->shouldShowImeWithHardKeyboard()Z
-Landroid/inputmethodservice/InputMethodService;->mExtractEditText:Landroid/inputmethodservice/ExtractEditText;
-Landroid/inputmethodservice/InputMethodService;->mExtractView:Landroid/view/View;
-Landroid/inputmethodservice/InputMethodService;->mRootView:Landroid/view/View;
-Landroid/inputmethodservice/InputMethodService;->mSettingsObserver:Landroid/inputmethodservice/InputMethodService$SettingsObserver;
-Landroid/inputmethodservice/InputMethodService;->mTheme:I
-Landroid/inputmethodservice/InputMethodService;->mTmpInsets:Landroid/inputmethodservice/InputMethodService$Insets;
-Landroid/inputmethodservice/InputMethodService;->onExtractedDeleteText(II)V
-Landroid/inputmethodservice/InputMethodService;->onExtractedReplaceText(IILjava/lang/CharSequence;)V
-Landroid/inputmethodservice/InputMethodService;->onExtractedSetSpan(Ljava/lang/Object;III)V
-Landroid/inputmethodservice/Keyboard;->mModifierKeys:Ljava/util/List;
-Landroid/inputmethodservice/Keyboard;->mTotalHeight:I
-Landroid/inputmethodservice/Keyboard;->mTotalWidth:I
-Landroid/inputmethodservice/Keyboard;->resize(II)V
-Landroid/inputmethodservice/KeyboardView;->mKeyBackground:Landroid/graphics/drawable/Drawable;
-Landroid/inputmethodservice/KeyboardView;->mLabelTextSize:I
-Landroid/inputmethodservice/KeyboardView;->mPreviewText:Landroid/widget/TextView;
-Landroid/inputmethodservice/KeyboardView;->openPopupIfRequired(Landroid/view/MotionEvent;)Z
-Landroid/inputmethodservice/KeyboardView;->repeatKey()Z
-Landroid/inputmethodservice/KeyboardView;->showKey(I)V
 Landroid/location/Country;-><init>(Ljava/lang/String;I)V
 Landroid/location/Country;->getCountryIso()Ljava/lang/String;
 Landroid/location/Country;->getSource()I
@@ -3143,81 +2854,6 @@
 Landroid/media/TimedText;->getObject(I)Ljava/lang/Object;
 Landroid/media/ToneGenerator;->mNativeContext:J
 Landroid/media/TtmlRenderer;-><init>(Landroid/content/Context;)V
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_16_9:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_1_1:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_2_3:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_3_2:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->ASPECT_RATIO_4_3:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->AVAILABILITY_AVAILABLE:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->AVAILABILITY_FREE_WITH_SUBSCRIPTION:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->AVAILABILITY_PAID_CONTENT:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_AUTHOR:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_AVAILABILITY:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_BROWSABLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_CONTENT_ID:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_DURATION_MILLIS:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_INTENT_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_INTERACTION_COUNT:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_INTERACTION_TYPE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_INTERNAL_PROVIDER_ID:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_ITEM_COUNT:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_LAST_PLAYBACK_POSITION_MILLIS:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_LIVE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_LOGO_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_OFFER_PRICE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_POSTER_ART_ASPECT_RATIO:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_PREVIEW_VIDEO_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_RELEASE_DATE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_STARTING_PRICE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_THUMBNAIL_ASPECT_RATIO:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_TRANSIENT:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->COLUMN_TYPE:Ljava/lang/String;
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_FANS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_FOLLOWERS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_LIKES:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_LISTENS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_THUMBS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_VIEWERS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->INTERACTION_TYPE_VIEWS:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_ALBUM:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_ARTIST:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_CHANNEL:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_CLIP:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_EVENT:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_MOVIE:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_PLAYLIST:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_STATION:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_TRACK:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_TV_EPISODE:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_TV_SEASON:I
-Landroid/media/tv/TvContract$PreviewProgramColumns;->TYPE_TV_SERIES:I
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_AUDIO_LANGUAGE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_CANONICAL_GENRE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_CONTENT_RATING:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_EPISODE_DISPLAY_NUMBER:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_EPISODE_TITLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_DATA:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_FLAG1:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_FLAG2:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_FLAG3:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_INTERNAL_PROVIDER_FLAG4:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_LONG_DESCRIPTION:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_POSTER_ART_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_REVIEW_RATING:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_REVIEW_RATING_STYLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SEARCHABLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SEASON_DISPLAY_NUMBER:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SEASON_TITLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SERIES_ID:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SHORT_DESCRIPTION:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_THUMBNAIL_URI:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_TITLE:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_VERSION_NUMBER:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_VIDEO_HEIGHT:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_VIDEO_WIDTH:Ljava/lang/String;
-Landroid/media/tv/TvContract$ProgramColumns;->REVIEW_RATING_STYLE_PERCENTAGE:I
-Landroid/media/tv/TvContract$ProgramColumns;->REVIEW_RATING_STYLE_STARS:I
-Landroid/media/tv/TvContract$ProgramColumns;->REVIEW_RATING_STYLE_THUMBS_UP_DOWN:I
 Landroid/media/tv/TvInputInfo;->getComponent()Landroid/content/ComponentName;
 Landroid/media/tv/TvInputService$Session;->mOverlayFrame:Landroid/graphics/Rect;
 Landroid/media/VolumeShaper$Configuration;-><init>(IIIDI[F[F)V
@@ -3709,28 +3345,6 @@
 Landroid/net/wifi/WifiSsid;->getOctets()[B
 Landroid/net/wifi/WifiSsid;->NONE:Ljava/lang/String;
 Landroid/net/wifi/WifiSsid;->octets:Ljava/io/ByteArrayOutputStream;
-Landroid/nfc/cardemulation/AidGroup;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/nfc/cardemulation/AidGroup;->aids:Ljava/util/List;
-Landroid/nfc/cardemulation/AidGroup;->category:Ljava/lang/String;
-Landroid/nfc/cardemulation/AidGroup;->createFromXml(Lorg/xmlpull/v1/XmlPullParser;)Landroid/nfc/cardemulation/AidGroup;
-Landroid/nfc/cardemulation/AidGroup;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/nfc/cardemulation/AidGroup;->description:Ljava/lang/String;
-Landroid/nfc/cardemulation/AidGroup;->getAids()Ljava/util/List;
-Landroid/nfc/cardemulation/AidGroup;->getCategory()Ljava/lang/String;
-Landroid/nfc/cardemulation/AidGroup;->writeAsXml(Lorg/xmlpull/v1/XmlSerializer;)V
-Landroid/nfc/cardemulation/ApduServiceInfo;-><init>(Landroid/content/pm/PackageManager;Landroid/content/pm/ResolveInfo;Z)V
-Landroid/nfc/cardemulation/ApduServiceInfo;-><init>(Landroid/content/pm/ResolveInfo;ZLjava/lang/String;Ljava/util/ArrayList;Ljava/util/ArrayList;ZIILjava/lang/String;)V
-Landroid/nfc/cardemulation/ApduServiceInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/nfc/cardemulation/ApduServiceInfo;->getDescription()Ljava/lang/String;
-Landroid/nfc/cardemulation/ApduServiceInfo;->getSettingsActivityName()Ljava/lang/String;
-Landroid/nfc/cardemulation/ApduServiceInfo;->getUid()I
-Landroid/nfc/cardemulation/ApduServiceInfo;->isOnHost()Z
-Landroid/nfc/cardemulation/ApduServiceInfo;->loadBanner(Landroid/content/pm/PackageManager;)Landroid/graphics/drawable/Drawable;
-Landroid/nfc/cardemulation/ApduServiceInfo;->mDynamicAidGroups:Ljava/util/HashMap;
-Landroid/nfc/cardemulation/ApduServiceInfo;->mService:Landroid/content/pm/ResolveInfo;
-Landroid/nfc/cardemulation/ApduServiceInfo;->mStaticAidGroups:Ljava/util/HashMap;
-Landroid/nfc/cardemulation/ApduServiceInfo;->requiresUnlock()Z
-Landroid/nfc/ErrorCodes;->isError(I)Z
 Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I
 Landroid/nfc/INfcAdapterExtras;->authenticate(Ljava/lang/String;[B)V
 Landroid/nfc/INfcAdapterExtras;->close(Ljava/lang/String;Landroid/os/IBinder;)Landroid/os/Bundle;
@@ -3739,21 +3353,6 @@
 Landroid/nfc/INfcAdapterExtras;->open(Ljava/lang/String;Landroid/os/IBinder;)Landroid/os/Bundle;
 Landroid/nfc/INfcAdapterExtras;->setCardEmulationRoute(Ljava/lang/String;I)V
 Landroid/nfc/INfcAdapterExtras;->transceive(Ljava/lang/String;[B)Landroid/os/Bundle;
-Landroid/nfc/NdefRecord;->mId:[B
-Landroid/nfc/NfcActivityManager;->mAdapter:Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->attemptDeadServiceRecovery(Ljava/lang/Exception;)V
-Landroid/nfc/NfcAdapter;->getAdapterState()I
-Landroid/nfc/NfcAdapter;->getContext()Landroid/content/Context;
-Landroid/nfc/NfcAdapter;->getDefaultAdapter()Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->getNfcAdapter(Landroid/content/Context;)Landroid/nfc/NfcAdapter;
-Landroid/nfc/NfcAdapter;->getNfcAdapterExtrasInterface()Landroid/nfc/INfcAdapterExtras;
-Landroid/nfc/NfcAdapter;->getService()Landroid/nfc/INfcAdapter;
-Landroid/nfc/NfcAdapter;->setNdefPushMessageCallback(Landroid/nfc/NfcAdapter$CreateNdefMessageCallback;Landroid/app/Activity;I)V
-Landroid/nfc/NfcAdapter;->sService:Landroid/nfc/INfcAdapter;
-Landroid/nfc/NfcManager;-><init>(Landroid/content/Context;)V
-Landroid/nfc/Tag;->getServiceHandle()I
-Landroid/nfc/Tag;->getTagService()Landroid/nfc/INfcTag;
-Landroid/nfc/Tag;->mId:[B
 Landroid/opengl/EGL14;->eglGetDisplay(J)Landroid/opengl/EGLDisplay;
 Landroid/opengl/GLES20;->glGetActiveAttrib(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V
 Landroid/opengl/GLES20;->glGetActiveUniform(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V
@@ -4445,9 +4044,6 @@
 Landroid/provider/CalendarContract$CalendarAlerts;->rescheduleMissedAlarms(Landroid/content/ContentResolver;Landroid/content/Context;Landroid/app/AlarmManager;)V
 Landroid/provider/CalendarContract$CalendarAlerts;->scheduleAlarm(Landroid/content/Context;Landroid/app/AlarmManager;J)V
 Landroid/provider/CallLog$Calls;->addCall(Lcom/android/internal/telephony/CallerInfo;Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIILandroid/telecom/PhoneAccountHandle;JILjava/lang/Long;ZLandroid/os/UserHandle;Z)Landroid/net/Uri;
-Landroid/provider/ContactsContract$ContactCounts;->EXTRA_ADDRESS_BOOK_INDEX:Ljava/lang/String;
-Landroid/provider/ContactsContract$ContactCounts;->EXTRA_ADDRESS_BOOK_INDEX_COUNTS:Ljava/lang/String;
-Landroid/provider/ContactsContract$ContactCounts;->EXTRA_ADDRESS_BOOK_INDEX_TITLES:Ljava/lang/String;
 Landroid/provider/ContactsContract$Contacts$AggregationSuggestions;->builder()Landroid/provider/ContactsContract$Contacts$AggregationSuggestions$Builder;
 Landroid/provider/ContactsContract$Contacts;->CORP_CONTENT_URI:Landroid/net/Uri;
 Landroid/provider/ContactsContract$QuickContact;->composeQuickContactsIntent(Landroid/content/Context;Landroid/graphics/Rect;Landroid/net/Uri;I[Ljava/lang/String;)Landroid/content/Intent;
@@ -4971,7 +4567,7 @@
 Landroid/renderscript/RSSurfaceView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
 Landroid/renderscript/Script$Builder;-><init>(Landroid/renderscript/RenderScript;)V
 Landroid/renderscript/Script$Builder;->mRS:Landroid/renderscript/RenderScript;
-Landroid/security/Credentials;->convertToPem([[Ljava/security/cert/Certificate;)[B
+Landroid/security/Credentials;->convertToPem([Ljava/security/cert/Certificate;)[B
 Landroid/security/Credentials;->getInstance()Landroid/security/Credentials;
 Landroid/security/Credentials;->install(Landroid/content/Context;Ljava/lang/String;[B)V
 Landroid/security/Credentials;->install(Landroid/content/Context;Ljava/security/KeyPair;)V
@@ -5838,21 +5434,6 @@
 Landroid/view/AccessibilityIterators$AbstractTextSegmentIterator;->mText:Ljava/lang/String;
 Landroid/view/ActionProvider;->reset()V
 Landroid/view/ActionProvider;->setSubUiVisibilityListener(Landroid/view/ActionProvider$SubUiVisibilityListener;)V
-Landroid/view/animation/Animation;->detach()V
-Landroid/view/animation/Animation;->getInvalidateRegion(IIIILandroid/graphics/RectF;Landroid/view/animation/Transformation;)V
-Landroid/view/animation/Animation;->initializeInvalidateRegion(IIII)V
-Landroid/view/animation/Animation;->mListener:Landroid/view/animation/Animation$AnimationListener;
-Landroid/view/animation/Animation;->mPreviousRegion:Landroid/graphics/RectF;
-Landroid/view/animation/Animation;->mPreviousTransformation:Landroid/view/animation/Transformation;
-Landroid/view/animation/Animation;->mRegion:Landroid/graphics/RectF;
-Landroid/view/animation/Animation;->mTransformation:Landroid/view/animation/Transformation;
-Landroid/view/animation/AnimationUtils;->createAnimationFromXml(Landroid/content/Context;Lorg/xmlpull/v1/XmlPullParser;Landroid/view/animation/AnimationSet;Landroid/util/AttributeSet;)Landroid/view/animation/Animation;
-Landroid/view/animation/Transformation;->printShortString(Ljava/io/PrintWriter;)V
-Landroid/view/animation/TranslateAnimation;->mFromXValue:F
-Landroid/view/animation/TranslateAnimation;->mFromYValue:F
-Landroid/view/animation/TranslateAnimation;->mToXValue:F
-Landroid/view/animation/TranslateAnimation;->mToYValue:F
-Landroid/view/animation/TranslateYAnimation;-><init>(IFIF)V
 Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/view/autofill/IAutoFillManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/autofill/IAutoFillManager;
 Landroid/view/Choreographer$CallbackQueue;->addCallbackLocked(JLjava/lang/Object;Ljava/lang/Object;)V
@@ -6649,7 +6230,6 @@
 Landroid/webkit/WebResourceResponse;->mImmutable:Z
 Landroid/webkit/WebResourceResponse;->mStatusCode:I
 Landroid/webkit/WebSettings$TextSize;->value:I
-Landroid/webkit/WebSyncManager;->mHandler:Landroid/os/Handler;
 Landroid/webkit/WebSyncManager;->syncFromRamToFlash()V
 Landroid/webkit/WebView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;IILjava/util/Map;Z)V
 Landroid/webkit/WebView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;ILjava/util/Map;Z)V
@@ -7322,73 +6902,6 @@
 Lcom/android/ims/internal/IImsVideoCallCallback;->receiveSessionModifyResponse(ILandroid/telecom/VideoProfile;Landroid/telecom/VideoProfile;)V
 Lcom/android/ims/internal/IImsVideoCallProvider$Stub;-><init>()V
 Lcom/android/ims/internal/IImsVideoCallProvider;->setCallback(Lcom/android/ims/internal/IImsVideoCallCallback;)V
-Lcom/android/ims/internal/uce/common/CapInfo;-><init>()V
-Lcom/android/ims/internal/uce/common/CapInfo;->setCapTimestamp(J)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setCdViaPresenceSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setExts([Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFtHttpSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFtSnFSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFtSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFtThumbSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setFullSnFGroupChatSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setGeoPullFtSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setGeoPullSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setGeoPushSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setImSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setIpVideoSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setIpVoiceSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setIsSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setRcsIpVideoCallSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setRcsIpVideoOnlyCallSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setRcsIpVoiceCallSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setSmSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setSpSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setVsDuringCSSupported(Z)V
-Lcom/android/ims/internal/uce/common/CapInfo;->setVsSupported(Z)V
-Lcom/android/ims/internal/uce/common/StatusCode;-><init>()V
-Lcom/android/ims/internal/uce/common/StatusCode;->setStatusCode(I)V
-Lcom/android/ims/internal/uce/common/UceLong;->getUceLong()J
-Lcom/android/ims/internal/uce/common/UceLong;->setUceLong(J)V
-Lcom/android/ims/internal/uce/presence/PresCmdId;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresCmdId;->setCmdId(I)V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setCmdId(Lcom/android/ims/internal/uce/presence/PresCmdId;)V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setRequestId(I)V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setStatus(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/presence/PresCmdStatus;->setUserData(I)V
-Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresPublishTriggerType;->setPublishTrigeerType(I)V
-Lcom/android/ims/internal/uce/presence/PresResInfo;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresResInfo;->setDisplayName(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInfo;->setInstanceInfo(Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;)V
-Lcom/android/ims/internal/uce/presence/PresResInfo;->setResUri(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setPresentityUri(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setReason(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setResId(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setResInstanceState(I)V
-Lcom/android/ims/internal/uce/presence/PresResInstanceInfo;->setTupleInfo([Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setFullState(Z)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setListName(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setPresSubscriptionState(Lcom/android/ims/internal/uce/presence/PresSubscriptionState;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setRequestId(I)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setSubscriptionExpireTime(I)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setSubscriptionTerminatedReason(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setUri(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresRlmiInfo;->setVersion(I)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setCmdId(Lcom/android/ims/internal/uce/presence/PresCmdId;)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setReasonPhrase(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setRequestId(I)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setRetryAfter(I)V
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->setSipResponseCode(I)V
-Lcom/android/ims/internal/uce/presence/PresSubscriptionState;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresSubscriptionState;->setPresSubscriptionState(I)V
-Lcom/android/ims/internal/uce/presence/PresTupleInfo;-><init>()V
-Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setContactUri(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setFeatureTag(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setTimestamp(Ljava/lang/String;)V
 Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
 Lcom/android/internal/app/AlertController$AlertParams;-><init>(Landroid/content/Context;)V
 Lcom/android/internal/app/AlertController$AlertParams;->apply(Lcom/android/internal/app/AlertController;)V
@@ -8351,6 +7864,7 @@
 Lcom/android/internal/util/AsyncChannel;->sendMessageSynchronously(Landroid/os/Message;)Landroid/os/Message;
 Lcom/android/internal/util/AsyncChannel;->STATUS_SUCCESSFUL:I
 Lcom/android/internal/util/FastPrintWriter;-><init>(Ljava/io/OutputStream;)V
+Lcom/android/internal/util/HexDump;->toHexString([BZ)Ljava/lang/String;
 Lcom/android/internal/util/XmlUtils;->convertValueToBoolean(Ljava/lang/CharSequence;Z)Z
 Lcom/android/internal/util/XmlUtils;->convertValueToInt(Ljava/lang/CharSequence;I)I
 Lcom/android/internal/util/XmlUtils;->readMapXml(Ljava/io/InputStream;)Ljava/util/HashMap;
@@ -8440,6 +7954,7 @@
 Lcom/android/internal/widget/IRemoteViewsFactory;->hasStableIds()Z
 Lcom/android/internal/widget/IRemoteViewsFactory;->isCreated()Z
 Lcom/android/internal/widget/IRemoteViewsFactory;->onDataSetChanged()V
+Lcom/android/internal/widget/ScrollBarUtils;->getThumbLength(IIII)I
 Lcom/android/internal/widget/ScrollingTabContainerView;-><init>(Landroid/content/Context;)V
 Lcom/android/internal/widget/ScrollingTabContainerView;->addTab(Landroid/app/ActionBar$Tab;IZ)V
 Lcom/android/internal/widget/ScrollingTabContainerView;->addTab(Landroid/app/ActionBar$Tab;Z)V
@@ -8511,6 +8026,8 @@
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->setNpnProtocols([B)V
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->setSoWriteTimeout(I)V
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->setUseSessionTickets(Z)V
+Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setHostname(Ljava/lang/String;)V
+Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setUseSessionTickets(Z)V
 Lcom/android/org/conscrypt/ConscryptSocketBase;->getHostname()Ljava/lang/String;
 Lcom/android/org/conscrypt/ConscryptSocketBase;->getHostnameOrIP()Ljava/lang/String;
 Lcom/android/org/conscrypt/ConscryptSocketBase;->getSoWriteTimeout()I
@@ -8980,46 +8497,6 @@
 Ljava/util/zip/Inflater;->len:I
 Ljava/util/zip/Inflater;->needDict:Z
 Ljava/util/zip/Inflater;->off:I
-Ljava/util/zip/ZipConstants;->CENATT:I
-Ljava/util/zip/ZipConstants;->CENATX:I
-Ljava/util/zip/ZipConstants;->CENCOM:I
-Ljava/util/zip/ZipConstants;->CENCRC:I
-Ljava/util/zip/ZipConstants;->CENDSK:I
-Ljava/util/zip/ZipConstants;->CENEXT:I
-Ljava/util/zip/ZipConstants;->CENFLG:I
-Ljava/util/zip/ZipConstants;->CENHDR:I
-Ljava/util/zip/ZipConstants;->CENHOW:I
-Ljava/util/zip/ZipConstants;->CENLEN:I
-Ljava/util/zip/ZipConstants;->CENNAM:I
-Ljava/util/zip/ZipConstants;->CENOFF:I
-Ljava/util/zip/ZipConstants;->CENSIG:J
-Ljava/util/zip/ZipConstants;->CENSIZ:I
-Ljava/util/zip/ZipConstants;->CENTIM:I
-Ljava/util/zip/ZipConstants;->CENVEM:I
-Ljava/util/zip/ZipConstants;->CENVER:I
-Ljava/util/zip/ZipConstants;->ENDCOM:I
-Ljava/util/zip/ZipConstants;->ENDHDR:I
-Ljava/util/zip/ZipConstants;->ENDOFF:I
-Ljava/util/zip/ZipConstants;->ENDSIG:J
-Ljava/util/zip/ZipConstants;->ENDSIZ:I
-Ljava/util/zip/ZipConstants;->ENDSUB:I
-Ljava/util/zip/ZipConstants;->ENDTOT:I
-Ljava/util/zip/ZipConstants;->EXTCRC:I
-Ljava/util/zip/ZipConstants;->EXTHDR:I
-Ljava/util/zip/ZipConstants;->EXTLEN:I
-Ljava/util/zip/ZipConstants;->EXTSIG:J
-Ljava/util/zip/ZipConstants;->EXTSIZ:I
-Ljava/util/zip/ZipConstants;->LOCCRC:I
-Ljava/util/zip/ZipConstants;->LOCEXT:I
-Ljava/util/zip/ZipConstants;->LOCFLG:I
-Ljava/util/zip/ZipConstants;->LOCHDR:I
-Ljava/util/zip/ZipConstants;->LOCHOW:I
-Ljava/util/zip/ZipConstants;->LOCLEN:I
-Ljava/util/zip/ZipConstants;->LOCNAM:I
-Ljava/util/zip/ZipConstants;->LOCSIG:J
-Ljava/util/zip/ZipConstants;->LOCSIZ:I
-Ljava/util/zip/ZipConstants;->LOCTIM:I
-Ljava/util/zip/ZipConstants;->LOCVER:I
 Ljava/util/zip/ZipEntry;-><init>(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V
 Ljava/util/zip/ZipEntry;->method:I
 Ljava/util/zip/ZipFile;->close(J)V
@@ -9034,6 +8511,16 @@
 Ljavax/net/ssl/SSLServerSocketFactory;->defaultServerSocketFactory:Ljavax/net/ssl/SSLServerSocketFactory;
 Ljavax/net/ssl/SSLSocketFactory;->createSocket(Ljava/net/Socket;Ljava/io/InputStream;Z)Ljava/net/Socket;
 Ljavax/net/ssl/SSLSocketFactory;->defaultSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
+Llibcore/icu/ICU;->addLikelySubtags(Ljava/util/Locale;)Ljava/util/Locale;
+Llibcore/io/Memory;->peekByte(J)B
+Llibcore/io/Memory;->peekByteArray(J[BII)V
+Llibcore/io/Memory;->peekInt(JZ)I
+Llibcore/io/Memory;->peekLong(JZ)J
+Llibcore/io/Memory;->pokeByte(JB)V
+Llibcore/io/Memory;->pokeByteArray(J[BII)V
+Llibcore/io/Memory;->pokeInt(JIZ)V
+Llibcore/io/Memory;->pokeLong(JJZ)V
+Llibcore/io/Streams;->copy(Ljava/io/InputStream;Ljava/io/OutputStream;)I
 Llibcore/util/BasicLruCache;->map:Ljava/util/LinkedHashMap;
 Llibcore/util/ZoneInfo;->mTransitions:[J
 Lorg/apache/http/conn/ssl/AbstractVerifier;->BAD_COUNTRY_2LDS:[Ljava/lang/String;
@@ -9056,6 +8543,8 @@
 Lorg/ccil/cowan/tagsoup/ElementType;->theNamespace:Ljava/lang/String;
 Lorg/ccil/cowan/tagsoup/ElementType;->theParent:Lorg/ccil/cowan/tagsoup/ElementType;
 Lorg/ccil/cowan/tagsoup/ElementType;->theSchema:Lorg/ccil/cowan/tagsoup/Schema;
+Lorg/ccil/cowan/tagsoup/HTMLSchema;-><init>()V
+Lorg/ccil/cowan/tagsoup/Parser;-><init>()V
 Lorg/ccil/cowan/tagsoup/Schema;->theElementTypes:Ljava/util/HashMap;
 Lorg/ccil/cowan/tagsoup/Schema;->theEntities:Ljava/util/HashMap;
 Lorg/ccil/cowan/tagsoup/Schema;->thePrefix:Ljava/lang/String;
@@ -9155,10 +8644,84 @@
 Lorg/xml/sax/SAXParseException;->lineNumber:I
 Lorg/xml/sax/SAXParseException;->publicId:Ljava/lang/String;
 Lorg/xml/sax/SAXParseException;->systemId:Ljava/lang/String;
+Lsun/misc/Cleaner;->clean()V
+Lsun/misc/Unsafe;->addressSize()I
+Lsun/misc/Unsafe;->allocateInstance(Ljava/lang/Class;)Ljava/lang/Object;
+Lsun/misc/Unsafe;->allocateMemory(J)J
+Lsun/misc/Unsafe;->arrayBaseOffset(Ljava/lang/Class;)I
+Lsun/misc/Unsafe;->arrayIndexScale(Ljava/lang/Class;)I
+Lsun/misc/Unsafe;->compareAndSwapInt(Ljava/lang/Object;JII)Z
+Lsun/misc/Unsafe;->compareAndSwapLong(Ljava/lang/Object;JJJ)Z
+Lsun/misc/Unsafe;->compareAndSwapObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z
+Lsun/misc/Unsafe;->copyMemory(JJJ)V
+Lsun/misc/Unsafe;->copyMemoryFromPrimitiveArray(Ljava/lang/Object;JJJ)V
+Lsun/misc/Unsafe;->copyMemoryToPrimitiveArray(JLjava/lang/Object;JJ)V
+Lsun/misc/Unsafe;->freeMemory(J)V
+Lsun/misc/Unsafe;->fullFence()V
+Lsun/misc/Unsafe;->getAndAddInt(Ljava/lang/Object;JI)I
+Lsun/misc/Unsafe;->getAndAddLong(Ljava/lang/Object;JJ)J
+Lsun/misc/Unsafe;->getAndSetInt(Ljava/lang/Object;JI)I
+Lsun/misc/Unsafe;->getAndSetLong(Ljava/lang/Object;JJ)J
+Lsun/misc/Unsafe;->getAndSetObject(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;
+Lsun/misc/Unsafe;->getArrayBaseOffsetForComponentType(Ljava/lang/Class;)I
+Lsun/misc/Unsafe;->getArrayIndexScaleForComponentType(Ljava/lang/Class;)I
+Lsun/misc/Unsafe;->getBoolean(Ljava/lang/Object;J)Z
+Lsun/misc/Unsafe;->getByte(J)B
+Lsun/misc/Unsafe;->getByte(Ljava/lang/Object;J)B
+Lsun/misc/Unsafe;->getChar(J)C
+Lsun/misc/Unsafe;->getChar(Ljava/lang/Object;J)C
+Lsun/misc/Unsafe;->getDouble(J)D
+Lsun/misc/Unsafe;->getDouble(Ljava/lang/Object;J)D
+Lsun/misc/Unsafe;->getFloat(J)F
+Lsun/misc/Unsafe;->getFloat(Ljava/lang/Object;J)F
+Lsun/misc/Unsafe;->getInt(J)I
+Lsun/misc/Unsafe;->getInt(Ljava/lang/Object;J)I
+Lsun/misc/Unsafe;->getIntVolatile(Ljava/lang/Object;J)I
+Lsun/misc/Unsafe;->getLong(J)J
+Lsun/misc/Unsafe;->getLong(Ljava/lang/Object;J)J
+Lsun/misc/Unsafe;->getLongVolatile(Ljava/lang/Object;J)J
+Lsun/misc/Unsafe;->getObject(Ljava/lang/Object;J)Ljava/lang/Object;
+Lsun/misc/Unsafe;->getObjectVolatile(Ljava/lang/Object;J)Ljava/lang/Object;
+Lsun/misc/Unsafe;->getShort(J)S
+Lsun/misc/Unsafe;->getShort(Ljava/lang/Object;J)S
+Lsun/misc/Unsafe;->getUnsafe()Lsun/misc/Unsafe;
+Lsun/misc/Unsafe;->INVALID_FIELD_OFFSET:I
+Lsun/misc/Unsafe;->loadFence()V
+Lsun/misc/Unsafe;->objectFieldOffset(Ljava/lang/reflect/Field;)J
+Lsun/misc/Unsafe;->pageSize()I
+Lsun/misc/Unsafe;->park(ZJ)V
+Lsun/misc/Unsafe;->putBoolean(Ljava/lang/Object;JZ)V
+Lsun/misc/Unsafe;->putByte(JB)V
+Lsun/misc/Unsafe;->putByte(Ljava/lang/Object;JB)V
+Lsun/misc/Unsafe;->putChar(JC)V
+Lsun/misc/Unsafe;->putChar(Ljava/lang/Object;JC)V
+Lsun/misc/Unsafe;->putDouble(JD)V
+Lsun/misc/Unsafe;->putDouble(Ljava/lang/Object;JD)V
+Lsun/misc/Unsafe;->putFloat(JF)V
+Lsun/misc/Unsafe;->putFloat(Ljava/lang/Object;JF)V
+Lsun/misc/Unsafe;->putInt(JI)V
+Lsun/misc/Unsafe;->putInt(Ljava/lang/Object;JI)V
+Lsun/misc/Unsafe;->putIntVolatile(Ljava/lang/Object;JI)V
+Lsun/misc/Unsafe;->putLong(JJ)V
+Lsun/misc/Unsafe;->putLong(Ljava/lang/Object;JJ)V
+Lsun/misc/Unsafe;->putLongVolatile(Ljava/lang/Object;JJ)V
+Lsun/misc/Unsafe;->putObject(Ljava/lang/Object;JLjava/lang/Object;)V
+Lsun/misc/Unsafe;->putObjectVolatile(Ljava/lang/Object;JLjava/lang/Object;)V
+Lsun/misc/Unsafe;->putOrderedInt(Ljava/lang/Object;JI)V
+Lsun/misc/Unsafe;->putOrderedLong(Ljava/lang/Object;JJ)V
+Lsun/misc/Unsafe;->putOrderedObject(Ljava/lang/Object;JLjava/lang/Object;)V
+Lsun/misc/Unsafe;->putShort(JS)V
+Lsun/misc/Unsafe;->putShort(Ljava/lang/Object;JS)V
+Lsun/misc/Unsafe;->setMemory(JJB)V
+Lsun/misc/Unsafe;->storeFence()V
 Lsun/misc/Unsafe;->theUnsafe:Lsun/misc/Unsafe;
 Lsun/misc/Unsafe;->THE_ONE:Lsun/misc/Unsafe;
+Lsun/misc/Unsafe;->unpark(Ljava/lang/Object;)V
 Lsun/misc/URLClassPath$JarLoader;->getJarFile()Ljava/util/jar/JarFile;
 Lsun/misc/URLClassPath;->lmap:Ljava/util/HashMap;
 Lsun/misc/URLClassPath;->loaders:Ljava/util/ArrayList;
 Lsun/misc/URLClassPath;->urls:Ljava/util/Stack;
+Lsun/nio/ch/DirectBuffer;->cleaner()Lsun/misc/Cleaner;
+Lsun/security/x509/AlgorithmId;->get(Ljava/lang/String;)Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/AlgorithmId;->getName()Ljava/lang/String;
 Lsun/security/x509/AVA;->hasRFC2253Keyword()Z
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index f1e700b..b8c1468 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -93,10 +93,6 @@
 Landroid/content/pm/IPackageStatsObserver;->onGetStatsCompleted(Landroid/content/pm/PackageStats;Z)V
 Landroid/database/sqlite/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
 Landroid/database/sqlite/SqliteWrapper;->query(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
-Landroid/graphics/Bitmap;->createGraphicBufferHandle()Landroid/graphics/GraphicBuffer;
-Landroid/graphics/Bitmap;->createHardwareBitmap(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;
-Landroid/graphics/drawable/Drawable;->isProjected()Z
-Landroid/graphics/drawable/Drawable;->updateTintFilter(Landroid/graphics/PorterDuffColorFilter;Landroid/content/res/ColorStateList;Landroid/graphics/PorterDuff$Mode;)Landroid/graphics/PorterDuffColorFilter;
 Landroid/hardware/camera2/CaptureRequest$Key;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
 Landroid/hardware/display/DisplayManagerGlobal;->getInstance()Landroid/hardware/display/DisplayManagerGlobal;
 Landroid/hardware/display/DisplayManagerGlobal;->getRealDisplay(I)Landroid/view/Display;
@@ -609,31 +605,6 @@
 Lcom/android/ims/internal/IImsUtListener;->utConfigurationQueryFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V
 Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdated(Lcom/android/ims/internal/IImsUt;I)V
 Lcom/android/ims/internal/IImsUtListener;->utConfigurationUpdateFailed(Lcom/android/ims/internal/IImsUt;ILandroid/telephony/ims/ImsReasonInfo;)V
-Lcom/android/ims/internal/uce/common/CapInfo;->getCapTimestamp()J
-Lcom/android/ims/internal/uce/common/CapInfo;->isCdViaPresenceSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFtHttpSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFtSnFSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFtSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFtThumbSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isFullSnFGroupChatSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isGeoPullFtSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isGeoPullSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isGeoPushSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isImSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isIpVideoSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isIpVoiceSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isIsSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isRcsIpVideoCallSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isRcsIpVideoOnlyCallSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isRcsIpVoiceCallSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isSmSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isSpSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isVsDuringCSSupported()Z
-Lcom/android/ims/internal/uce/common/CapInfo;->isVsSupported()Z
-Lcom/android/ims/internal/uce/common/StatusCode;->getStatusCode()I
-Lcom/android/ims/internal/uce/common/UceLong;-><init>()V
-Lcom/android/ims/internal/uce/common/UceLong;->getClientId()I
-Lcom/android/ims/internal/uce/common/UceLong;->setClientId(I)V
 Lcom/android/ims/internal/uce/options/IOptionsListener;->cmdStatus(Lcom/android/ims/internal/uce/options/OptionsCmdStatus;)V
 Lcom/android/ims/internal/uce/options/IOptionsListener;->getVersionCb(Ljava/lang/String;)V
 Lcom/android/ims/internal/uce/options/IOptionsListener;->incomingOptions(Ljava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;I)V
@@ -649,24 +620,6 @@
 Lcom/android/ims/internal/uce/options/IOptionsService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
 Lcom/android/ims/internal/uce/options/IOptionsService;->responseIncomingOptions(IIILjava/lang/String;Lcom/android/ims/internal/uce/options/OptionsCapInfo;Z)Lcom/android/ims/internal/uce/common/StatusCode;
 Lcom/android/ims/internal/uce/options/IOptionsService;->setMyInfo(ILcom/android/ims/internal/uce/common/CapInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;-><init>()V
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;->getCapInfo()Lcom/android/ims/internal/uce/common/CapInfo;
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;->getSdp()Ljava/lang/String;
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;->setCapInfo(Lcom/android/ims/internal/uce/common/CapInfo;)V
-Lcom/android/ims/internal/uce/options/OptionsCapInfo;->setSdp(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/options/OptionsCmdId;-><init>()V
-Lcom/android/ims/internal/uce/options/OptionsCmdId;->setCmdId(I)V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;-><init>()V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setCapInfo(Lcom/android/ims/internal/uce/common/CapInfo;)V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setCmdId(Lcom/android/ims/internal/uce/options/OptionsCmdId;)V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setStatus(Lcom/android/ims/internal/uce/common/StatusCode;)V
-Lcom/android/ims/internal/uce/options/OptionsCmdStatus;->setUserData(I)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;-><init>()V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setCmdId(Lcom/android/ims/internal/uce/options/OptionsCmdId;)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setReasonPhrase(Ljava/lang/String;)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setRequestId(I)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setRetryAfter(I)V
-Lcom/android/ims/internal/uce/options/OptionsSipResponse;->setSipResponseCode(I)V
 Lcom/android/ims/internal/uce/presence/IPresenceListener;->capInfoReceived(Ljava/lang/String;[Lcom/android/ims/internal/uce/presence/PresTupleInfo;)V
 Lcom/android/ims/internal/uce/presence/IPresenceListener;->cmdStatus(Lcom/android/ims/internal/uce/presence/PresCmdStatus;)V
 Lcom/android/ims/internal/uce/presence/IPresenceListener;->getVersionCb(Ljava/lang/String;)V
@@ -685,18 +638,6 @@
 Lcom/android/ims/internal/uce/presence/IPresenceService;->reenableService(II)Lcom/android/ims/internal/uce/common/StatusCode;
 Lcom/android/ims/internal/uce/presence/IPresenceService;->removeListener(ILcom/android/ims/internal/uce/common/UceLong;)Lcom/android/ims/internal/uce/common/StatusCode;
 Lcom/android/ims/internal/uce/presence/IPresenceService;->setNewFeatureTag(ILjava/lang/String;Lcom/android/ims/internal/uce/presence/PresServiceInfo;I)Lcom/android/ims/internal/uce/common/StatusCode;
-Lcom/android/ims/internal/uce/presence/PresCapInfo;->getCapInfo()Lcom/android/ims/internal/uce/common/CapInfo;
-Lcom/android/ims/internal/uce/presence/PresCapInfo;->getContactUri()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresCapInfo;->mContactUri:Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getMediaType()I
-Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceDesc()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceId()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresServiceInfo;->getServiceVer()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getCmdId()Lcom/android/ims/internal/uce/presence/PresCmdId;
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getReasonPhrase()Ljava/lang/String;
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getRequestId()I
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getRetryAfter()I
-Lcom/android/ims/internal/uce/presence/PresSipResponse;->getSipResponseCode()I
 Lcom/android/ims/internal/uce/uceservice/IUceListener;->setStatus(I)V
 Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V
 Lcom/android/ims/internal/uce/uceservice/IUceService;->createOptionsService(Lcom/android/ims/internal/uce/options/IOptionsListener;Lcom/android/ims/internal/uce/common/UceLong;)I
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 300a530..5b73eaa 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
@@ -442,8 +443,10 @@
 
     private int mConnectionId = AccessibilityInteractionClient.NO_ID;
 
+    @UnsupportedAppUsage
     private AccessibilityServiceInfo mInfo;
 
+    @UnsupportedAppUsage
     private IBinder mWindowToken;
 
     private WindowManager mWindowManager;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index ed684d7..be2e2fa 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
 
 import android.annotation.IntDef;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -695,6 +696,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCapabilities(int capabilities) {
         mCapabilities = capabilities;
     }
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 4ebcc44..17d54d2 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -17,6 +17,7 @@
 package android.animation;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ConstantState;
 
@@ -460,6 +461,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void reverse() {
         throw new IllegalStateException("Reverse is not supported");
     }
diff --git a/core/java/android/animation/ArgbEvaluator.java b/core/java/android/animation/ArgbEvaluator.java
index a96bee6..5b69d18 100644
--- a/core/java/android/animation/ArgbEvaluator.java
+++ b/core/java/android/animation/ArgbEvaluator.java
@@ -16,6 +16,8 @@
 
 package android.animation;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * This evaluator can be used to perform type interpolation between integer
  * values that represent ARGB colors.
@@ -31,6 +33,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static ArgbEvaluator getInstance() {
         return sInstance;
     }
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index 5a23fdd..5b3813d 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -16,6 +16,7 @@
 
 package android.animation;
 
+import android.annotation.UnsupportedAppUsage;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
@@ -1070,6 +1071,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void cancel() {
         if (currentChangingAnimations.size() > 0) {
             LinkedHashMap<View, Animator> currentAnimCopy =
@@ -1105,6 +1107,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void cancel(int transitionType) {
         switch (transitionType) {
             case CHANGE_APPEARING:
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index cc95eb6..a0464df 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -19,6 +19,7 @@
 import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Looper;
 import android.os.Trace;
 import android.util.AndroidRuntimeException;
@@ -75,6 +76,7 @@
     /**
      * Internal constants
      */
+    @UnsupportedAppUsage
     private static float sDurationScale = 1.0f;
 
     /**
@@ -200,6 +202,7 @@
     //
 
     // How long the animation should last in ms
+    @UnsupportedAppUsage
     private long mDuration = 300;
 
     // The amount of time in ms to delay starting the animation after start() is called. Note
@@ -1534,6 +1537,7 @@
      * @param fraction The elapsed fraction of the animation.
      */
     @CallSuper
+    @UnsupportedAppUsage
     void animateValue(float fraction) {
         fraction = mInterpolator.getInterpolation(fraction);
         mCurrentFraction = fraction;
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 3aeef14..4517446 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.app.backup.IBackupCallback;
 import android.app.backup.IBackupManager;
 import android.os.ParcelFileDescriptor;
  
@@ -55,7 +56,7 @@
     void doBackup(in ParcelFileDescriptor oldState,
             in ParcelFileDescriptor data,
             in ParcelFileDescriptor newState,
-            long quotaBytes, int token, IBackupManager callbackBinder, int transportFlags);
+            long quotaBytes, IBackupCallback callbackBinder, int transportFlags);
 
     /**
      * Restore an entire data snapshot to the application.
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index ec2cf0c..097dd9c 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -941,11 +941,13 @@
         private static final String TAG = "BackupServiceBinder";
 
         @Override
-        public void doBackup(ParcelFileDescriptor oldState,
+        public void doBackup(
+                ParcelFileDescriptor oldState,
                 ParcelFileDescriptor data,
                 ParcelFileDescriptor newState,
-                long quotaBytes, int token, IBackupManager callbackBinder, int transportFlags)
-                throws RemoteException {
+                long quotaBytes,
+                IBackupCallback callbackBinder,
+                int transportFlags) throws RemoteException {
             // Ensure that we're running with the app's normal permission level
             long ident = Binder.clearCallingIdentity();
 
@@ -969,7 +971,7 @@
 
                 Binder.restoreCallingIdentity(ident);
                 try {
-                    callbackBinder.opComplete(token, 0);
+                    callbackBinder.operationComplete(0);
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
diff --git a/core/java/android/app/backup/IBackupCallback.aidl b/core/java/android/app/backup/IBackupCallback.aidl
new file mode 100644
index 0000000..9582a58
--- /dev/null
+++ b/core/java/android/app/backup/IBackupCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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.app.backup;
+
+import android.app.backup.IBackupManager;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Callback interface made for responding to one-way calls from the system.
+ *
+ * @hide
+ */
+oneway interface IBackupCallback {
+    void operationComplete(long result);
+}
diff --git a/core/java/android/ddm/DdmHandleAppName.java b/core/java/android/ddm/DdmHandleAppName.java
index 7e39e47..9560787 100644
--- a/core/java/android/ddm/DdmHandleAppName.java
+++ b/core/java/android/ddm/DdmHandleAppName.java
@@ -16,6 +16,7 @@
 
 package android.ddm;
 
+import android.annotation.UnsupportedAppUsage;
 import org.apache.harmony.dalvik.ddmc.Chunk;
 import org.apache.harmony.dalvik.ddmc.ChunkHandler;
 import org.apache.harmony.dalvik.ddmc.DdmServer;
@@ -69,6 +70,7 @@
      * before or after DDMS connects.  For the latter we need to send up
      * an APNM message.
      */
+    @UnsupportedAppUsage
     public static void setAppName(String name, int userId) {
         if (name == null || name.length() == 0)
             return;
@@ -79,6 +81,7 @@
         sendAPNM(name, userId);
     }
 
+    @UnsupportedAppUsage
     public static String getAppName() {
         return mAppName;
     }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 431c651..46671b2 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -28,6 +28,7 @@
 import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
 import android.app.Dialog;
 import android.content.Context;
@@ -343,10 +344,12 @@
 
     InputMethodManager mImm;
     
+    @UnsupportedAppUsage
     int mTheme = 0;
     
     LayoutInflater mInflater;
     TypedArray mThemeAttrs;
+    @UnsupportedAppUsage
     View mRootView;
     SoftInputWindow mWindow;
     boolean mInitialized;
@@ -378,8 +381,10 @@
 
     boolean mFullscreenApplied;
     boolean mIsFullscreen;
+    @UnsupportedAppUsage
     View mExtractView;
     boolean mExtractViewHidden;
+    @UnsupportedAppUsage
     ExtractEditText mExtractEditText;
     ViewGroup mExtractAccessories;
     View mExtractAction;
@@ -402,6 +407,7 @@
      */
     boolean mShouldClearInsetOfPreviousIme;
 
+    @UnsupportedAppUsage
     final Insets mTmpInsets = new Insets();
     final int[] mTmpLocation = new int[2];
 
@@ -811,6 +817,7 @@
             mService.getContentResolver().unregisterContentObserver(this);
         }
 
+        @UnsupportedAppUsage
         private boolean shouldShowImeWithHardKeyboard() {
             // Lazily initialize as needed.
             if (mShowImeWithHardKeyboard == ShowImeWithHardKeyboardType.UNKNOWN) {
@@ -850,6 +857,7 @@
             return "SettingsObserver{mShowImeWithHardKeyboard=" + mShowImeWithHardKeyboard  + "}";
         }
     }
+    @UnsupportedAppUsage
     private SettingsObserver mSettingsObserver;
 
     /**
@@ -2492,6 +2500,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void onExtractedDeleteText(int start, int end) {
         InputConnection conn = getCurrentInputConnection();
         if (conn != null) {
@@ -2504,6 +2513,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void onExtractedReplaceText(int start, int end, CharSequence text) {
         InputConnection conn = getCurrentInputConnection();
         if (conn != null) {
@@ -2515,6 +2525,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void onExtractedSetSpan(Object span, int start, int end, int flags) {
         InputConnection conn = getCurrentInputConnection();
         if (conn != null) {
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index a5490ef..ec5f050 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -18,6 +18,7 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.XmlRes;
 import android.content.Context;
 import android.content.res.Resources;
@@ -110,18 +111,21 @@
     private int mKeyHeight;
     
     /** Total height of the keyboard, including the padding and keys */
+    @UnsupportedAppUsage
     private int mTotalHeight;
     
     /** 
      * Total width of the keyboard, including left side gaps and keys, but not any gaps on the
      * right side.
      */
+    @UnsupportedAppUsage
     private int mTotalWidth;
     
     /** List of keys in this keyboard */
     private List<Key> mKeys;
     
     /** List of modifier keys such as Shift & Alt, if any */
+    @UnsupportedAppUsage
     private List<Key> mModifierKeys;
     
     /** Width of the screen available to fit the keyboard */
@@ -623,6 +627,7 @@
         rows.add(row);
     }
 
+    @UnsupportedAppUsage
     final void resize(int newWidth, int newHeight) {
         int numRows = rows.size();
         for (int rowIndex = 0; rowIndex < numRows; ++rowIndex) {
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 16c1f6d..9ca8049 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -16,6 +16,7 @@
 
 package android.inputmethodservice;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -133,6 +134,7 @@
 
     private Keyboard mKeyboard;
     private int mCurrentKeyIndex = NOT_A_KEY;
+    @UnsupportedAppUsage
     private int mLabelTextSize;
     private int mKeyTextSize;
     private int mKeyTextColor;
@@ -140,6 +142,7 @@
     private int mShadowColor;
     private float mBackgroundDimAmount;
 
+    @UnsupportedAppUsage
     private TextView mPreviewText;
     private PopupWindow mPreviewPopup;
     private int mPreviewTextSizeLarge;
@@ -217,6 +220,7 @@
     private float mOldPointerX;
     private float mOldPointerY;
 
+    @UnsupportedAppUsage
     private Drawable mKeyBackground;
 
     private static final int REPEAT_INTERVAL = 50; // ~20 keys per second
@@ -910,6 +914,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void showKey(final int keyIndex) {
         final PopupWindow previewPopup = mPreviewPopup;
         final Key[] keys = mKeys;
@@ -1052,6 +1057,7 @@
                 key.x + key.width + mPaddingLeft, key.y + key.height + mPaddingTop);
     }
 
+    @UnsupportedAppUsage
     private boolean openPopupIfRequired(MotionEvent me) {
         // Check if we have a popup layout specified first.
         if (mPopupLayout == 0) {
@@ -1357,6 +1363,7 @@
         return true;
     }
 
+    @UnsupportedAppUsage
     private boolean repeatKey() {
         Key key = mKeys[mRepeatKeyIndex];
         detectAndSendKey(mCurrentKey, key.x, key.y, mLastTapTime);
diff --git a/core/java/android/nfc/ErrorCodes.java b/core/java/android/nfc/ErrorCodes.java
index 3adcdc3..98e31ad 100644
--- a/core/java/android/nfc/ErrorCodes.java
+++ b/core/java/android/nfc/ErrorCodes.java
@@ -16,6 +16,8 @@
 
 package android.nfc;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * This class defines all the error codes that can be returned by the service
  * and producing an exception on the application level. These are needed since
@@ -25,6 +27,7 @@
  */
 public class ErrorCodes {
 
+    @UnsupportedAppUsage
     public static boolean isError(int code) {
         if (code < 0) {
             return true;
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 093a9b4..b0090ca 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -16,6 +16,7 @@
 
 package android.nfc;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Parcel;
@@ -279,6 +280,7 @@
 
     private final short mTnf;
     private final byte[] mType;
+    @UnsupportedAppUsage
     private final byte[] mId;
     private final byte[] mPayload;
 
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 958063a..abfa133 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -16,6 +16,7 @@
 
 package android.nfc;
 
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.Application;
 import android.content.ContentProvider;
@@ -45,6 +46,7 @@
     static final String TAG = NfcAdapter.TAG;
     static final Boolean DBG = false;
 
+    @UnsupportedAppUsage
     final NfcAdapter mAdapter;
 
     // All objects in the lists are protected by this
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index c3f23a1..21fed48 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -20,6 +20,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.app.Activity;
 import android.app.ActivityThread;
 import android.app.OnActivityPausedListener;
@@ -325,6 +326,7 @@
     // Final after first constructor, except for
     // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
     // recovery
+    @UnsupportedAppUsage
     static INfcAdapter sService;
     static INfcTag sTagService;
     static INfcCardEmulation sCardEmulationService;
@@ -490,6 +492,7 @@
      * or throws if NFC is not available.
      * @hide
      */
+    @UnsupportedAppUsage
     public static synchronized NfcAdapter getNfcAdapter(Context context) {
         if (!sIsInitialized) {
             sHasNfcFeature = hasNfcFeature();
@@ -593,6 +596,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     public static NfcAdapter getDefaultAdapter() {
         // introduced in API version 9 (GB 2.3)
         // deprecated in API version 10 (GB 2.3.3)
@@ -615,6 +619,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public Context getContext() {
         return mContext;
     }
@@ -623,6 +628,7 @@
      * Returns the binder interface to the service.
      * @hide
      */
+    @UnsupportedAppUsage
     public INfcAdapter getService() {
         isEnabled();  // NOP call to recover sService if it is stale
         return sService;
@@ -676,6 +682,7 @@
      * NFC service dead - attempt best effort recovery
      * @hide
      */
+    @UnsupportedAppUsage
     public void attemptDeadServiceRecovery(Exception e) {
         Log.e(TAG, "NFC service dead - attempting to recover", e);
         INfcAdapter service = getServiceInterface();
@@ -746,6 +753,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public int getAdapterState() {
         try {
             return sService.getState();
@@ -1227,6 +1235,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
             int flags) {
         if (activity == null) {
@@ -1862,6 +1871,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public INfcAdapterExtras getNfcAdapterExtrasInterface() {
         if (mContext == null) {
             throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java
index 50d6745..71199c9 100644
--- a/core/java/android/nfc/NfcManager.java
+++ b/core/java/android/nfc/NfcManager.java
@@ -17,6 +17,7 @@
 package android.nfc;
 
 import android.annotation.SystemService;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 
 /**
@@ -44,6 +45,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public NfcManager(Context context) {
         NfcAdapter adapter;
         context = context.getApplicationContext();
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 154d5a1..ce684cf 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -16,6 +16,7 @@
 
 package android.nfc;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.nfc.tech.IsoDep;
 import android.nfc.tech.MifareClassic;
@@ -110,6 +111,7 @@
  * <p>
  */
 public final class Tag implements Parcelable {
+    @UnsupportedAppUsage
     final byte[] mId;
     final int[] mTechList;
     final String[] mTechStringList;
@@ -235,6 +237,7 @@
      * For use by NfcService only.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getServiceHandle() {
         return mServiceHandle;
     }
@@ -355,6 +358,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public INfcTag getTagService() {
         return mTagService;
     }
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
index 78a9401..63776c4 100644
--- a/core/java/android/nfc/cardemulation/AidGroup.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -24,6 +24,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -45,8 +46,11 @@
 
     static final String TAG = "AidGroup";
 
+    @UnsupportedAppUsage
     final List<String> aids;
+    @UnsupportedAppUsage
     final String category;
+    @UnsupportedAppUsage
     final String description;
 
     /**
@@ -79,6 +83,7 @@
         this.description = null;
     }
 
+    @UnsupportedAppUsage
     AidGroup(String category, String description) {
         this.aids = new ArrayList<String>();
         this.category = category;
@@ -88,6 +93,7 @@
     /**
      * @return the category of this AID group
      */
+    @UnsupportedAppUsage
     public String getCategory() {
         return category;
     }
@@ -95,6 +101,7 @@
     /**
      * @return the list of AIDs in this group
      */
+    @UnsupportedAppUsage
     public List<String> getAids() {
         return aids;
     }
@@ -124,6 +131,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<AidGroup> CREATOR =
             new Parcelable.Creator<AidGroup>() {
 
@@ -144,6 +152,7 @@
         }
     };
 
+    @UnsupportedAppUsage
     static public AidGroup createFromXml(XmlPullParser parser) throws XmlPullParserException, IOException {
         String category = null;
         ArrayList<String> aids = new ArrayList<String>();
@@ -185,6 +194,7 @@
         return group;
     }
 
+    @UnsupportedAppUsage
     public void writeAsXml(XmlSerializer out) throws IOException {
         out.startTag(null, "aid-group");
         out.attribute(null, "category", category);
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 218e4f2..e8d801c 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -16,6 +16,7 @@
 
 package android.nfc.cardemulation;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -54,6 +55,7 @@
     /**
      * The service that implements this
      */
+    @UnsupportedAppUsage
     final ResolveInfo mService;
 
     /**
@@ -69,11 +71,13 @@
     /**
      * Mapping from category to static AID group
      */
+    @UnsupportedAppUsage
     final HashMap<String, AidGroup> mStaticAidGroups;
 
     /**
      * Mapping from category to dynamic AID group
      */
+    @UnsupportedAppUsage
     final HashMap<String, AidGroup> mDynamicAidGroups;
 
     /**
@@ -99,6 +103,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
             ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
             boolean requiresUnlock, int bannerResource, int uid,
@@ -120,6 +125,7 @@
         this.mSettingsActivityName = settingsActivityName;
     }
 
+    @UnsupportedAppUsage
     public ApduServiceInfo(PackageManager pm, ResolveInfo info, boolean onHost) throws
             XmlPullParserException, IOException {
         ServiceInfo si = info.serviceInfo;
@@ -374,18 +380,22 @@
         return (mStaticAidGroups.containsKey(category) || mDynamicAidGroups.containsKey(category));
     }
 
+    @UnsupportedAppUsage
     public boolean isOnHost() {
         return mOnHost;
     }
 
+    @UnsupportedAppUsage
     public boolean requiresUnlock() {
         return mRequiresDeviceUnlock;
     }
 
+    @UnsupportedAppUsage
     public String getDescription() {
         return mDescription;
     }
 
+    @UnsupportedAppUsage
     public int getUid() {
         return mUid;
     }
@@ -411,6 +421,7 @@
         return mService.loadIcon(pm);
     }
 
+    @UnsupportedAppUsage
     public Drawable loadBanner(PackageManager pm) {
         Resources res;
         try {
@@ -426,6 +437,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public String getSettingsActivityName() { return mSettingsActivityName; }
 
     @Override
@@ -483,6 +495,7 @@
         dest.writeString(mSettingsActivityName);
     };
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<ApduServiceInfo> CREATOR =
             new Parcelable.Creator<ApduServiceInfo>() {
         @Override
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f4f43e3..6cf67de 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9217,6 +9217,19 @@
        /** {@hide} */
        public static final String STORAGE_BENCHMARK_INTERVAL = "storage_benchmark_interval";
 
+        /**
+         * Whether or not Settings should enable psd API.
+         * {@hide}
+         */
+        public static final String SETTINGS_USE_PSD_API = "settings_use_psd_api";
+
+        /**
+         * Whether or not Settings should enable external provider API.
+         * {@hide}
+         */
+        public static final String SETTINGS_USE_EXTERNAL_PROVIDER_API =
+                "settings_use_external_provider_api";
+
        /**
         * Sample validity in seconds to configure for the system DNS resolver.
         * {@hide}
@@ -9824,6 +9837,18 @@
                 "recommended_network_evaluator_cache_expiry_ms";
 
         /**
+         * Whether wifi scan throttle is enabled or not.
+         * This is intended to be used via adb commands or a menu in developer option to turn off
+         * the default wifi scan throttling mechanism for apps.
+         *
+         * Type: int (0 for false, 1 for true)
+         * @hide
+         */
+        public static final String WIFI_SCAN_THROTTLE_ENABLED = "wifi_scan_throttle_enabled";
+
+        private static final Validator WIFI_SCAN_THROTTLE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
         * Settings to allow BLE scans to be enabled even when Bluetooth is turned off for
         * connectivity.
         * @hide
@@ -12315,6 +12340,7 @@
             VALIDATORS.put(SOFT_AP_TIMEOUT_ENABLED, SOFT_AP_TIMEOUT_ENABLED_VALIDATOR);
             VALIDATORS.put(WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON,
                     WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR);
+            VALIDATORS.put(WIFI_SCAN_THROTTLE_ENABLED, WIFI_SCAN_THROTTLE_ENABLED_VALIDATOR);
             VALIDATORS.put(APP_AUTO_RESTRICTION_ENABLED, APP_AUTO_RESTRICTION_ENABLED_VALIDATOR);
             VALIDATORS.put(ZEN_DURATION, ZEN_DURATION_VALIDATOR);
             VALIDATORS.put(CHARGING_VIBRATION_ENABLED, CHARGING_VIBRATION_ENABLED_VALIDATOR);
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
index 1cd76d2..e5e1c92 100644
--- a/core/java/android/service/autofill/AutofillFieldClassificationService.java
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -65,16 +65,36 @@
     /**
      * Manifest metadata key for the resource string containing the name of the default field
      * classification algorithm.
+     *
+     * @deprecated Use {@link #RESOURCE_DEFAULT_ALGORITHM} instead.
      */
+    @Deprecated
     public static final String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM =
             "android.autofill.field_classification.default_algorithm";
+
     /**
      * Manifest metadata key for the resource string array containing the names of all field
      * classification algorithms provided by the service.
+     *
+     * @deprecated Use {@link #RESOURCE_AVAILABLE_ALGORITHMS} instead.
      */
+    @Deprecated
     public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS =
             "android.autofill.field_classification.available_algorithms";
 
+    /**
+     * Name of the resource string containing the name of the default field
+     * classification algorithm.
+     */
+    public static final String RESOURCE_DEFAULT_ALGORITHM =
+            "autofill_field_classification_default_algorithm";
+
+   /**
+    * Name of the resource string array containing the names of all field
+    * classification algorithms provided by the service.
+    */
+    public static final String RESOURCE_AVAILABLE_ALGORITHMS =
+            "autofill_field_classification_available_algorithms";
 
     /** {@hide} **/
     public static final String EXTRA_SCORES = "scores";
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 0d94af4..e0c354a 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -71,6 +71,12 @@
     public static final String KEY_SMART_ACTIONS = "key_smart_actions";
 
     /**
+     * Data type: ArrayList of {@link CharSequence}.
+     * Used to suggest smart replies for a notification.
+     */
+    public static final String KEY_SMART_REPLIES = "key_smart_replies";
+
+    /**
      * Create a notification adjustment.
      *
      * @param pkg The package of the notification.
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 09425a9..09eecd8 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1427,6 +1427,7 @@
         private @UserSentiment int mUserSentiment = USER_SENTIMENT_NEUTRAL;
         private boolean mHidden;
         private ArrayList<Notification.Action> mSmartActions;
+        private ArrayList<CharSequence> mSmartReplies;
 
         public Ranking() {}
 
@@ -1564,6 +1565,13 @@
         }
 
         /**
+         * @hide
+         */
+        public List<CharSequence> getSmartReplies() {
+            return mSmartReplies;
+        }
+
+        /**
          * Returns whether this notification can be displayed as a badge.
          *
          * @return true if the notification can be displayed as a badge, false otherwise.
@@ -1591,7 +1599,8 @@
                 CharSequence explanation, String overrideGroupKey,
                 NotificationChannel channel, ArrayList<String> overridePeople,
                 ArrayList<SnoozeCriterion> snoozeCriteria, boolean showBadge,
-                int userSentiment, boolean hidden, ArrayList<Notification.Action> smartActions) {
+                int userSentiment, boolean hidden, ArrayList<Notification.Action> smartActions,
+                ArrayList<CharSequence> smartReplies) {
             mKey = key;
             mRank = rank;
             mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
@@ -1608,6 +1617,7 @@
             mUserSentiment = userSentiment;
             mHidden = hidden;
             mSmartActions = smartActions;
+            mSmartReplies = smartReplies;
         }
 
         /**
@@ -1658,6 +1668,7 @@
         private ArrayMap<String, Integer> mUserSentiment;
         private ArrayMap<String, Boolean> mHidden;
         private ArrayMap<String, ArrayList<Notification.Action>> mSmartActions;
+        private ArrayMap<String, ArrayList<CharSequence>> mSmartReplies;
 
         private RankingMap(NotificationRankingUpdate rankingUpdate) {
             mRankingUpdate = rankingUpdate;
@@ -1686,7 +1697,8 @@
                     getVisibilityOverride(key), getSuppressedVisualEffects(key),
                     getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key),
                     getChannel(key), getOverridePeople(key), getSnoozeCriteria(key),
-                    getShowBadge(key), getUserSentiment(key), getHidden(key), getSmartActions(key));
+                    getShowBadge(key), getUserSentiment(key), getHidden(key), getSmartActions(key),
+                    getSmartReplies(key));
             return rank >= 0;
         }
 
@@ -1833,6 +1845,15 @@
             return mSmartActions.get(key);
         }
 
+        private ArrayList<CharSequence> getSmartReplies(String key) {
+            synchronized (this) {
+                if (mSmartReplies == null) {
+                    buildSmartReplies();
+                }
+            }
+            return mSmartReplies.get(key);
+        }
+
         // Locked by 'this'
         private void buildRanksLocked() {
             String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -1959,6 +1980,15 @@
             }
         }
 
+        // Locked by 'this'
+        private void buildSmartReplies() {
+            Bundle smartReplies = mRankingUpdate.getSmartReplies();
+            mSmartReplies = new ArrayMap<>(smartReplies.size());
+            for (String key : smartReplies.keySet()) {
+                mSmartReplies.put(key, smartReplies.getCharSequenceArrayList(key));
+            }
+        }
+
         // ----------- Parcelable
 
         @Override
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index bed22149..c67fad0 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -38,12 +38,14 @@
     private final Bundle mUserSentiment;
     private final Bundle mHidden;
     private final Bundle mSmartActions;
+    private final Bundle mSmartReplies;
 
     public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
             Bundle visibilityOverrides, Bundle suppressedVisualEffects,
             int[] importance, Bundle explanation, Bundle overrideGroupKeys,
             Bundle channels, Bundle overridePeople, Bundle snoozeCriteria,
-            Bundle showBadge, Bundle userSentiment, Bundle hidden, Bundle smartActions) {
+            Bundle showBadge, Bundle userSentiment, Bundle hidden, Bundle smartActions,
+            Bundle smartReplies) {
         mKeys = keys;
         mInterceptedKeys = interceptedKeys;
         mVisibilityOverrides = visibilityOverrides;
@@ -58,6 +60,7 @@
         mUserSentiment = userSentiment;
         mHidden = hidden;
         mSmartActions = smartActions;
+        mSmartReplies = smartReplies;
     }
 
     public NotificationRankingUpdate(Parcel in) {
@@ -76,6 +79,7 @@
         mUserSentiment = in.readBundle();
         mHidden = in.readBundle();
         mSmartActions = in.readBundle();
+        mSmartReplies = in.readBundle();
     }
 
     @Override
@@ -99,6 +103,7 @@
         out.writeBundle(mUserSentiment);
         out.writeBundle(mHidden);
         out.writeBundle(mSmartActions);
+        out.writeBundle(mSmartReplies);
     }
 
     public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -167,4 +172,8 @@
     public Bundle getSmartActions() {
         return mSmartActions;
     }
+
+    public Bundle getSmartReplies() {
+        return mSmartReplies;
+    }
 }
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 2499afb..1b063e1 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -380,8 +380,8 @@
     /** @hide */ public static final int LOG_ID_SYSTEM = 3;
     /** @hide */ public static final int LOG_ID_CRASH = 4;
 
-    /** @hide */ public static native int println_native(int bufID,
-            int priority, String tag, String msg);
+    /** @hide */
+    public static native int println_native(int bufID, int priority, String tag, String msg);
 
     /**
      * Return the maximum payload the log daemon accepts without truncation.
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index b3400ef..af18caa 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -22,32 +22,34 @@
 import libcore.util.EmptyArray;
 
 /**
- * SparseArrays map integers to Objects.  Unlike a normal array of Objects,
- * there can be gaps in the indices.  It is intended to be more memory efficient
- * than using a HashMap to map Integers to Objects, both because it avoids
+ * <code>SparseArray</code> maps integers to Objects and, unlike a normal array of Objects,
+ * its indices can contain gaps. <code>SparseArray</code> is intended to be more memory-efficient
+ * than a
+ * <a href="/reference/java/util/HashMap"><code>HashMap</code></a>, because it avoids
  * auto-boxing keys and its data structure doesn't rely on an extra entry object
  * for each mapping.
  *
  * <p>Note that this container keeps its mappings in an array data structure,
- * using a binary search to find keys.  The implementation is not intended to be appropriate for
+ * using a binary search to find keys. The implementation is not intended to be appropriate for
  * data structures
- * that may contain large numbers of items.  It is generally slower than a traditional
- * HashMap, since lookups require a binary search and adds and removes require inserting
- * and deleting entries in the array.  For containers holding up to hundreds of items,
- * the performance difference is not significant, less than 50%.</p>
+ * that may contain large numbers of items. It is generally slower than a
+ * <code>HashMap</code> because lookups require a binary search,
+ * and adds and removes require inserting
+ * and deleting entries in the array. For containers holding up to hundreds of items,
+ * the performance difference is less than 50%.
  *
  * <p>To help with performance, the container includes an optimization when removing
  * keys: instead of compacting its array immediately, it leaves the removed entry marked
- * as deleted.  The entry can then be re-used for the same key, or compacted later in
- * a single garbage collection step of all removed entries.  This garbage collection will
- * need to be performed at any time the array needs to be grown or the the map size or
- * entry values are retrieved.</p>
+ * as deleted. The entry can then be re-used for the same key or compacted later in
+ * a single garbage collection of all removed entries. This garbage collection
+ * must be performed whenever the array needs to be grown, or when the map size or
+ * entry values are retrieved.
  *
  * <p>It is possible to iterate over the items in this container using
  * {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
- * <code>keyAt(int)</code> with ascending values of the index will return the
- * keys in ascending order, or the values corresponding to the keys in ascending
- * order in the case of <code>valueAt(int)</code>.</p>
+ * <code>keyAt(int)</code> with ascending values of the index returns the
+ * keys in ascending order. In the case of <code>valueAt(int)</code>, the
+ * values corresponding to the keys are returned in ascending order.
  */
 public class SparseArray<E> implements Cloneable {
     private static final Object DELETED = new Object();
@@ -333,7 +335,7 @@
 
     /**
      * Returns an index for which {@link #valueAt} would return the
-     * specified key, or a negative number if no keys map to the
+     * specified value, or a negative number if no keys map to the
      * specified value.
      * <p>Beware that this is a linear search, unlike lookups by key,
      * and that multiple keys can map to the same value and this will
@@ -357,7 +359,7 @@
 
     /**
      * Returns an index for which {@link #valueAt} would return the
-     * specified key, or a negative number if no keys map to the
+     * specified value, or a negative number if no keys map to the
      * specified value.
      * <p>Beware that this is a linear search, unlike lookups by key,
      * and that multiple keys can map to the same value and this will
diff --git a/core/java/android/view/RecordingCanvas.java b/core/java/android/view/RecordingCanvas.java
index 74fa9e8..3364483 100644
--- a/core/java/android/view/RecordingCanvas.java
+++ b/core/java/android/view/RecordingCanvas.java
@@ -536,9 +536,6 @@
             @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset,
             int indexCount, @NonNull Paint paint) {
         checkRange(verts.length, vertOffset, vertexCount);
-        if (isHardwareAccelerated()) {
-            return;
-        }
         if (texs != null) {
             checkRange(texs.length, texOffset, vertexCount);
         }
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 64686dd..87b7b05 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -19,6 +19,7 @@
 import android.annotation.AnimRes;
 import android.annotation.ColorInt;
 import android.annotation.InterpolatorRes;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.RectF;
@@ -183,6 +184,7 @@
     /**
      * The animation listener to be notified when the animation starts, ends or repeats.
      */
+    @UnsupportedAppUsage
     AnimationListener mListener;
 
     /**
@@ -211,9 +213,13 @@
     private boolean mMore = true;
     private boolean mOneMoreTime = true;
 
+    @UnsupportedAppUsage
     RectF mPreviousRegion = new RectF();
+    @UnsupportedAppUsage
     RectF mRegion = new RectF();
+    @UnsupportedAppUsage
     Transformation mTransformation = new Transformation();
+    @UnsupportedAppUsage
     Transformation mPreviousTransformation = new Transformation();
 
     private final CloseGuard guard = CloseGuard.get();
@@ -322,6 +328,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public void detach() {
         if (mStarted && !mEnded) {
             mEnded = true;
@@ -1046,6 +1053,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void getInvalidateRegion(int left, int top, int right, int bottom,
             RectF invalidate, Transformation transformation) {
 
@@ -1077,6 +1085,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void initializeInvalidateRegion(int left, int top, int right, int bottom) {
         final RectF region = mPreviousRegion;
         region.set(left, top, right, bottom);
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 29f8442..c877b9c 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -19,6 +19,7 @@
 import android.annotation.AnimRes;
 import android.annotation.InterpolatorRes;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
@@ -157,6 +158,7 @@
         return createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser));
     }
 
+    @UnsupportedAppUsage
     private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
             AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
 
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
index 8eb5b5c..58da04d 100644
--- a/core/java/android/view/animation/Transformation.java
+++ b/core/java/android/view/animation/Transformation.java
@@ -17,6 +17,7 @@
 package android.view.animation;
 
 import android.annotation.FloatRange;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 
@@ -238,6 +239,7 @@
      * Print short string, to optimize dumping.
      * @hide
      */
+    @UnsupportedAppUsage
     public void printShortString(PrintWriter pw) {
         pw.print("{alpha="); pw.print(mAlpha);
         pw.print(" matrix=");
diff --git a/core/java/android/view/animation/TranslateAnimation.java b/core/java/android/view/animation/TranslateAnimation.java
index 216022b..6c040d4 100644
--- a/core/java/android/view/animation/TranslateAnimation.java
+++ b/core/java/android/view/animation/TranslateAnimation.java
@@ -16,6 +16,7 @@
 
 package android.view.animation;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -34,13 +35,17 @@
     private int mToYType = ABSOLUTE;
 
     /** @hide */
+    @UnsupportedAppUsage
     protected float mFromXValue = 0.0f;
     /** @hide */
+    @UnsupportedAppUsage
     protected float mToXValue = 0.0f;
 
     /** @hide */
+    @UnsupportedAppUsage
     protected float mFromYValue = 0.0f;
     /** @hide */
+    @UnsupportedAppUsage
     protected float mToYValue = 0.0f;
 
     /** @hide */
diff --git a/core/java/android/view/animation/TranslateYAnimation.java b/core/java/android/view/animation/TranslateYAnimation.java
index 714558d..a6e0ccb 100644
--- a/core/java/android/view/animation/TranslateYAnimation.java
+++ b/core/java/android/view/animation/TranslateYAnimation.java
@@ -16,6 +16,7 @@
 
 package android.view.animation;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Matrix;
 
 /**
@@ -38,6 +39,7 @@
     /**
      * Constructor. Passes in 0 for the x parameters of TranslateAnimation
      */
+    @UnsupportedAppUsage
     public TranslateYAnimation(int fromYType, float fromYValue, int toYType, float toYValue) {
         super(ABSOLUTE, 0, ABSOLUTE, 0, fromYType, fromYValue, toYType, toYValue);
     }
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index b5c7364..32b2f63 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1405,7 +1405,8 @@
         final SyncResultReceiver receiver = new SyncResultReceiver();
         try {
             mService.getAvailableFieldClassificationAlgorithms(receiver);
-            final String[] algorithms = receiver.getObjectResult(SyncResultReceiver.TYPE_STRING);
+            final String[] algorithms = receiver
+                    .getObjectResult(SyncResultReceiver.TYPE_STRING_ARRAY);
             return algorithms != null ? Arrays.asList(algorithms) : Collections.emptyList();
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
@@ -2906,7 +2907,7 @@
                 case TYPE_STRING:
                     return (T) mBundle.getString(EXTRA);
                 case TYPE_STRING_ARRAY:
-                    return (T) mBundle.getString(EXTRA);
+                    return (T) mBundle.getStringArray(EXTRA);
                 case TYPE_PARCELABLE:
                     return (T) mBundle.getParcelable(EXTRA);
                 default:
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 9685f75..943c8bd 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -25,6 +25,7 @@
 import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Slog;
+import android.util.SparseLongArray;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
@@ -62,8 +63,6 @@
 
 import java.io.PrintWriter;
 import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
 
 public final class ProcessState {
     private static final String TAG = "ProcessStats";
@@ -127,6 +126,7 @@
     private final long mVersion;
     private final DurationsTable mDurations;
     private final PssTable mPssTable;
+    private final long[] mTotalRunningPss = new long[ProcessStats.PSS_COUNT];
 
     private ProcessState mCommonProcess;
     private int mCurCombinedState = STATE_NOTHING;
@@ -135,6 +135,9 @@
     private int mLastPssState = STATE_NOTHING;
     private long mLastPssTime;
 
+    private long mTotalRunningStartTime;
+    private long mTotalRunningDuration;
+
     private boolean mActive;
     private int mNumActiveServices;
     private int mNumStartedServices;
@@ -182,6 +185,9 @@
         mVersion = vers;
         mCurCombinedState = commonProcess.mCurCombinedState;
         mStartTime = now;
+        if (mCurCombinedState != STATE_NOTHING) {
+            mTotalRunningStartTime = now;
+        }
         mDurations = new DurationsTable(commonProcess.mStats.mTableData);
         mPssTable = new PssTable(commonProcess.mStats.mTableData);
     }
@@ -190,6 +196,8 @@
         ProcessState pnew = new ProcessState(this, mPackage, mUid, mVersion, mName, now);
         pnew.mDurations.addDurations(mDurations);
         pnew.mPssTable.copyFrom(mPssTable, PSS_COUNT);
+        System.arraycopy(mTotalRunningPss, 0, pnew.mTotalRunningPss, 0, ProcessStats.PSS_COUNT);
+        pnew.mTotalRunningDuration = getTotalRunningDuration(now);
         pnew.mNumExcessiveCpu = mNumExcessiveCpu;
         pnew.mNumCachedKill = mNumCachedKill;
         pnew.mMinCachedKillPss = mMinCachedKillPss;
@@ -235,7 +243,7 @@
     public void setMultiPackage(boolean val) {
         mMultiPackage = val;
     }
-    
+
     public int getDurationsBucketCount() {
         return mDurations.getKeyCount();
     }
@@ -243,6 +251,10 @@
     public void add(ProcessState other) {
         mDurations.addDurations(other.mDurations);
         mPssTable.mergeStats(other.mPssTable);
+        // Note that we don't touch mTotalRunningPss, because in current use
+        // 'other' is older stats that are being added in to these newer ones.
+        // So the newer ones keep track of the total running time, which is always
+        // the right thing over whatever was in older stats.
         mNumExcessiveCpu += other.mNumExcessiveCpu;
         if (other.mNumCachedKill > 0) {
             addCachedKill(other.mNumCachedKill, other.mMinCachedKillPss,
@@ -277,6 +289,10 @@
         out.writeInt(mMultiPackage ? 1 : 0);
         mDurations.writeToParcel(out);
         mPssTable.writeToParcel(out);
+        for (int i = 0; i < ProcessStats.PSS_COUNT; i++) {
+            out.writeLong(mTotalRunningPss[i]);
+        }
+        out.writeLong(getTotalRunningDuration(now));
         out.writeInt(0);  // was mNumExcessiveWake
         out.writeInt(mNumExcessiveCpu);
         out.writeInt(mNumCachedKill);
@@ -300,6 +316,10 @@
         if (!mPssTable.readFromParcel(in)) {
             return false;
         }
+        for (int i = 0; i < ProcessStats.PSS_COUNT; i++) {
+            mTotalRunningPss[i] = in.readLong();
+        }
+        mTotalRunningDuration = in.readLong();
         in.readInt(); // was mNumExcessiveWake
         mNumExcessiveCpu = in.readInt();
         mNumCachedKill = in.readInt();
@@ -334,7 +354,8 @@
     public boolean hasAnyData() {
         return !(mDurations.getKeyCount() == 0
                 && mCurCombinedState == STATE_NOTHING
-                && mPssTable.getKeyCount() == 0);
+                && mPssTable.getKeyCount() == 0
+                && mTotalRunningPss[PSS_SAMPLE_COUNT] == 0);
     }
 
     /**
@@ -374,6 +395,19 @@
         if (!mDead && (mCurCombinedState != state)) {
             //Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
             commitStateTime(now);
+            if (state == STATE_NOTHING) {
+                // We are transitioning to a no longer running state... stop counting run time.
+                mTotalRunningDuration += now - mTotalRunningStartTime;
+                mTotalRunningStartTime = 0;
+            } else if (mCurCombinedState == STATE_NOTHING) {
+                // We previously weren't running...  now starting again, clear out total
+                // running info.
+                mTotalRunningDuration = 0;
+                mTotalRunningStartTime = now;
+                for (int i = ProcessStats.PSS_COUNT - 1; i >= 0; i--) {
+                    mTotalRunningPss[i] = 0;
+                }
+            }
             mCurCombinedState = state;
         }
     }
@@ -388,6 +422,8 @@
             if (dur > 0) {
                 mDurations.addDuration(mCurCombinedState, dur);
             }
+            mTotalRunningDuration += now - mTotalRunningStartTime;
+            mTotalRunningStartTime = now;
         }
         mStartTime = now;
     }
@@ -496,6 +532,8 @@
             // First update the common process.
             mCommonProcess.mPssTable.mergeStats(mCurCombinedState, 1, pss, pss, pss, uss, uss, uss,
                     rss, rss, rss);
+            PssTable.mergeStats(mCommonProcess.mTotalRunningPss, 0, 1, pss, pss, pss, uss, uss, uss,
+                    rss, rss, rss);
 
             // If the common process is not multi-package, there is nothing else to do.
             if (!mCommonProcess.mMultiPackage) {
@@ -504,7 +542,10 @@
 
             if (pkgList != null) {
                 for (int ip=pkgList.size()-1; ip>=0; ip--) {
-                    pullFixedProc(pkgList, ip).mPssTable.mergeStats(mCurCombinedState, 1,
+                    ProcessState fixedProc = pullFixedProc(pkgList, ip);
+                    fixedProc.mPssTable.mergeStats(mCurCombinedState, 1,
+                            pss, pss, pss, uss, uss, uss, rss, rss, rss);
+                    PssTable.mergeStats(fixedProc.mTotalRunningPss, 0, 1,
                             pss, pss, pss, uss, uss, uss, rss, rss, rss);
                 }
             }
@@ -621,6 +662,11 @@
         return proc;
     }
 
+    public long getTotalRunningDuration(long now) {
+        return mTotalRunningDuration +
+                (mTotalRunningStartTime != 0 ? (now - mTotalRunningStartTime) : 0);
+    }
+
     public long getDuration(int state, long now) {
         long time = mDurations.getValueForId((byte)state);
         if (mCurCombinedState == state) {
@@ -671,7 +717,7 @@
 
     /**
      * Sums up the PSS data and adds it to 'data'.
-     * 
+     *
      * @param data The aggregate data is added here.
      * @param now SystemClock.uptimeMillis()
      */
@@ -834,6 +880,7 @@
                     String running = "";
                     if (mCurCombinedState == bucket) {
                         running = " (running)";
+                        time += now - mStartTime;
                     }
                     if (time != 0) {
                         pw.print(prefix);
@@ -870,7 +917,7 @@
     }
 
     public void dumpPss(PrintWriter pw, String prefix,
-            int[] screenStates, int[] memStates, int[] procStates) {
+            int[] screenStates, int[] memStates, int[] procStates, long now) {
         boolean printedHeader = false;
         int printedScreen = -1;
         for (int is=0; is<screenStates.length; is++) {
@@ -880,52 +927,51 @@
                     final int iscreen = screenStates[is];
                     final int imem = memStates[im];
                     final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
-                    long count = getPssSampleCount(bucket);
-                    if (count > 0) {
-                        if (!printedHeader) {
-                            pw.print(prefix);
-                            pw.print("PSS/USS (");
-                            pw.print(mPssTable.getKeyCount());
-                            pw.println(" entries):");
-                            printedHeader = true;
-                        }
-                        pw.print(prefix);
-                        pw.print("  ");
-                        if (screenStates.length > 1) {
-                            DumpUtils.printScreenLabel(pw,
-                                    printedScreen != iscreen ? iscreen : STATE_NOTHING);
-                            printedScreen = iscreen;
-                        }
-                        if (memStates.length > 1) {
-                            DumpUtils.printMemLabel(pw,
-                                    printedMem != imem ? imem : STATE_NOTHING, '/');
-                            printedMem = imem;
-                        }
-                        pw.print(DumpUtils.STATE_LABELS[procStates[ip]]); pw.print(": ");
-                        pw.print(count);
-                        pw.print(" samples ");
-                        DebugUtils.printSizeValue(pw, getPssMinimum(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssAverage(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssMaximum(bucket) * 1024);
-                        pw.print(" / ");
-                        DebugUtils.printSizeValue(pw, getPssUssMinimum(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssUssAverage(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssUssMaximum(bucket) * 1024);
-                        pw.print(" / ");
-                        DebugUtils.printSizeValue(pw, getPssRssMinimum(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssRssAverage(bucket) * 1024);
-                        pw.print(" ");
-                        DebugUtils.printSizeValue(pw, getPssRssMaximum(bucket) * 1024);
-                        pw.println();
+                    final int key = mPssTable.getKey((byte)bucket);
+                    if (key == SparseMappingTable.INVALID_KEY) {
+                        continue;
                     }
+                    final long[] table = mPssTable.getArrayForKey(key);
+                    final int tableOffset = SparseMappingTable.getIndexFromKey(key);
+                    if (!printedHeader) {
+                        pw.print(prefix);
+                        pw.print("PSS/USS (");
+                        pw.print(mPssTable.getKeyCount());
+                        pw.println(" entries):");
+                        printedHeader = true;
+                    }
+                    pw.print(prefix);
+                    pw.print("  ");
+                    if (screenStates.length > 1) {
+                        DumpUtils.printScreenLabel(pw,
+                                printedScreen != iscreen ? iscreen : STATE_NOTHING);
+                        printedScreen = iscreen;
+                    }
+                    if (memStates.length > 1) {
+                        DumpUtils.printMemLabel(pw,
+                                printedMem != imem ? imem : STATE_NOTHING, '/');
+                        printedMem = imem;
+                    }
+                    pw.print(DumpUtils.STATE_LABELS[procStates[ip]]); pw.print(": ");
+                    dumpPssSamples(pw, table, tableOffset);
+                    pw.println();
                 }
             }
         }
+        final long totalRunningDuration = getTotalRunningDuration(now);
+        if (totalRunningDuration != 0) {
+            pw.print(prefix);
+            pw.print("Cur time ");
+            TimeUtils.formatDuration(totalRunningDuration, pw);
+            if (mTotalRunningStartTime != 0) {
+                pw.print(" (running)");
+            }
+            if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
+                pw.print(": ");
+                dumpPssSamples(pw, mTotalRunningPss, 0);
+            }
+            pw.println();
+        }
         if (mNumExcessiveCpu != 0) {
             pw.print(prefix); pw.print("Killed for excessive CPU use: ");
                     pw.print(mNumExcessiveCpu); pw.println(" times");
@@ -939,6 +985,28 @@
         }
     }
 
+    public static void dumpPssSamples(PrintWriter pw, long[] table, int offset) {
+        DebugUtils.printSizeValue(pw, table[offset + PSS_MINIMUM] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_AVERAGE] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_MAXIMUM] * 1024);
+        pw.print("/");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_USS_MINIMUM] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_USS_AVERAGE] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_USS_MAXIMUM] * 1024);
+        pw.print("/");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_RSS_MINIMUM] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_RSS_AVERAGE] * 1024);
+        pw.print("-");
+        DebugUtils.printSizeValue(pw, table[offset + PSS_RSS_MAXIMUM] * 1024);
+        pw.print(" over ");
+        pw.print(table[offset + PSS_SAMPLE_COUNT]);
+    }
+
     private void dumpProcessSummaryDetails(PrintWriter pw, String prefix,
             String label, int[] screenStates, int[] memStates, int[] procStates,
             long now, long totalTime, boolean full) {
@@ -1116,6 +1184,21 @@
             dumpAllPssCheckin(pw);
             pw.println();
         }
+        if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
+            pw.print("pkgrun,");
+            pw.print(pkgName);
+            pw.print(",");
+            pw.print(uid);
+            pw.print(",");
+            pw.print(vers);
+            pw.print(",");
+            pw.print(DumpUtils.collapseString(pkgName, itemName));
+            pw.print(",");
+            pw.print(getTotalRunningDuration(now));
+            pw.print(",");
+            dumpPssSamplesCheckin(pw, mTotalRunningPss, 0);
+            pw.println();
+        }
         if (mNumExcessiveCpu > 0 || mNumCachedKill > 0) {
             pw.print("pkgkills,");
             pw.print(pkgName);
@@ -1158,6 +1241,17 @@
             dumpAllPssCheckin(pw);
             pw.println();
         }
+        if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
+            pw.print("procrun,");
+            pw.print(procName);
+            pw.print(",");
+            pw.print(uid);
+            pw.print(",");
+            pw.print(getTotalRunningDuration(now));
+            pw.print(",");
+            dumpPssSamplesCheckin(pw, mTotalRunningPss, 0);
+            pw.println();
+        }
         if (mNumExcessiveCpu > 0 || mNumCachedKill > 0) {
             pw.print("kills,");
             pw.print(procName);
@@ -1204,28 +1298,33 @@
             pw.print(',');
             DumpUtils.printProcStateTag(pw, type);
             pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_SAMPLE_COUNT));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_MINIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_AVERAGE));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_MAXIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_USS_MINIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_USS_AVERAGE));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_USS_MAXIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_RSS_MINIMUM));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_RSS_AVERAGE));
-            pw.print(':');
-            pw.print(mPssTable.getValue(key, PSS_RSS_MAXIMUM));
+            dumpPssSamplesCheckin(pw, mPssTable.getArrayForKey(key),
+                    SparseMappingTable.getIndexFromKey(key));
         }
     }
 
+    public static void dumpPssSamplesCheckin(PrintWriter pw, long[] table, int offset) {
+        pw.print(table[offset + PSS_SAMPLE_COUNT]);
+        pw.print(':');
+        pw.print(table[offset + PSS_MINIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_AVERAGE]);
+        pw.print(':');
+        pw.print(table[offset + PSS_MAXIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_USS_MINIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_USS_AVERAGE]);
+        pw.print(':');
+        pw.print(table[offset + PSS_USS_MAXIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_RSS_MINIMUM]);
+        pw.print(':');
+        pw.print(table[offset + PSS_RSS_AVERAGE]);
+        pw.print(':');
+        pw.print(table[offset + PSS_RSS_MAXIMUM]);
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
@@ -1253,7 +1352,7 @@
         }
 
         // Group proc stats by type (screen state + mem state + process state)
-        Map<Integer, Long> durationByState = new HashMap<>();
+        SparseLongArray durationByState = new SparseLongArray();
         boolean didCurState = false;
         for (int i=0; i<mDurations.getKeyCount(); i++) {
             final int key = mDurations.getKeyAt(i);
@@ -1272,7 +1371,7 @@
         for (int i=0; i<mPssTable.getKeyCount(); i++) {
             final int key = mPssTable.getKeyAt(i);
             final int type = SparseMappingTable.getIdFromKey(key);
-            if (!durationByState.containsKey(type)) {
+            if (durationByState.indexOfKey(type) < 0) {
                 // state without duration should not have stats!
                 continue;
             }
@@ -1284,36 +1383,35 @@
                     type);
 
             long duration = durationByState.get(type);
-            durationByState.remove(type); // remove the key since it is already being dumped.
+            durationByState.delete(type); // remove the key since it is already being dumped.
             proto.write(ProcessStatsProto.State.DURATION_MS, duration);
 
-            proto.write(ProcessStatsProto.State.SAMPLE_SIZE, mPssTable.getValue(key, PSS_SAMPLE_COUNT));
-            ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.PSS,
-                    mPssTable.getValue(key, PSS_MINIMUM),
-                    mPssTable.getValue(key, PSS_AVERAGE),
-                    mPssTable.getValue(key, PSS_MAXIMUM));
-            ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.USS,
-                    mPssTable.getValue(key, PSS_USS_MINIMUM),
-                    mPssTable.getValue(key, PSS_USS_AVERAGE),
-                    mPssTable.getValue(key, PSS_USS_MAXIMUM));
-            ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.RSS,
-                    mPssTable.getValue(key, PSS_RSS_MINIMUM),
-                    mPssTable.getValue(key, PSS_RSS_AVERAGE),
-                    mPssTable.getValue(key, PSS_RSS_MAXIMUM));
+            mPssTable.writeStatsToProtoForKey(proto, key);
 
             proto.end(stateToken);
         }
 
-        for (Map.Entry<Integer, Long> entry : durationByState.entrySet()) {
+        for (int i = 0; i < durationByState.size(); i++) {
             final long stateToken = proto.start(ProcessStatsProto.STATES);
             DumpUtils.printProcStateTagProto(proto,
                     ProcessStatsProto.State.SCREEN_STATE,
                     ProcessStatsProto.State.MEMORY_STATE,
                     ProcessStatsProto.State.PROCESS_STATE,
-                    entry.getKey());
-            proto.write(ProcessStatsProto.State.DURATION_MS, entry.getValue());
+                    durationByState.keyAt(i));
+            proto.write(ProcessStatsProto.State.DURATION_MS, durationByState.valueAt(i));
             proto.end(stateToken);
         }
+
+        final long totalRunningDuration = getTotalRunningDuration(now);
+        if (totalRunningDuration > 0) {
+            final long stateToken = proto.start(ProcessStatsProto.TOTAL_RUNNING_STATE);
+            proto.write(ProcessStatsProto.State.DURATION_MS, totalRunningDuration);
+            if (mTotalRunningPss[PSS_SAMPLE_COUNT] != 0) {
+                PssTable.writeStatsToProto(proto, mTotalRunningPss, 0);
+            }
+            proto.end(stateToken);
+        }
+
         proto.end(token);
     }
 }
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 12b16d0..d088354 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -158,7 +158,7 @@
     };
 
     // Current version of the parcel format.
-    private static final int PARCEL_VERSION = 33;
+    private static final int PARCEL_VERSION = 34;
     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
     private static final int MAGIC = 0x50535454;
 
@@ -1483,7 +1483,7 @@
                             proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
                                     ALL_PROC_STATES, now);
                             proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
-                                    ALL_PROC_STATES);
+                                    ALL_PROC_STATES, now);
                             proc.dumpInternalLocked(pw, "        ", dumpAll);
                         }
                     } else {
@@ -1558,7 +1558,7 @@
                 int uid = uids.keyAt(iu);
                 numTotalProcs++;
                 final ProcessState proc = uids.valueAt(iu);
-                if (proc.hasAnyData()) {
+                if (!proc.hasAnyData()) {
                     continue;
                 }
                 if (!proc.isMultiPackage()) {
@@ -1587,7 +1587,7 @@
                         pw.print(" entries)"); pw.println(":");
                 proc.dumpProcessState(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
                         ALL_PROC_STATES, now);
-                proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES);
+                proc.dumpPss(pw, "        ", ALL_SCREEN_ADJ, ALL_MEM_ADJ, ALL_PROC_STATES, now);
                 proc.dumpInternalLocked(pw, "        ", dumpAll);
             }
         }
diff --git a/core/java/com/android/internal/app/procstats/PssTable.java b/core/java/com/android/internal/app/procstats/PssTable.java
index 1e7c566..f858e55 100644
--- a/core/java/com/android/internal/app/procstats/PssTable.java
+++ b/core/java/com/android/internal/app/procstats/PssTable.java
@@ -28,6 +28,10 @@
 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MAXIMUM;
 import static com.android.internal.app.procstats.ProcessStats.PSS_COUNT;
 
+import android.service.procstats.ProcessStatsProto;
+import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
+
 /**
  * Class to accumulate PSS data.
  */
@@ -46,18 +50,17 @@
     public void mergeStats(PssTable that) {
         final int N = that.getKeyCount();
         for (int i=0; i<N; i++) {
-            final int key = that.getKeyAt(i);
-            final int state = SparseMappingTable.getIdFromKey(key);
-            mergeStats(state, (int)that.getValue(key, PSS_SAMPLE_COUNT),
-                    that.getValue(key, PSS_MINIMUM),
-                    that.getValue(key, PSS_AVERAGE),
-                    that.getValue(key, PSS_MAXIMUM),
-                    that.getValue(key, PSS_USS_MINIMUM),
-                    that.getValue(key, PSS_USS_AVERAGE),
-                    that.getValue(key, PSS_USS_MAXIMUM),
-                    that.getValue(key, PSS_RSS_MINIMUM),
-                    that.getValue(key, PSS_RSS_AVERAGE),
-                    that.getValue(key, PSS_RSS_MAXIMUM));
+            final int thatKey = that.getKeyAt(i);
+            final int state = SparseMappingTable.getIdFromKey(thatKey);
+
+            final int key = getOrAddKey((byte)state, PSS_COUNT);
+            final long[] stats = getArrayForKey(key);
+            final int statsIndex = SparseMappingTable.getIndexFromKey(key);
+
+            final long[] thatStats = that.getArrayForKey(thatKey);
+            final int thatStatsIndex = SparseMappingTable.getIndexFromKey(thatKey);
+
+            mergeStats(stats, statsIndex, thatStats, thatStatsIndex);
         }
     }
 
@@ -68,64 +71,100 @@
     public void mergeStats(int state, int inCount, long minPss, long avgPss, long maxPss,
             long minUss, long avgUss, long maxUss, long minRss, long avgRss, long maxRss) {
         final int key = getOrAddKey((byte)state, PSS_COUNT);
-        final long count = getValue(key, PSS_SAMPLE_COUNT);
+        final long[] stats = getArrayForKey(key);
+        final int statsIndex = SparseMappingTable.getIndexFromKey(key);
+        mergeStats(stats, statsIndex, inCount, minPss, avgPss, maxPss, minUss, avgUss, maxUss,
+                minRss, avgRss, maxRss);
+    }
+
+    public static void mergeStats(final long[] stats, final int statsIndex,
+            final long[] thatStats, int thatStatsIndex) {
+        mergeStats(stats, statsIndex, (int)thatStats[thatStatsIndex + PSS_SAMPLE_COUNT],
+                thatStats[thatStatsIndex + PSS_MINIMUM],
+                thatStats[thatStatsIndex + PSS_AVERAGE],
+                thatStats[thatStatsIndex + PSS_MAXIMUM],
+                thatStats[thatStatsIndex + PSS_USS_MINIMUM],
+                thatStats[thatStatsIndex + PSS_USS_AVERAGE],
+                thatStats[thatStatsIndex + PSS_USS_MAXIMUM],
+                thatStats[thatStatsIndex + PSS_RSS_MINIMUM],
+                thatStats[thatStatsIndex + PSS_RSS_AVERAGE],
+                thatStats[thatStatsIndex + PSS_RSS_MAXIMUM]);
+    }
+
+    public static void mergeStats(final long[] stats, final int statsIndex, final int inCount,
+            final long minPss, final long avgPss, final long maxPss,
+            final long minUss, final long avgUss, final long maxUss,
+            final long minRss, final long avgRss, final long maxRss) {
+        final long count = stats[statsIndex + PSS_SAMPLE_COUNT];
         if (count == 0) {
-            setValue(key, PSS_SAMPLE_COUNT, inCount);
-            setValue(key, PSS_MINIMUM, minPss);
-            setValue(key, PSS_AVERAGE, avgPss);
-            setValue(key, PSS_MAXIMUM, maxPss);
-            setValue(key, PSS_USS_MINIMUM, minUss);
-            setValue(key, PSS_USS_AVERAGE, avgUss);
-            setValue(key, PSS_USS_MAXIMUM, maxUss);
-            setValue(key, PSS_RSS_MINIMUM, minRss);
-            setValue(key, PSS_RSS_AVERAGE, avgRss);
-            setValue(key, PSS_RSS_MAXIMUM, maxRss);
+            stats[statsIndex + PSS_SAMPLE_COUNT] = inCount;
+            stats[statsIndex + PSS_MINIMUM] = minPss;
+            stats[statsIndex + PSS_AVERAGE] = avgPss;
+            stats[statsIndex + PSS_MAXIMUM] = maxPss;
+            stats[statsIndex + PSS_USS_MINIMUM] = minUss;
+            stats[statsIndex + PSS_USS_AVERAGE] = avgUss;
+            stats[statsIndex + PSS_USS_MAXIMUM] = maxUss;
+            stats[statsIndex + PSS_RSS_MINIMUM] = minRss;
+            stats[statsIndex + PSS_RSS_AVERAGE] = avgRss;
+            stats[statsIndex + PSS_RSS_MAXIMUM] = maxRss;
         } else {
-            setValue(key, PSS_SAMPLE_COUNT, count + inCount);
+            stats[statsIndex + PSS_SAMPLE_COUNT] = count + inCount;
 
-            long val;
-
-            val = getValue(key, PSS_MINIMUM);
-            if (val > minPss) {
-                setValue(key, PSS_MINIMUM, minPss);
+            if (stats[statsIndex + PSS_MINIMUM] > minPss) {
+                stats[statsIndex + PSS_MINIMUM] = minPss;
             }
 
-            val = getValue(key, PSS_AVERAGE);
-            setValue(key, PSS_AVERAGE,
-                    (long)(((val*(double)count)+(avgPss*(double)inCount)) / (count+inCount)));
+            stats[statsIndex + PSS_AVERAGE] = (long)(((stats[statsIndex + PSS_AVERAGE]
+                    * (double)count) + (avgPss * (double)inCount)) / (count + inCount));
 
-            val = getValue(key, PSS_MAXIMUM);
-            if (val < maxPss) {
-                setValue(key, PSS_MAXIMUM, maxPss);
+            if (stats[statsIndex + PSS_MAXIMUM] < maxPss) {
+                stats[statsIndex + PSS_MAXIMUM] = maxPss;
             }
 
-            val = getValue(key, PSS_USS_MINIMUM);
-            if (val > minUss) {
-                setValue(key, PSS_USS_MINIMUM, minUss);
+            if (stats[statsIndex + PSS_USS_MINIMUM] > minUss) {
+                stats[statsIndex + PSS_USS_MINIMUM] = minUss;
             }
 
-            val = getValue(key, PSS_USS_AVERAGE);
-            setValue(key, PSS_USS_AVERAGE,
-                    (long)(((val*(double)count)+(avgUss*(double)inCount)) / (count+inCount)));
+            stats[statsIndex + PSS_USS_AVERAGE] = (long)(((stats[statsIndex + PSS_USS_AVERAGE]
+                    * (double)count) + (avgUss * (double)inCount)) / (count + inCount));
 
-            val = getValue(key, PSS_USS_MAXIMUM);
-            if (val < maxUss) {
-                setValue(key, PSS_USS_MAXIMUM, maxUss);
+            if (stats[statsIndex + PSS_USS_MAXIMUM] < maxUss) {
+                stats[statsIndex + PSS_USS_MAXIMUM] = maxUss;
             }
 
-            val = getValue(key, PSS_RSS_MINIMUM);
-            if (val > minUss) {
-                setValue(key, PSS_RSS_MINIMUM, minUss);
+            if (stats[statsIndex + PSS_RSS_MINIMUM] > minRss) {
+                stats[statsIndex + PSS_RSS_MINIMUM] = minRss;
             }
 
-            val = getValue(key, PSS_RSS_AVERAGE);
-            setValue(key, PSS_RSS_AVERAGE,
-                    (long)(((val*(double)count)+(avgUss*(double)inCount)) / (count+inCount)));
+            stats[statsIndex + PSS_RSS_AVERAGE] = (long)(((stats[statsIndex + PSS_RSS_AVERAGE]
+                    * (double)count) + (avgRss * (double)inCount)) / (count + inCount));
 
-            val = getValue(key, PSS_RSS_MAXIMUM);
-            if (val < maxUss) {
-                setValue(key, PSS_RSS_MAXIMUM, maxUss);
+            if (stats[statsIndex + PSS_RSS_MAXIMUM] < maxRss) {
+                stats[statsIndex + PSS_RSS_MAXIMUM] = maxRss;
             }
         }
     }
+
+    public void writeStatsToProtoForKey(ProtoOutputStream proto, int key) {
+        final long[] stats = getArrayForKey(key);
+        final int statsIndex = SparseMappingTable.getIndexFromKey(key);
+        writeStatsToProto(proto, stats, statsIndex);
+    }
+
+    public static void writeStatsToProto(ProtoOutputStream proto, final long[] stats,
+            final int statsIndex) {
+        proto.write(ProcessStatsProto.State.SAMPLE_SIZE, stats[statsIndex + PSS_SAMPLE_COUNT]);
+        ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.PSS,
+                stats[statsIndex + PSS_MINIMUM],
+                stats[statsIndex + PSS_AVERAGE],
+                stats[statsIndex + PSS_MAXIMUM]);
+        ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.USS,
+                stats[statsIndex + PSS_USS_MINIMUM],
+                stats[statsIndex + PSS_USS_AVERAGE],
+                stats[statsIndex + PSS_USS_MAXIMUM]);
+        ProtoUtils.toAggStatsProto(proto, ProcessStatsProto.State.RSS,
+                stats[statsIndex + PSS_RSS_MINIMUM],
+                stats[statsIndex + PSS_RSS_AVERAGE],
+                stats[statsIndex + PSS_RSS_MAXIMUM]);
+    }
 }
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 5a39915..eb369e1 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -17,12 +17,19 @@
 package com.android.internal.os;
 
 import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
 import android.os.Binder;
+import android.os.OsProtoEnums;
+import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.format.DateFormat;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -31,6 +38,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BinderInternal.CallSession;
 import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
 import java.lang.reflect.InvocationTargetException;
@@ -74,38 +82,117 @@
     private final Random mRandom;
     private long mStartTime = System.currentTimeMillis();
 
-    public BinderCallsStats(Random random) {
-        this.mRandom = random;
+    // State updated by the broadcast receiver below.
+    private boolean mScreenInteractive;
+    private boolean mCharging;
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case Intent.ACTION_BATTERY_CHANGED:
+                    mCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
+                    break;
+                case Intent.ACTION_SCREEN_ON:
+                    mScreenInteractive = true;
+                    break;
+                case Intent.ACTION_SCREEN_OFF:
+                    mScreenInteractive = false;
+                    break;
+            }
+        }
+    };
+
+    /** Injector for {@link BinderCallsStats}. */
+    public static class Injector {
+        public Random getRandomGenerator() {
+            return new Random();
+        }
+    }
+
+    public BinderCallsStats(Injector injector) {
+        this.mRandom = injector.getRandomGenerator();
+    }
+
+    public void systemReady(Context context) {
+        registerBroadcastReceiver(context);
+        setInitialState(queryScreenInteractive(context), queryIsCharging());
+    }
+
+    /**
+     * Listens for screen/battery state changes.
+     */
+    @VisibleForTesting
+    public void registerBroadcastReceiver(Context context) {
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        context.registerReceiver(mBroadcastReceiver, filter);
+    }
+
+    /**
+     * Sets the battery/screen initial state.
+     *
+     * This has to be updated *after* the broadcast receiver is installed.
+     */
+    @VisibleForTesting
+    public void setInitialState(boolean isScreenInteractive, boolean isCharging) {
+        this.mScreenInteractive = isScreenInteractive;
+        this.mCharging = isCharging;
+        // Data collected previously was not accurate since the battery/screen state was not set.
+        reset();
+    }
+
+    private boolean queryIsCharging() {
+        final BatteryManagerInternal batteryManager =
+                LocalServices.getService(BatteryManagerInternal.class);
+        if (batteryManager == null) {
+            Slog.wtf(TAG, "BatteryManager null while starting BinderCallsStatsService");
+            // Default to true to not collect any data.
+            return true;
+        } else {
+            return batteryManager.getPlugType() != OsProtoEnums.BATTERY_PLUGGED_NONE;
+        }
+    }
+
+    private boolean queryScreenInteractive(Context context) {
+        final PowerManager powerManager = context.getSystemService(PowerManager.class);
+        final boolean screenInteractive;
+        if (powerManager == null) {
+            Slog.wtf(TAG, "PowerManager null while starting BinderCallsStatsService",
+                    new Throwable());
+            return true;
+        } else {
+            return powerManager.isInteractive();
+        }
     }
 
     @Override
+    @Nullable
     public CallSession callStarted(Binder binder, int code) {
-        return callStarted(binder.getClass(), code);
-    }
-
-    private CallSession callStarted(Class<? extends Binder> binderClass, int code) {
-        CallSession s = mCallSessionsPool.poll();
-        if (s == null) {
-            s = new CallSession();
+        if (mCharging) {
+            return null;
         }
 
-        s.binderClass = binderClass;
+        final CallSession s = obtainCallSession();
+        s.binderClass = binder.getClass();
         s.transactionCode = code;
         s.exceptionThrown = false;
         s.cpuTimeStarted = -1;
         s.timeStarted = -1;
-
-        synchronized (mLock) {
-            if (!mDetailedTracking && !shouldTrackCall()) {
-                return s;
-            }
-
+        if (mDetailedTracking || shouldRecordDetailedData()) {
             s.cpuTimeStarted = getThreadTimeMicro();
             s.timeStarted = getElapsedRealtimeMicro();
         }
         return s;
     }
 
+    private CallSession obtainCallSession() {
+        CallSession s = mCallSessionsPool.poll();
+        return s == null ? new CallSession() : s;
+    }
+
     @Override
     public void callEnded(@Nullable CallSession s, int parcelRequestSize, int parcelReplySize) {
         if (s == null) {
@@ -134,13 +221,15 @@
         final int callingUid = getCallingUid();
 
         synchronized (mLock) {
-            UidEntry uidEntry = mUidEntries.get(callingUid);
-            if (uidEntry == null) {
-                uidEntry = new UidEntry(callingUid);
-                mUidEntries.put(callingUid, uidEntry);
+            // This was already checked in #callStart but check again while synchronized.
+            if (mCharging) {
+                return;
             }
+
+            final UidEntry uidEntry = getUidEntry(callingUid);
             uidEntry.callCount++;
-            CallStat callStat = uidEntry.getOrCreate(s.binderClass, s.transactionCode);
+            final CallStat callStat = uidEntry.getOrCreate(
+                    s.binderClass, s.transactionCode, mScreenInteractive);
             callStat.callCount++;
 
             if (recordCall) {
@@ -164,6 +253,15 @@
         }
     }
 
+    private UidEntry getUidEntry(int uid) {
+        UidEntry uidEntry = mUidEntries.get(uid);
+        if (uidEntry == null) {
+            uidEntry = new UidEntry(uid);
+            mUidEntries.put(uid, uidEntry);
+        }
+        return uidEntry;
+    }
+
     @Override
     public void callThrewException(@Nullable CallSession s, Exception exception) {
         if (s == null) {
@@ -176,12 +274,12 @@
                 if (mExceptionCounts.size() >= MAX_EXCEPTION_COUNT_SIZE) {
                     className = EXCEPTION_COUNT_OVERFLOW_NAME;
                 }
-                Integer count = mExceptionCounts.get(className);
+                final Integer count = mExceptionCounts.get(className);
                 mExceptionCounts.put(className, count == null ? 1 : count + 1);
             }
         } catch (RuntimeException e) {
             // Do not propagate the exception. We do not want to swallow original exception.
-            Log.wtf(TAG, "Unexpected exception while updating mExceptionCounts", e);
+            Slog.wtf(TAG, "Unexpected exception while updating mExceptionCounts");
         }
     }
 
@@ -219,15 +317,16 @@
 
         ArrayList<ExportedCallStat> resultCallStats = new ArrayList<>();
         synchronized (mLock) {
-            int uidEntriesSize = mUidEntries.size();
+            final int uidEntriesSize = mUidEntries.size();
             for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++){
-                UidEntry entry = mUidEntries.valueAt(entryIdx);
+                final UidEntry entry = mUidEntries.valueAt(entryIdx);
                 for (CallStat stat : entry.getCallStatsList()) {
                     ExportedCallStat exported = new ExportedCallStat();
                     exported.uid = entry.uid;
                     exported.className = stat.binderClass.getName();
                     exported.binderClass = stat.binderClass;
                     exported.transactionCode = stat.transactionCode;
+                    exported.screenInteractive = stat.screenInteractive;
                     exported.cpuTimeMicros = stat.cpuTimeMicros;
                     exported.maxCpuTimeMicros = stat.maxCpuTimeMicros;
                     exported.latencyMicros = stat.latencyMicros;
@@ -294,9 +393,9 @@
         pw.print("Start time: ");
         pw.println(DateFormat.format("yyyy-MM-dd HH:mm:ss", mStartTime));
         pw.println("Sampling interval period: " + mPeriodicSamplingInterval);
-        List<UidEntry> entries = new ArrayList<>();
+        final List<UidEntry> entries = new ArrayList<>();
 
-        int uidEntriesSize = mUidEntries.size();
+        final int uidEntriesSize = mUidEntries.size();
         for (int i = 0; i < uidEntriesSize; i++) {
             UidEntry e = mUidEntries.valueAt(i);
             entries.add(e);
@@ -306,16 +405,17 @@
         }
 
         entries.sort(Comparator.<UidEntry>comparingDouble(value -> value.cpuTimeMicros).reversed());
-        String datasetSizeDesc = verbose ? "" : "(top 90% by cpu time) ";
-        StringBuilder sb = new StringBuilder();
-        List<UidEntry> topEntries = verbose ? entries
+        final String datasetSizeDesc = verbose ? "" : "(top 90% by cpu time) ";
+        final StringBuilder sb = new StringBuilder();
+        final List<UidEntry> topEntries = verbose ? entries
                 : getHighestValues(entries, value -> value.cpuTimeMicros, 0.9);
         pw.println("Per-UID raw data " + datasetSizeDesc
-                + "(package/uid, call_desc, cpu_time_micros, max_cpu_time_micros, "
+                + "(package/uid, call_desc, screen_interactive, "
+                + "cpu_time_micros, max_cpu_time_micros, "
                 + "latency_time_micros, max_latency_time_micros, exception_count, "
                 + "max_request_size_bytes, max_reply_size_bytes, recorded_call_count, "
                 + "call_count):");
-        List<ExportedCallStat> exportedCallStats = getExportedCallStats();
+        final List<ExportedCallStat> exportedCallStats = getExportedCallStats();
         exportedCallStats.sort(BinderCallsStats::compareByCpuDesc);
         for (ExportedCallStat e : exportedCallStats) {
             sb.setLength(0);
@@ -323,6 +423,7 @@
                     .append(uidToString(e.uid, appIdToPkgNameMap))
                     .append(',').append(e.className)
                     .append('#').append(e.methodName)
+                    .append(',').append(e.screenInteractive)
                     .append(',').append(e.cpuTimeMicros)
                     .append(',').append(e.maxCpuTimeMicros)
                     .append(',').append(e.latencyMicros)
@@ -337,7 +438,7 @@
         pw.println();
         pw.println("Per-UID Summary " + datasetSizeDesc
                 + "(cpu_time, % of total cpu_time, recorded_call_count, call_count, package/uid):");
-        List<UidEntry> summaryEntries = verbose ? entries
+        final List<UidEntry> summaryEntries = verbose ? entries
                 : getHighestValues(entries, value -> value.cpuTimeMicros, 0.9);
         for (UidEntry entry : summaryEntries) {
             String uidStr = uidToString(entry.uid, appIdToPkgNameMap);
@@ -352,7 +453,7 @@
         pw.println();
 
         pw.println("Exceptions thrown (exception_count, class_name):");
-        List<Pair<String, Integer>> exceptionEntries = new ArrayList<>();
+        final List<Pair<String, Integer>> exceptionEntries = new ArrayList<>();
         // We cannot use new ArrayList(Collection) constructor because MapCollections does not
         // implement toArray method.
         mExceptionCounts.entrySet().iterator().forEachRemaining(
@@ -369,9 +470,9 @@
     }
 
     private static String uidToString(int uid, Map<Integer, String> pkgNameMap) {
-        int appId = UserHandle.getAppId(uid);
-        String pkgName = pkgNameMap == null ? null : pkgNameMap.get(appId);
-        String uidStr = UserHandle.formatUid(uid);
+        final int appId = UserHandle.getAppId(uid);
+        final String pkgName = pkgNameMap == null ? null : pkgNameMap.get(appId);
+        final String uidStr = UserHandle.formatUid(uid);
         return pkgName == null ? uidStr : pkgName + '/' + uidStr;
     }
 
@@ -387,7 +488,7 @@
         return SystemClock.elapsedRealtimeNanos() / 1000;
     }
 
-    private boolean shouldTrackCall() {
+    private boolean shouldRecordDetailedData() {
         return mRandom.nextInt() % mPeriodicSamplingInterval == 0;
     }
 
@@ -444,6 +545,8 @@
     public static class CallStat {
         public Class<? extends Binder> binderClass;
         public int transactionCode;
+        // True if the screen was interactive when the call ended.
+        public boolean screenInteractive;
         // Number of calls for which we collected data for. We do not record data for all the calls
         // when sampling is on.
         public long recordedCallCount;
@@ -464,9 +567,11 @@
         public long maxReplySizeBytes;
         public long exceptionCount;
 
-        CallStat(Class<? extends Binder> binderClass, int transactionCode) {
+        CallStat(Class<? extends Binder> binderClass, int transactionCode,
+                boolean screenInteractive) {
             this.binderClass = binderClass;
             this.transactionCode = transactionCode;
+            this.screenInteractive = screenInteractive;
         }
     }
 
@@ -474,6 +579,7 @@
     public static class CallStatKey {
         public Class<? extends Binder> binderClass;
         public int transactionCode;
+        private boolean screenInteractive;
 
         @Override
         public boolean equals(Object o) {
@@ -481,8 +587,9 @@
                 return true;
             }
 
-            CallStatKey key = (CallStatKey) o;
+            final CallStatKey key = (CallStatKey) o;
             return transactionCode == key.transactionCode
+                    && screenInteractive == key.screenInteractive
                     && (binderClass.equals(key.binderClass));
         }
 
@@ -490,6 +597,7 @@
         public int hashCode() {
             int result = binderClass.hashCode();
             result = 31 * result + transactionCode;
+            result = 31 * result + (screenInteractive ? 1231 : 1237);
             return result;
         }
     }
@@ -516,17 +624,20 @@
         private Map<CallStatKey, CallStat> mCallStats = new ArrayMap<>();
         private CallStatKey mTempKey = new CallStatKey();
 
-        CallStat getOrCreate(Class<? extends Binder> binderClass, int transactionCode) {
+        CallStat getOrCreate(Class<? extends Binder> binderClass, int transactionCode,
+                boolean screenInteractive) {
             // Use a global temporary key to avoid creating new objects for every lookup.
             mTempKey.binderClass = binderClass;
             mTempKey.transactionCode = transactionCode;
+            mTempKey.screenInteractive = screenInteractive;
             CallStat mapCallStat = mCallStats.get(mTempKey);
             // Only create CallStat if it's a new entry, otherwise update existing instance
             if (mapCallStat == null) {
-                mapCallStat = new CallStat(binderClass, transactionCode);
+                mapCallStat = new CallStat(binderClass, transactionCode, screenInteractive);
                 CallStatKey key = new CallStatKey();
                 key.binderClass = binderClass;
                 key.transactionCode = transactionCode;
+                key.screenInteractive = screenInteractive;
                 mCallStats.put(key, mapCallStat);
             }
             return mapCallStat;
@@ -595,6 +706,11 @@
         return result;
     }
 
+    @VisibleForTesting
+    public BroadcastReceiver getBroadcastReceiver() {
+        return mBroadcastReceiver;
+    }
+
     private static int compareByCpuDesc(
             ExportedCallStat a, ExportedCallStat b) {
         return Long.compare(b.cpuTimeMicros, a.cpuTimeMicros);
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 2790324..616520f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -140,14 +140,14 @@
 
     void showShutdownUi(boolean isReboot, String reason);
 
-    // Used to show the dialog when FingerprintService starts authentication
-    void showFingerprintDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
-    // Used to hide the dialog when a finger is authenticated
-    void onFingerprintAuthenticated();
+    // Used to show the dialog when BiometricService starts authentication
+    void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
+    // Used to hide the dialog when a biometric is authenticated
+    void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
-    void onFingerprintHelp(String message);
+    void onBiometricHelp(String message);
     // Used to set a message - the dialog will dismiss after a certain amount of time
-    void onFingerprintError(String error);
-    // Used to hide the fingerprint dialog when the authenticationclient is stopped
-    void hideFingerprintDialog();
+    void onBiometricError(String error);
+    // Used to hide the biometric dialog when the AuthenticationClient is stopped
+    void hideBiometricDialog();
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 159d49b..a79e15a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -90,14 +90,14 @@
     void showPinningEnterExitToast(boolean entering);
     void showPinningEscapeToast();
 
-    // Used to show the dialog when FingerprintService starts authentication
-    void showFingerprintDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
-    // Used to hide the dialog when a finger is authenticated
-    void onFingerprintAuthenticated();
+    // Used to show the dialog when BiometricService starts authentication
+    void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
+    // Used to hide the dialog when a biometric is authenticated
+    void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
-    void onFingerprintHelp(String message);
+    void onBiometricHelp(String message);
     // Used to set a message - the dialog will dismiss after a certain amount of time
-    void onFingerprintError(String error);
-    // Used to hide the fingerprint dialog when the authenticationclient is stopped
-    void hideFingerprintDialog();
+    void onBiometricError(String error);
+    // Used to hide the biometric dialog when the AuthenticationClient is stopped
+    void hideBiometricDialog();
 }
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 3b024b4..db3bfe6 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -320,9 +320,12 @@
                          jintArray jcolors, jint colorIndex,
                          jshortArray jindices, jint indexIndex,
                          jint indexCount, jlong paintHandle) {
+
+    const int vertexCount = floatCount >> 1;  // 2 floats per SkPoint
+
     AutoJavaFloatArray  vertA(env, jverts, vertIndex + floatCount);
     AutoJavaFloatArray  texA(env, jtexs, texIndex + floatCount);
-    AutoJavaIntArray    colorA(env, jcolors, colorIndex + floatCount);
+    AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
     AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
 
     const float* verts = vertA.ptr() + vertIndex;
@@ -337,7 +340,6 @@
         indices = (const uint16_t*)(indexA.ptr() + indexIndex);
     }
 
-    int vertexCount = floatCount >> 1;  // 2 floats per SkPoint
     SkVertices::VertexMode mode = static_cast<SkVertices::VertexMode>(modeHandle);
     const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     get_canvas(canvasHandle)->drawVertices(SkVertices::MakeCopy(mode, vertexCount,
diff --git a/core/proto/android/service/procstats.proto b/core/proto/android/service/procstats.proto
index 15ede0c..b2a88b7 100644
--- a/core/proto/android/service/procstats.proto
+++ b/core/proto/android/service/procstats.proto
@@ -174,4 +174,8 @@
         optional android.util.AggStats rss = 8;
     }
     repeated State states = 5;
+
+    // Total time process has been running...  screen_state, memory_state, and process_state
+    // will not be set.
+    optional State total_running_state = 6;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c2ff9c9..6a3487c1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -606,6 +606,14 @@
     <protected-broadcast android:name="android.intent.action.DOCK_IDLE" />
     <protected-broadcast android:name="android.intent.action.DOCK_ACTIVE" />
 
+    <!-- Added in Q -->
+
+    <!-- For CarIdlenessTracker -->
+    <protected-broadcast android:name="com.android.server.jobscheduler.GARAGE_MODE_ON" />
+    <protected-broadcast android:name="com.android.server.jobscheduler.GARAGE_MODE_OFF" />
+    <protected-broadcast android:name="com.android.server.jobscheduler.FORCE_IDLE" />
+    <protected-broadcast android:name="com.android.server.jobscheduler.UNFORCE_IDLE" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
@@ -3500,6 +3508,10 @@
     <permission android:name="android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE"
                 android:protectionLevel="signature" />
 
+    <!-- @hide Internal permission to allows an application to access card content provider. -->
+    <permission android:name="android.permission.WRITE_SETTINGS_HOMEPAGE_DATA"
+                android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows applications to set a live wallpaper.
          @hide XXX Change to signature once the picker is moved to its
          own apk as Ghod Intended. -->
diff --git a/core/res/res/values-night/themes_package_installer.xml b/core/res/res/values-night/themes_package_installer.xml
new file mode 100644
index 0000000..0ad2bdc
--- /dev/null
+++ b/core/res/res/values-night/themes_package_installer.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+
+<!-- themes for the permission grant dialog. -->
+<resources>
+    <style name="Theme.DeviceDefault.PermissionGrantApp"
+           parent="@style/Theme.DeviceDefault.Panel">
+        <item name="windowIsFloating">false</item>
+        <item name="windowTranslucentStatus">true</item>
+        <item name="backgroundDimEnabled">true</item>
+        <item name="windowAnimationStyle">@style/Animation.Material.Dialog</item>
+    </style>
+
+    <style name="Theme.DeviceDefault.PermissionGrant"
+           parent="@style/Theme.DeviceDefault.Dialog">
+        <item name="titleTextStyle">@style/PermissionGrantTitleMessage</item>
+        <item name="radioButtonStyle">@style/PermissionGrantRadioButton</item>
+        <item name="checkboxStyle">@style/PermissionGrantCheckbox</item>
+        <item name="buttonBarStyle">@style/PermissionGrantButtonBar</item>
+    </style>
+</resources>
diff --git a/core/res/res/values/themes_package_installer.xml b/core/res/res/values/themes_package_installer.xml
index a6341dc..3bc93cd 100644
--- a/core/res/res/values/themes_package_installer.xml
+++ b/core/res/res/values/themes_package_installer.xml
@@ -17,7 +17,7 @@
 
 <!-- themes for the permission grant dialog. -->
 <resources>
-    <style name="Theme.DeviceDefault.Light.Panel.PermissionGrantApp"
+    <style name="Theme.DeviceDefault.PermissionGrantApp"
            parent="@style/Theme.DeviceDefault.Light.Panel">
         <item name="windowIsFloating">false</item>
         <item name="windowTranslucentStatus">true</item>
@@ -25,7 +25,7 @@
         <item name="windowAnimationStyle">@style/Animation.Material.Dialog</item>
     </style>
 
-    <style name="Theme.DeviceDefault.Light.Dialog.PermissionGrant"
+    <style name="Theme.DeviceDefault.PermissionGrant"
            parent="@style/Theme.DeviceDefault.Light.Dialog">
         <item name="titleTextStyle">@style/PermissionGrantTitleMessage</item>
         <item name="radioButtonStyle">@style/PermissionGrantRadioButton</item>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 1a87fa2..5542f00 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -383,6 +383,8 @@
                     Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL,
                     Settings.Global.SETUP_PREPAID_DETECTION_REDIR_HOST,
                     Settings.Global.SETUP_PREPAID_DETECTION_TARGET_URL,
+                    Settings.Global.SETTINGS_USE_EXTERNAL_PROVIDER_API,
+                    Settings.Global.SETTINGS_USE_PSD_API,
                     Settings.Global.SHORTCUT_MANAGER_CONSTANTS,
                     Settings.Global.SHOW_FIRST_CRASH_DIALOG,
                     Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG,
@@ -484,6 +486,7 @@
                     Settings.Global.WIFI_SAVED_STATE,
                     Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE,
                     Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,
+                    Settings.Global.WIFI_SCAN_THROTTLE_ENABLED,
                     Settings.Global.WIFI_SCORE_PARAMS,
                     Settings.Global.WIFI_SLEEP_POLICY,
                     Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
@@ -704,3 +707,4 @@
     }
 
 }
+
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 5599ee6..2f83190 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -16,7 +16,11 @@
 
 package com.android.internal.os;
 
+import android.content.Context;
+import android.content.Intent;
+import android.os.BatteryManager;
 import android.os.Binder;
+import android.os.OsProtoEnums;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -392,6 +396,113 @@
     }
 
     @Test
+    public void testDataResetWhenInitialStateSet() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        bcs.setInitialState(true, true);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(0, uidEntries.size());
+    }
+
+    @Test
+    public void testScreenAndChargerInitialStates() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Binder binder = new Binder();
+        bcs.setInitialState(true /** screen iteractive */, false);
+
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.time += 10;
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        List<BinderCallsStats.CallStat> callStatsList =
+                new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
+        assertEquals(true, callStatsList.get(0).screenInteractive);
+    }
+
+    @Test
+    public void testNoDataCollectedOnCharger() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
+                .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
+        bcs.getBroadcastReceiver().onReceive(null, intent);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        assertEquals(0, bcs.getUidEntries().size());
+    }
+
+    @Test
+    public void testScreenOff() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_OFF));
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(1, uidEntries.size());
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        Assert.assertNotNull(uidEntry);
+        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+        assertEquals(false, callStatsList.get(0).screenInteractive);
+    }
+
+    @Test
+    public void testScreenOn() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_ON));
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+        assertEquals(1, uidEntries.size());
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        Assert.assertNotNull(uidEntry);
+        List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+        assertEquals(true, callStatsList.get(0).screenInteractive);
+    }
+
+    @Test
+    public void testOnCharger() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
+                .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_AC);
+        bcs.getBroadcastReceiver().onReceive(null, intent);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        assertEquals(0, bcs.getExportedCallStats().size());
+    }
+
+    @Test
+    public void testOnBattery() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED)
+                .putExtra(BatteryManager.EXTRA_PLUGGED, OsProtoEnums.BATTERY_PLUGGED_NONE);
+        bcs.getBroadcastReceiver().onReceive(null, intent);
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        assertEquals(1, bcs.getExportedCallStats().size());
+    }
+
+    @Test
     public void testDumpDoesNotThrowException() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
@@ -419,6 +530,8 @@
     public void testGetExportedStatsWhenDetailedTrackingEnabled() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         bcs.setDetailedTracking(true);
+        bcs.getBroadcastReceiver().onReceive(null, new Intent(Intent.ACTION_SCREEN_ON));
+
         Binder binder = new Binder();
         CallSession callSession = bcs.callStarted(binder, 1);
         bcs.time += 10;
@@ -430,6 +543,7 @@
         assertEquals(TEST_UID, stat.uid);
         assertEquals("android.os.Binder", stat.className);
         assertEquals("1", stat.methodName);
+        assertEquals(true, stat.screenInteractive);
         assertEquals(10, stat.cpuTimeMicros);
         assertEquals(10, stat.maxCpuTimeMicros);
         assertEquals(20, stat.latencyMicros);
@@ -462,11 +576,15 @@
 
         TestBinderCallsStats() {
             // Make random generator not random.
-            super(new Random() {
-                int mCallCount = 0;
+            super(new Injector() {
+                public Random getRandomGenerator() {
+                    return new Random() {
+                        int mCallCount = 0;
 
-                public int nextInt() {
-                    return mCallCount++;
+                        public int nextInt() {
+                            return mCallCount++;
+                        }
+                    };
                 }
             });
         }
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index ffe6abc1..53e9826 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas.VertexMode;
 import android.text.GraphicsOperations;
 import android.text.MeasuredParagraph;
@@ -44,6 +45,7 @@
      * freed by NativeAllocation.
      * @hide
      */
+    @UnsupportedAppUsage
     protected long mNativeCanvasWrapper;
 
     /**
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index c6f8415..cea6c1c 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.content.res.ResourcesImpl;
 import android.os.Parcel;
@@ -59,6 +60,7 @@
     private static final long NATIVE_ALLOCATION_SIZE = 32;
 
     // Convenience for JNI access
+    @UnsupportedAppUsage
     private final long mNativePtr;
 
     /**
@@ -75,9 +77,13 @@
      */
     private boolean mRequestPremultiplied;
 
+    @UnsupportedAppUsage
     private byte[] mNinePatchChunk; // may be null
+    @UnsupportedAppUsage
     private NinePatch.InsetStruct mNinePatchInsets; // may be null
+    @UnsupportedAppUsage
     private int mWidth;
+    @UnsupportedAppUsage
     private int mHeight;
     private boolean mRecycled;
 
@@ -99,11 +105,13 @@
      * density when running old apps.
      * @hide
      */
+    @UnsupportedAppUsage
     public static void setDefaultDensity(int density) {
         sDefaultDensity = density;
     }
 
     @SuppressWarnings("deprecation")
+    @UnsupportedAppUsage
     static int getDefaultDensity() {
         if (sDefaultDensity >= 0) {
             return sDefaultDensity;
@@ -117,6 +125,7 @@
      * int (pointer).
      */
     // called from JNI
+    @UnsupportedAppUsage
     Bitmap(long nativeBitmap, int width, int height, int density, boolean requestPremultiplied,
             byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
         if (nativeBitmap == 0) {
@@ -158,6 +167,7 @@
      * width/height values
      */
     @SuppressWarnings("unused") // called from JNI
+    @UnsupportedAppUsage
     void reinit(int width, int height, boolean requestPremultiplied) {
         mWidth = width;
         mHeight = height;
@@ -328,6 +338,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setNinePatchChunk(byte[] chunk) {
         mNinePatchChunk = chunk;
     }
@@ -523,6 +534,7 @@
          */
         HARDWARE    (7);
 
+        @UnsupportedAppUsage
         final int nativeInt;
 
         private static Config sConfigs[] = {
@@ -533,6 +545,7 @@
             this.nativeInt = ni;
         }
 
+        @UnsupportedAppUsage
         static Config nativeToConfig(int ni) {
             return sConfigs[ni];
         }
@@ -667,6 +680,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap createAshmemBitmap() {
         checkRecycled("Can't copy a recycled bitmap");
         noteHardwareBitmapSlowCall();
@@ -685,6 +699,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap createAshmemBitmap(Config config) {
         checkRecycled("Can't copy a recycled bitmap");
         noteHardwareBitmapSlowCall();
@@ -703,6 +718,7 @@
      *         currently PIXEL_FORMAT_RGBA_8888 is the only supported format
      * @hide
      */
+    @UnsupportedAppUsage
     public static Bitmap createHardwareBitmap(@NonNull GraphicBuffer graphicBuffer) {
         return nativeCreateHardwareBitmap(graphicBuffer);
     }
@@ -1500,6 +1516,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     static public int scaleFromDensity(int size, int sdensity, int tdensity) {
         if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
             return size;
@@ -2032,6 +2049,7 @@
      * @return {@link GraphicBuffer} which is internally used by hardware bitmap
      * @hide
      */
+    @UnsupportedAppUsage
     public GraphicBuffer createGraphicBufferHandle() {
         return nativeCreateGraphicBufferHandle(mNativePtr);
     }
@@ -2049,6 +2067,7 @@
     private static native Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig);
     private static native long nativeGetNativeFinalizer();
     private static native void nativeRecycle(long nativeBitmap);
+    @UnsupportedAppUsage
     private static native void nativeReconfigure(long nativeBitmap, int width, int height,
                                                  int config, boolean isPremultiplied);
 
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 7ea35e7..adab1a9c 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.os.Trace;
@@ -831,11 +832,15 @@
         return decodeFileDescriptor(fd, null, null);
     }
 
+    @UnsupportedAppUsage
     private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
             Rect padding, Options opts);
+    @UnsupportedAppUsage
     private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
             Rect padding, Options opts);
+    @UnsupportedAppUsage
     private static native Bitmap nativeDecodeAsset(long nativeAsset, Rect padding, Options opts);
+    @UnsupportedAppUsage
     private static native Bitmap nativeDecodeByteArray(byte[] data, int offset,
             int length, Options opts);
     private static native boolean nativeIsSeekable(FileDescriptor fd);
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index 2da27c7..9b5027d 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -15,6 +15,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 
 import java.io.FileDescriptor;
@@ -165,6 +166,7 @@
 
         This can be called from JNI code.
     */
+    @UnsupportedAppUsage
     private BitmapRegionDecoder(long decoder) {
         mNativeBitmapRegionDecoder = decoder;
         mRecycled = false;
@@ -267,6 +269,7 @@
     private static native int nativeGetHeight(long lbm);
     private static native void nativeClean(long lbm);
 
+    @UnsupportedAppUsage
     private static native BitmapRegionDecoder nativeNewInstance(
             byte[] data, int offset, int length, boolean isShareable);
     private static native BitmapRegionDecoder nativeNewInstance(
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 5577f53..bcf7229 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 
 /**
  * Shader used to draw a bitmap as a texture. The bitmap can be repeated or
@@ -28,9 +29,12 @@
      * @hide
      */
     @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
+    @UnsupportedAppUsage
     public Bitmap mBitmap;
 
+    @UnsupportedAppUsage
     private int mTileX;
+    @UnsupportedAppUsage
     private int mTileY;
 
     /**
diff --git a/graphics/java/android/graphics/Camera.java b/graphics/java/android/graphics/Camera.java
index 60588d0..3388941 100644
--- a/graphics/java/android/graphics/Camera.java
+++ b/graphics/java/android/graphics/Camera.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * A camera instance can be used to compute 3D transformations and
  * generate a matrix that can be applied, for instance, on a
@@ -174,5 +176,6 @@
     private native void nativeGetMatrix(long native_matrix);
     private native void nativeApplyToCanvas(long native_canvas);
 
+    @UnsupportedAppUsage
     long native_instance;
 }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index a465eea..ef58c8f 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
 
 import dalvik.annotation.optimization.CriticalNative;
@@ -54,6 +55,7 @@
     public static boolean sCompatibilitySetBitmap = false;
 
     /** @hide */
+    @UnsupportedAppUsage
     public long getNativeCanvasWrapper() {
         return mNativeCanvasWrapper;
     }
@@ -62,6 +64,7 @@
     public boolean isRecordingFor(Object o) { return false; }
 
     // may be null
+    @UnsupportedAppUsage
     private Bitmap mBitmap;
 
     // optional field set by the caller
@@ -123,6 +126,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public Canvas(long nativeCanvas) {
         if (nativeCanvas == 0) {
             throw new IllegalStateException();
@@ -141,6 +145,7 @@
      * @hide
      */
     @Deprecated
+    @UnsupportedAppUsage
     protected GL getGL() {
         return null;
     }
@@ -269,6 +274,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setScreenDensity(int density) {
         mScreenDensity = density;
     }
@@ -1263,6 +1269,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void release() {
         mNativeCanvasWrapper = 0;
         if (mFinalizer != null) {
@@ -1276,6 +1283,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void freeCaches() {
         nFreeCaches();
     }
@@ -1285,6 +1293,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static void freeTextLayoutCaches() {
         nFreeTextLayoutCaches();
     }
@@ -1591,9 +1600,9 @@
      * Draw the specified circle using the specified paint. If radius is <= 0, then nothing will be
      * drawn. The circle will be filled or framed based on the Style in the paint.
      *
-     * @param cx The x-coordinate of the center of the cirle to be drawn
-     * @param cy The y-coordinate of the center of the cirle to be drawn
-     * @param radius The radius of the cirle to be drawn
+     * @param cx The x-coordinate of the center of the circle to be drawn
+     * @param cy The y-coordinate of the center of the circle to be drawn
+     * @param radius The radius of the circle to be drawn
      * @param paint The paint used to draw the circle
      */
     public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
diff --git a/graphics/java/android/graphics/CanvasProperty.java b/graphics/java/android/graphics/CanvasProperty.java
index ea3886c..1275e08 100644
--- a/graphics/java/android/graphics/CanvasProperty.java
+++ b/graphics/java/android/graphics/CanvasProperty.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import com.android.internal.util.VirtualRefBasePtr;
 
 /**
@@ -26,10 +27,12 @@
 
     private VirtualRefBasePtr mProperty;
 
+    @UnsupportedAppUsage
     public static CanvasProperty<Float> createFloat(float initialValue) {
         return new CanvasProperty<Float>(nCreateFloat(initialValue));
     }
 
+    @UnsupportedAppUsage
     public static CanvasProperty<Paint> createPaint(Paint initialValue) {
         return new CanvasProperty<Paint>(nCreatePaint(initialValue.getNativeInstance()));
     }
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 9201a2e..0f7980c 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 /**
  * A color filter that transforms colors through a 4x5 color matrix. This filter
@@ -26,6 +27,7 @@
  * @see ColorMatrix
  */
 public class ColorMatrixColorFilter extends ColorFilter {
+    @UnsupportedAppUsage
     private final ColorMatrix mMatrix = new ColorMatrix();
 
     /**
@@ -76,6 +78,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setColorMatrix(@Nullable ColorMatrix matrix) {
         discardNativeInstance();
         if (matrix == null) {
@@ -104,6 +107,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setColorMatrixArray(@Nullable float[] array) {
         // called '...Array' so that passing null isn't ambiguous
         discardNativeInstance();
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index c69eb32..229923c 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.graphics.fonts.FontVariationAxis;
 import android.text.TextUtils;
@@ -51,16 +52,19 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public long mNativePtr;
 
     // Points native font family builder. Must be zero after freezing this family.
     private long mBuilderPtr;
 
+    @UnsupportedAppUsage
     public FontFamily() {
         mBuilderPtr = nInitBuilder(null, 0);
         mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
     }
 
+    @UnsupportedAppUsage
     public FontFamily(@Nullable String[] langs, int variant) {
         final String langsString;
         if (langs == null || langs.length == 0) {
@@ -80,6 +84,7 @@
      * @return boolean returns false if some error happens in native code, e.g. broken font file is
      *                 passed, etc.
      */
+    @UnsupportedAppUsage
     public boolean freeze() {
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("This FontFamily is already frozen");
@@ -93,6 +98,7 @@
         return mNativePtr != 0;
     }
 
+    @UnsupportedAppUsage
     public void abortCreation() {
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("This FontFamily is already frozen or abandoned");
@@ -122,6 +128,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes,
             int weight, int italic) {
         if (mBuilderPtr == 0) {
@@ -147,6 +154,7 @@
      *            using the OS/2 table in the font.
      * @return
      */
+    @UnsupportedAppUsage
     public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
             boolean isAsset, int ttcIndex, int weight, int isItalic,
             FontVariationAxis[] axes) {
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 431d0e0..e3e8380 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontVariationAxis;
 import android.text.FontConfig;
 import android.util.Xml;
@@ -37,6 +38,7 @@
 public class FontListParser {
 
     /* Parse fallback list (no names) */
+    @UnsupportedAppUsage
     public static FontConfig parse(InputStream in) throws XmlPullParserException, IOException {
         try {
             XmlPullParser parser = Xml.newPullParser();
diff --git a/graphics/java/android/graphics/GraphicBuffer.java b/graphics/java/android/graphics/GraphicBuffer.java
index 53d2177..7408683 100644
--- a/graphics/java/android/graphics/GraphicBuffer.java
+++ b/graphics/java/android/graphics/GraphicBuffer.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -53,6 +54,7 @@
     private final int mFormat;
     private final int mUsage;
     // Note: do not rename, this field is used by native code
+    @UnsupportedAppUsage
     private final long mNativeObject;
 
     // These two fields are only used by lock/unlockCanvas()
@@ -84,6 +86,7 @@
     /**
      * Private use only. See {@link #create(int, int, int, int)}.
      */
+    @UnsupportedAppUsage
     private GraphicBuffer(int width, int height, int format, int usage, long nativeObject) {
         mWidth = width;
         mHeight = height;
@@ -96,6 +99,7 @@
      * For SurfaceControl JNI.
      * @hide
      */
+    @UnsupportedAppUsage
     public static GraphicBuffer createFromExisting(int width, int height,
             int format, int usage, long unwrappedNativeObject) {
         long nativeObject = nWrapGraphicBuffer(unwrappedNativeObject);
@@ -274,6 +278,7 @@
         nWriteGraphicBufferToParcel(mNativeObject, dest);
     }
 
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<GraphicBuffer> CREATOR =
             new Parcelable.Creator<GraphicBuffer>() {
         public GraphicBuffer createFromParcel(Parcel in) {
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 098f100..7bed1ac 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -28,6 +28,7 @@
 import android.annotation.Nullable;
 import android.annotation.Px;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.content.ContentResolver;
 import android.content.res.AssetFileDescriptor;
@@ -1856,6 +1857,7 @@
      * Private method called by JNI.
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private int postProcessAndRelease(@NonNull Canvas canvas) {
         try {
             return mPostProcessor.onPostProcess(canvas);
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 43fd270..9546a4a 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 public class ImageFormat {
     /*
      * these constants are chosen to be binary compatible with their previous
@@ -103,6 +105,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static final int Y8 = 0x20203859;
 
     /**
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index 1578ffb..62a890f 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -22,6 +22,7 @@
 package android.graphics;
 
 import android.annotation.ColorInt;
+import android.annotation.UnsupportedAppUsage;
 
 /**
  * A color filter that can be used to simulate simple lighting effects.
@@ -72,6 +73,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setColorMultiply(@ColorInt int mul) {
         if (mMul != mul) {
             mMul = mul;
@@ -97,6 +99,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setColorAdd(@ColorInt int add) {
         if (mAdd != add) {
             mAdd = add;
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 7139efe..7e6fc35 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 public class LinearGradient extends Shader {
 
@@ -31,15 +32,24 @@
      */
     private int mType;
 
+    @UnsupportedAppUsage
     private float mX0;
+    @UnsupportedAppUsage
     private float mY0;
+    @UnsupportedAppUsage
     private float mX1;
+    @UnsupportedAppUsage
     private float mY1;
+    @UnsupportedAppUsage
     private int[] mColors;
+    @UnsupportedAppUsage
     private float[] mPositions;
+    @UnsupportedAppUsage
     private int mColor0;
+    @UnsupportedAppUsage
     private int mColor1;
 
+    @UnsupportedAppUsage
     private TileMode mTileMode;
 
     /**
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index 486070c..f8cb366 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -21,6 +21,7 @@
 
 import libcore.util.NativeAllocationRegistry;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.PrintWriter;
 
 /**
@@ -39,6 +40,7 @@
     public static final int MPERSP_2 = 8;   //!< use with getValues/setValues
 
     /** @hide */
+    @UnsupportedAppUsage
     public final static Matrix IDENTITY_MATRIX = new Matrix() {
         void oops() {
             throw new IllegalStateException("Matrix can not be modified");
@@ -231,6 +233,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public final long native_instance;
 
     /**
diff --git a/graphics/java/android/graphics/Movie.java b/graphics/java/android/graphics/Movie.java
index 83857be..4c953b5 100644
--- a/graphics/java/android/graphics/Movie.java
+++ b/graphics/java/android/graphics/Movie.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 
 import java.io.FileInputStream;
@@ -25,8 +26,10 @@
  * @deprecated Prefer {@link android.graphics.drawable.AnimatedImageDrawable}.
  */
 public class Movie {
+    @UnsupportedAppUsage
     private long mNativeMovie;
 
+    @UnsupportedAppUsage
     private Movie(long nativeMovie) {
         if (nativeMovie == 0) {
             throw new RuntimeException("native movie creation failed");
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index b6a209f..800247a 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * The NinePatch class permits drawing a bitmap in nine or more sections.
  * Essentially, it allows the creation of custom graphics that will scale the
@@ -41,6 +43,7 @@
      */
     public static class InsetStruct {
         @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
+        @UnsupportedAppUsage
         InsetStruct(int opticalLeft, int opticalTop, int opticalRight, int opticalBottom,
                 int outlineLeft, int outlineTop, int outlineRight, int outlineBottom,
                 float outlineRadius, int outlineAlpha, float decodeScale) {
@@ -77,6 +80,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private final Bitmap mBitmap;
 
     /**
@@ -84,6 +88,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long mNativeChunk;
 
     private Paint mPaint;
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 1c85df0..98c990a 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -19,6 +19,7 @@
 import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.drawable.Drawable;
 
 import java.lang.annotation.Retention;
@@ -66,6 +67,7 @@
     public Path mPath;
 
     /** @hide */
+    @UnsupportedAppUsage
     public final Rect mRect = new Rect();
     /** @hide */
     public float mRadius = RADIUS_UNDEFINED;
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 42dac38..9dab536 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontVariationAxis;
 import android.os.LocaleList;
 import android.text.GraphicsOperations;
@@ -44,6 +45,7 @@
  */
 public class Paint {
 
+    @UnsupportedAppUsage
     private long mNativePaint;
     private long mNativeShader;
     private long mNativeColorFilter;
@@ -61,6 +63,7 @@
     private MaskFilter  mMaskFilter;
     private PathEffect  mPathEffect;
     private Shader      mShader;
+    @UnsupportedAppUsage
     private Typeface    mTypeface;
     private Xfermode    mXfermode;
 
@@ -618,6 +621,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setCompatibilityScaling(float factor) {
         if (factor == 1.0) {
             mHasCompatScaling = false;
@@ -635,6 +639,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public long getNativeInstance() {
         long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance();
         if (newNativeShader != mNativeShader) {
@@ -1718,6 +1723,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void setHyphenEdit(int hyphen) {
         nSetHyphenEdit(mNativePaint, hyphen);
     }
@@ -2261,6 +2267,7 @@
      * @see #getTextRunAdvances(String, int, int, int, int, boolean, float[], int)
      * @hide
      */
+    @UnsupportedAppUsage
     public float getTextRunAdvances(char[] chars, int index, int count,
             int contextIndex, int contextCount, boolean isRtl, float[] advances,
             int advancesIndex) {
@@ -2451,6 +2458,7 @@
      * @return the offset of the next position, or -1
      * @hide
      */
+    @UnsupportedAppUsage
     public int getTextRunCursor(char[] text, int contextStart, int contextLength,
             int dir, int offset, int cursorOpt) {
         int contextEnd = contextStart + contextLength;
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 1652f64..405ab0b 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.UnsupportedAppUsage;
 
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
@@ -46,10 +47,12 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean isSimplePath = true;
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public Region rects;
     private Direction mLastDirection = null;
 
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index f2d0227..f7acb11 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import java.io.InputStream;
 import java.io.OutputStream;
 
@@ -32,6 +33,7 @@
  */
 public class Picture {
     private PictureCanvas mRecordingCanvas;
+    @UnsupportedAppUsage
     private long mNativePicture;
     private boolean mRequiresHwAcceleration;
 
diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java
index d7d3049..fba5043 100644
--- a/graphics/java/android/graphics/PorterDuff.java
+++ b/graphics/java/android/graphics/PorterDuff.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * <p>This class contains the list of alpha compositing and blending modes
  * that can be passed to {@link PorterDuffXfermode}, a specialized implementation
@@ -364,6 +366,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public final int nativeInt;
     }
 
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index 88a6322..6665220 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 
 /**
  * A color filter that can be used to tint the source pixels using a single
@@ -50,6 +51,7 @@
      * @hide
      */
     @ColorInt
+    @UnsupportedAppUsage
     public int getColor() {
         return mColor;
     }
@@ -62,6 +64,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public PorterDuff.Mode getMode() {
         return mMode;
     }
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index f4b1191..41d2628 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.ColorInt;
+import android.annotation.UnsupportedAppUsage;
 
 public class RadialGradient extends Shader {
 
@@ -31,14 +32,22 @@
      */
     private int mType;
 
+    @UnsupportedAppUsage
     private float mX;
+    @UnsupportedAppUsage
     private float mY;
+    @UnsupportedAppUsage
     private float mRadius;
+    @UnsupportedAppUsage
     private int[] mColors;
+    @UnsupportedAppUsage
     private float[] mPositions;
+    @UnsupportedAppUsage
     private int mCenterColor;
+    @UnsupportedAppUsage
     private int mEdgeColor;
 
+    @UnsupportedAppUsage
     private TileMode mTileMode;
 
     /**
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 56a6820..4fec33f 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -19,6 +19,7 @@
 import android.annotation.CheckResult;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -206,6 +207,7 @@
      * Print short representation to given writer.
      * @hide
      */
+    @UnsupportedAppUsage
     public void printShortString(@NonNull PrintWriter pw) {
         pw.print('['); pw.print(left); pw.print(',');
         pw.print(top); pw.print("]["); pw.print(right);
@@ -694,6 +696,7 @@
      * Scales up the rect by the given scale.
      * @hide
      */
+    @UnsupportedAppUsage
     public void scale(float scale) {
         if (scale != 1.0f) {
             left = (int) (left * scale + 0.5f);
diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java
index b27fadd..29d9367 100644
--- a/graphics/java/android/graphics/Region.java
+++ b/graphics/java/android/graphics/Region.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Pools.SynchronizedPool;
@@ -31,6 +32,7 @@
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public long mNativeRegion;
 
     // the native values for these must match up with the enum in SkRegion.h
@@ -49,6 +51,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         public final int nativeInt;
     }
 
@@ -239,6 +242,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void scale(float scale) {
         scale(scale, null);
     }
@@ -333,6 +337,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public void recycle() {
         setEmpty();
         sPool.release(this);
@@ -406,6 +411,7 @@
 
     /* add dummy parameter so constructor can be called from jni without
        triggering 'not cloneable' exception */
+    @UnsupportedAppUsage
     private Region(long ni, int dummy) {
         this(ni);
     }
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 40288f5..40bcc9e 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -72,6 +73,7 @@
         TileMode(int nativeInt) {
             this.nativeInt = nativeInt;
         }
+        @UnsupportedAppUsage
         final int nativeInt;
     }
 
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 1eebd26..99f440d 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -68,13 +69,17 @@
  */
 public class SurfaceTexture {
     private final Looper mCreatorLooper;
+    @UnsupportedAppUsage
     private Handler mOnFrameAvailableHandler;
 
     /**
      * These fields are used by native code, do not access or modify.
      */
+    @UnsupportedAppUsage
     private long mSurfaceTexture;
+    @UnsupportedAppUsage
     private long mProducer;
+    @UnsupportedAppUsage
     private long mFrameAvailableListener;
 
     private boolean mIsSingleBuffered;
@@ -378,6 +383,7 @@
      * This method is invoked from native code only.
      */
     @SuppressWarnings({"UnusedDeclaration"})
+    @UnsupportedAppUsage
     private static void postEventFromNative(WeakReference<SurfaceTexture> weakSelf) {
         SurfaceTexture st = weakSelf.get();
         if (st != null) {
@@ -405,6 +411,7 @@
     private native void nativeSetDefaultBufferSize(int width, int height);
     private native void nativeUpdateTexImage();
     private native void nativeReleaseTexImage();
+    @UnsupportedAppUsage
     private native int nativeDetachFromGLContext();
     private native int nativeAttachToGLContext(int texName);
     private native void nativeRelease();
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index b6b80b4..f944d85 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 
 public class SweepGradient extends Shader {
 
@@ -31,11 +32,17 @@
      */
     private int mType;
 
+    @UnsupportedAppUsage
     private float mCx;
+    @UnsupportedAppUsage
     private float mCy;
+    @UnsupportedAppUsage
     private int[] mColors;
+    @UnsupportedAppUsage
     private float[] mPositions;
+    @UnsupportedAppUsage
     private int mColor0;
+    @UnsupportedAppUsage
     private int mColor1;
 
     /**
diff --git a/graphics/java/android/graphics/TableMaskFilter.java b/graphics/java/android/graphics/TableMaskFilter.java
index d0c1438..d81c491 100644
--- a/graphics/java/android/graphics/TableMaskFilter.java
+++ b/graphics/java/android/graphics/TableMaskFilter.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * @hide
  */
@@ -32,6 +34,7 @@
         native_instance = ni;
     }
     
+    @UnsupportedAppUsage
     public static TableMaskFilter CreateClipTable(int min, int max) {
         return new TableMaskFilter(nativeNewClip(min, max));
     }
diff --git a/graphics/java/android/graphics/TemporaryBuffer.java b/graphics/java/android/graphics/TemporaryBuffer.java
index 36a2275..0ae2c70 100644
--- a/graphics/java/android/graphics/TemporaryBuffer.java
+++ b/graphics/java/android/graphics/TemporaryBuffer.java
@@ -16,12 +16,14 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
 import com.android.internal.util.ArrayUtils;
 
 /**
  * @hide
  */
 public class TemporaryBuffer {
+    @UnsupportedAppUsage
     public static char[] obtain(int len) {
         char[] buf;
 
@@ -37,6 +39,7 @@
         return buf;
     }
 
+    @UnsupportedAppUsage
     public static void recycle(char[] temp) {
         if (temp.length > 1000) return;
 
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 18dd97f..522d7a5 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -25,6 +25,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetManager;
 import android.graphics.fonts.FontVariationAxis;
 import android.net.Uri;
@@ -93,6 +94,7 @@
     /** The NORMAL style of the default monospace typeface. */
     public static final Typeface MONOSPACE;
 
+    @UnsupportedAppUsage
     static Typeface[] sDefaults;
 
     /**
@@ -119,12 +121,15 @@
     private static final Object sDynamicCacheLock = new Object();
 
     static Typeface sDefaultTypeface;
+    @UnsupportedAppUsage
     static final Map<String, Typeface> sSystemFontMap;
+    @UnsupportedAppUsage
     static final Map<String, FontFamily[]> sSystemFallbackMap;
 
     /**
      * @hide
      */
+    @UnsupportedAppUsage
     public long native_instance;
 
     /** @hide */
@@ -139,6 +144,7 @@
     public static final int BOLD_ITALIC = 3;
     /** @hide */ public static final int STYLE_MASK = 0x03;
 
+    @UnsupportedAppUsage
     private @Style int mStyle = 0;
 
     /**
@@ -162,6 +168,7 @@
     private int[] mSupportedAxes;
     private static final int[] EMPTY_AXES = {};
 
+    @UnsupportedAppUsage
     private static void setDefault(Typeface t) {
         sDefaultTypeface = t;
         nativeSetDefault(t.native_instance);
@@ -891,6 +898,7 @@
      *
      * @param families array of font families
      */
+    @UnsupportedAppUsage
     private static Typeface createFromFamilies(FontFamily[] families) {
         long[] ptrArray = new long[families.length];
         for (int i = 0; i < families.length; i++) {
@@ -904,6 +912,7 @@
      * This method is used by supportlib-v27.
      * TODO: Remove private API use in supportlib: http://b/72665240
      */
+    @UnsupportedAppUsage
     private static Typeface createFromFamiliesWithDefault(FontFamily[] families, int weight,
                 int italic) {
         return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, weight, italic);
@@ -922,6 +931,7 @@
      *               closest to the regular weight and upright font is used.
      * @param families array of font families
      */
+    @UnsupportedAppUsage
     private static Typeface createFromFamiliesWithDefault(FontFamily[] families,
                 String fallbackName, int weight, int italic) {
         FontFamily[] fallback = sSystemFallbackMap.get(fallbackName);
@@ -939,6 +949,7 @@
     }
 
     // don't allow clients to call this directly
+    @UnsupportedAppUsage
     private Typeface(long ni) {
         if (ni == 0) {
             throw new RuntimeException("native typeface cannot be made");
@@ -1197,7 +1208,9 @@
     // TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[]
     private static native long nativeCreateFromTypefaceWithVariation(
             long native_instance, List<FontVariationAxis> axes);
+    @UnsupportedAppUsage
     private static native long nativeCreateWeightAlias(long native_instance, int weight);
+    @UnsupportedAppUsage
     private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
     private static native int[] nativeGetSupportedAxes(long native_instance);
 
diff --git a/graphics/java/android/graphics/Xfermode.java b/graphics/java/android/graphics/Xfermode.java
index a5da5d0..6f4adfd 100644
--- a/graphics/java/android/graphics/Xfermode.java
+++ b/graphics/java/android/graphics/Xfermode.java
@@ -21,6 +21,8 @@
 
 package android.graphics;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Xfermode is the base class for objects that are called to implement custom
  * "transfer-modes" in the drawing pipeline. The static function Create(Modes)
@@ -30,5 +32,6 @@
  */
 public class Xfermode {
     static final int DEFAULT = PorterDuff.Mode.SRC_OVER.nativeInt;
+    @UnsupportedAppUsage
     int porterDuffMode = DEFAULT;
 }
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index 4f467d9..3aaec31 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -19,6 +19,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -562,6 +563,7 @@
      *  callback, so no need to post.
      */
     @SuppressWarnings("unused")
+    @UnsupportedAppUsage
     private void onAnimationEnd() {
         if (mAnimationCallbacks != null) {
             for (Animatable2.AnimationCallback callback : mAnimationCallbacks) {
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index d714ca8..b29fd4d 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.content.res.Resources;
@@ -202,11 +203,13 @@
                 R.styleable.AnimatedRotateDrawable_frameDuration, state.mFrameDuration));
     }
 
+    @UnsupportedAppUsage
     public void setFramesCount(int framesCount) {
         mState.mFramesCount = framesCount;
         mIncrement = 360.0f / mState.mFramesCount;
     }
 
+    @UnsupportedAppUsage
     public void setFramesDuration(int framesDuration) {
         mState.mFrameDuration = framesDuration;
     }
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 3ed6a78..00380c5 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -20,6 +20,7 @@
 import android.animation.TimeInterpolator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -66,6 +67,7 @@
     private static final String ELEMENT_TRANSITION = "transition";
     private static final String ELEMENT_ITEM = "item";
 
+    @UnsupportedAppUsage
     private AnimatedStateListState mState;
 
     /** The currently running transition, if any. */
@@ -558,7 +560,9 @@
 
         int[] mAnimThemeAttrs;
 
+        @UnsupportedAppUsage
         LongSparseLongArray mTransitions;
+        @UnsupportedAppUsage
         SparseIntArray mStateIds;
 
         AnimatedStateListState(@Nullable AnimatedStateListState orig,
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 8e9862c..76f2cfb 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -25,6 +25,7 @@
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
 import android.app.Application;
 import android.content.pm.ActivityInfo.Config;
@@ -305,6 +306,7 @@
     private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
 
     /** Local, mutable animator set. */
+    @UnsupportedAppUsage
     private VectorDrawableAnimator mAnimatorSet;
 
     /**
@@ -313,6 +315,7 @@
      */
     private Resources mRes;
 
+    @UnsupportedAppUsage
     private AnimatedVectorDrawableState mAnimatedVectorState;
 
     /** The animator set that is parsed from the xml. */
@@ -641,6 +644,7 @@
      * Force to animate on UI thread.
      * @hide
      */
+    @UnsupportedAppUsage
     public void forceAnimationOnUI() {
         if (mAnimatorSet instanceof VectorDrawableAnimatorRT) {
             VectorDrawableAnimatorRT animator = (VectorDrawableAnimatorRT) mAnimatorSet;
@@ -1771,6 +1775,7 @@
         }
 
         // onFinished: should be called from native
+        @UnsupportedAppUsage
         private static void callOnFinished(VectorDrawableAnimatorRT set, int id) {
             set.onAnimationEnd(id);
         }
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 0fd1741..57764c2 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -24,6 +24,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.Resources.Theme;
@@ -88,6 +89,7 @@
     private AnimationState mAnimationState;
 
     /** The current frame, ranging from 0 to {@link #mAnimationState#getChildCount() - 1} */
+    @UnsupportedAppUsage
     private int mCurFrame = 0;
 
     /** Whether the drawable has an animation callback posted. */
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 99bed60..9761901 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -87,9 +88,11 @@
 
     private final Rect mDstRect = new Rect();   // #updateDstRectAndInsetsIfDirty() sets this
 
+    @UnsupportedAppUsage
     private BitmapState mBitmapState;
     private PorterDuffColorFilter mTintFilter;
 
+    @UnsupportedAppUsage
     private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
 
     private boolean mDstRectAndInsetsDirty = true;
@@ -237,6 +240,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public void setBitmap(Bitmap bitmap) {
         if (mBitmapState.mBitmap != bitmap) {
             mBitmapState.mBitmap = bitmap;
@@ -692,6 +696,7 @@
     /**
      * @hide only needed by a hack within ProgressBar
      */
+    @UnsupportedAppUsage
     public ColorStateList getTint() {
         return mBitmapState.mTint;
     }
@@ -699,6 +704,7 @@
     /**
      * @hide only needed by a hack within ProgressBar
      */
+    @UnsupportedAppUsage
     public Mode getTintMode() {
         return mBitmapState.mTintMode;
     }
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index d925b6b..31fdb02 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.Resources.Theme;
@@ -58,6 +59,7 @@
 
     private final Rect mTmpRect = new Rect();
 
+    @UnsupportedAppUsage
     private ClipState mState;
 
     ClipDrawable() {
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index a601d6d..18b41fa 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -52,6 +53,7 @@
  * @attr ref android.R.styleable#ColorDrawable_color
  */
 public class ColorDrawable extends Drawable {
+    @UnsupportedAppUsage
     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 
     @ViewDebug.ExportedProperty(deepExport = true, prefix = "state_")
@@ -336,6 +338,7 @@
         int[] mThemeAttrs;
         int mBaseColor; // base color, independent of setAlpha()
         @ViewDebug.ExportedProperty
+        @UnsupportedAppUsage
         int mUseColor;  // basecolor modulated by setAlpha()
         @Config int mChangingConfigurations;
         ColorStateList mTint = null;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 986d0c1..e1f7263 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -22,6 +22,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -186,6 +187,7 @@
     private int mLevel = 0;
     private @Config int mChangingConfigurations = 0;
     private Rect mBounds = ZERO_BOUNDS_RECT;  // lazily becomes a new Rect()
+    @UnsupportedAppUsage
     private WeakReference<Callback> mCallback = null;
     private boolean mVisible = true;
 
@@ -204,6 +206,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     protected int mSrcDensityOverride = 0;
 
     /**
@@ -714,6 +717,7 @@
      *
      * @hide magic!
      */
+    @UnsupportedAppUsage
     public boolean isProjected() {
         return false;
     }
@@ -1389,6 +1393,7 @@
      * @throws XmlPullParserException
      * @throws IOException
      */
+    @UnsupportedAppUsage
     void inflateWithAttributes(@NonNull @SuppressWarnings("unused") Resources r,
             @NonNull @SuppressWarnings("unused") XmlPullParser parser, @NonNull TypedArray attrs,
             @AttrRes int visibleAttr) throws XmlPullParserException, IOException {
@@ -1508,6 +1513,7 @@
      * Ensures the tint filter is consistent with the current tint color and
      * mode.
      */
+    @UnsupportedAppUsage
     @Nullable PorterDuffColorFilter updateTintFilter(@Nullable PorterDuffColorFilter tintFilter,
             @Nullable ColorStateList tint, @Nullable PorterDuff.Mode tintMode) {
         if (tint == null || tintMode == null) {
@@ -1613,6 +1619,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     public static PorterDuff.Mode parseTintMode(int value, Mode defaultMode) {
         switch (value) {
             case 3: return Mode.SRC_OVER;
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index e7b383a..10f6fae 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable;
 
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -54,9 +55,11 @@
      * to improve the quality at negligible cost.
      */
     private static final boolean DEFAULT_DITHER = true;
+    @UnsupportedAppUsage
     private DrawableContainerState mDrawableContainerState;
     private Rect mHotspotBounds;
     private Drawable mCurrDrawable;
+    @UnsupportedAppUsage
     private Drawable mLastDrawable;
     private int mAlpha = 0xFF;
 
@@ -686,11 +689,13 @@
         @Config int mChildrenChangingConfigurations;
 
         SparseArray<ConstantState> mDrawableFutures;
+        @UnsupportedAppUsage
         Drawable[] mDrawables;
         int mNumChildren;
 
         boolean mVariablePadding = false;
         boolean mCheckedPadding;
+        @UnsupportedAppUsage
         Rect mConstantPadding;
 
         boolean mConstantSize = false;
@@ -720,6 +725,7 @@
         boolean mAutoMirrored;
 
         ColorFilter mColorFilter;
+        @UnsupportedAppUsage
         boolean mHasColorFilter;
 
         ColorStateList mTintList;
@@ -730,6 +736,7 @@
         /**
          * @hide
          */
+        @UnsupportedAppUsage
         protected DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
                 Resources res) {
             mOwner = owner;
diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java
index 0ee9071..bad3791 100644
--- a/graphics/java/android/graphics/drawable/DrawableInflater.java
+++ b/graphics/java/android/graphics/drawable/DrawableInflater.java
@@ -22,6 +22,7 @@
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -49,6 +50,7 @@
             new HashMap<>();
 
     private final Resources mRes;
+    @UnsupportedAppUsage
     private final ClassLoader mClassLoader;
 
     /**
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index a907ca5..4ee45bf 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -46,6 +47,7 @@
  * Drawable container with only one child element.
  */
 public abstract class DrawableWrapper extends Drawable implements Drawable.Callback {
+    @UnsupportedAppUsage
     private DrawableWrapperState mState;
     private Drawable mDrawable;
     private boolean mMutated;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 5629389..8740234 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -20,6 +20,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -155,10 +156,14 @@
     private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
     private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
 
+    @UnsupportedAppUsage
     private GradientState mGradientState;
 
+    @UnsupportedAppUsage
     private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    @UnsupportedAppUsage
     private Rect mPadding;
+    @UnsupportedAppUsage
     private Paint mStrokePaint;   // optional, set by the caller
     private ColorFilter mColorFilter;   // optional, set by the caller
     private PorterDuffColorFilter mTintFilter;
@@ -1792,27 +1797,46 @@
 
     final static class GradientState extends ConstantState {
         public @Config int mChangingConfigurations;
+        @UnsupportedAppUsage
         public @Shape int mShape = RECTANGLE;
+        @UnsupportedAppUsage
         public @GradientType int mGradient = LINEAR_GRADIENT;
+        @UnsupportedAppUsage
         public int mAngle = 0;
+        @UnsupportedAppUsage
         public Orientation mOrientation;
+        @UnsupportedAppUsage
         public ColorStateList mSolidColors;
         public ColorStateList mStrokeColors;
+        @UnsupportedAppUsage
         public @ColorInt int[] mGradientColors;
         public @ColorInt int[] mTempColors; // no need to copy
         public float[] mTempPositions; // no need to copy
+        @UnsupportedAppUsage
         public float[] mPositions;
+        @UnsupportedAppUsage
         public int mStrokeWidth = -1; // if >= 0 use stroking.
+        @UnsupportedAppUsage
         public float mStrokeDashWidth = 0.0f;
+        @UnsupportedAppUsage
         public float mStrokeDashGap = 0.0f;
+        @UnsupportedAppUsage
         public float mRadius = 0.0f; // use this if mRadiusArray is null
+        @UnsupportedAppUsage
         public float[] mRadiusArray = null;
+        @UnsupportedAppUsage
         public Rect mPadding = null;
+        @UnsupportedAppUsage
         public int mWidth = -1;
+        @UnsupportedAppUsage
         public int mHeight = -1;
+        @UnsupportedAppUsage
         public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO;
+        @UnsupportedAppUsage
         public float mThicknessRatio = DEFAULT_THICKNESS_RATIO;
+        @UnsupportedAppUsage
         public int mInnerRadius = -1;
+        @UnsupportedAppUsage
         public int mThickness = -1;
         public boolean mDither = false;
         public Insets mOpticalInsets = Insets.NONE;
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 361fe0b..accc081 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -21,6 +21,7 @@
 import android.annotation.IdRes;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -99,6 +100,7 @@
 
     private static final int VERSION_STREAM_SERIALIZER = 1;
 
+    @UnsupportedAppUsage
     private final int mType;
 
     private ColorStateList mTintList;
@@ -115,6 +117,7 @@
 
     // TYPE_RESOURCE: package name
     // TYPE_URI: uri string
+    @UnsupportedAppUsage
     private String          mString1;
 
     // TYPE_RESOURCE: resId
@@ -139,6 +142,7 @@
      * @return The {@link android.graphics.Bitmap} held by this {@link #TYPE_BITMAP} Icon.
      * @hide
      */
+    @UnsupportedAppUsage
     public Bitmap getBitmap() {
         if (mType != TYPE_BITMAP && mType != TYPE_ADAPTIVE_BITMAP) {
             throw new IllegalStateException("called getBitmap() on " + this);
@@ -154,6 +158,7 @@
      * @return The length of the compressed bitmap byte array held by this {@link #TYPE_DATA} Icon.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDataLength() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataLength() on " + this);
@@ -168,6 +173,7 @@
      * valid compressed bitmap data is found.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getDataOffset() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataOffset() on " + this);
@@ -182,6 +188,7 @@
      * bitmap data.
      * @hide
      */
+    @UnsupportedAppUsage
     public byte[] getDataBytes() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataBytes() on " + this);
@@ -195,6 +202,7 @@
      * @return The {@link android.content.res.Resources} for this {@link #TYPE_RESOURCE} Icon.
      * @hide
      */
+    @UnsupportedAppUsage
     public Resources getResources() {
         if (mType != TYPE_RESOURCE) {
             throw new IllegalStateException("called getResources() on " + this);
@@ -560,6 +568,7 @@
      * Version of createWithResource that takes Resources. Do not use.
      * @hide
      */
+    @UnsupportedAppUsage
     public static Icon createWithResource(Resources res, @DrawableRes int resId) {
         if (res == null) {
             throw new IllegalArgumentException("Resource must not be null.");
@@ -692,6 +701,7 @@
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     public boolean hasTint() {
         return (mTintList != null) || (mTintMode != DEFAULT_TINT_MODE);
     }
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index ade4294..bc8a4cb 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -57,6 +58,7 @@
     private final Rect mTmpRect = new Rect();
     private final Rect mTmpInsetRect = new Rect();
 
+    @UnsupportedAppUsage
     private InsetState mState;
 
     /**
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 4725c2c..b4392c8 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -93,6 +94,7 @@
     public static final int INSET_UNDEFINED = Integer.MIN_VALUE;
 
     @NonNull
+    @UnsupportedAppUsage
     LayerState mLayerState;
 
     private int[] mPaddingL;
@@ -428,6 +430,7 @@
      * @param layer The layer to add.
      * @return The index of the layer.
      */
+    @UnsupportedAppUsage
     int addLayer(@NonNull ChildDrawable layer) {
         final LayerState st = mLayerState;
         final int N = st.mChildren != null ? st.mChildren.length : 0;
@@ -1739,6 +1742,7 @@
     /**
      * Ensures the child padding caches are large enough.
      */
+    @UnsupportedAppUsage
     void ensurePadding() {
         final int N = mLayerState.mNumChildren;
         if (mPaddingL != null && mPaddingL.length >= N) {
@@ -1820,6 +1824,7 @@
     }
 
     static class ChildDrawable {
+        @UnsupportedAppUsage
         public Drawable mDrawable;
         public int[] mThemeAttrs;
         public int mDensity = DisplayMetrics.DENSITY_DEFAULT;
@@ -1922,6 +1927,7 @@
         private int[] mThemeAttrs;
 
         int mNumChildren;
+        @UnsupportedAppUsage
         ChildDrawable[] mChildren;
 
         int mDensity;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 7f23cea..b534771 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -70,6 +71,7 @@
     /** Temporary rect used for density scaling. */
     private Rect mTempRect;
 
+    @UnsupportedAppUsage
     private NinePatchState mNinePatchState;
     private PorterDuffColorFilter mTintFilter;
     private Rect mPadding;
@@ -588,6 +590,7 @@
         @Config int mChangingConfigurations;
 
         // Values loaded during inflation.
+        @UnsupportedAppUsage
         NinePatch mNinePatch = null;
         ColorStateList mTint = null;
         Mode mTintMode = DEFAULT_TINT_MODE;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 266a6ac..1540cc2 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -120,6 +121,7 @@
     private final Rect mDirtyBounds = new Rect();
 
     /** Mirrors mLayerState with some extra information. */
+    @UnsupportedAppUsage
     private RippleState mState;
 
     /** The masking layer, e.g. the layer with id R.id.mask. */
@@ -157,6 +159,7 @@
     private Paint mRipplePaint;
 
     /** Target density of the display into which ripples are drawn. */
+    @UnsupportedAppUsage
     private int mDensity;
 
     /** Whether bounds are being overridden. */
@@ -857,6 +860,7 @@
         mMask.draw(canvas);
     }
 
+    @UnsupportedAppUsage
     Paint getRipplePaint() {
         if (mRipplePaint == null) {
             mRipplePaint = new Paint();
@@ -945,6 +949,7 @@
      * @param forceSoftware true if RenderThread animations should be disabled, false otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public void setForceSoftware(boolean forceSoftware) {
         mForceSoftware = forceSoftware;
     }
@@ -975,6 +980,7 @@
 
     static class RippleState extends LayerState {
         int[] mTouchThemeAttrs;
+        @UnsupportedAppUsage
         ColorStateList mColor = ColorStateList.valueOf(Color.MAGENTA);
         int mMaxRadius = RADIUS_AUTO;
 
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index c0dfe77..db5f082 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.content.res.Resources;
@@ -54,6 +55,7 @@
 public class RotateDrawable extends DrawableWrapper {
     private static final int MAX_LEVEL = 10000;
 
+    @UnsupportedAppUsage
     private RotateState mState;
 
     /**
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 51e143b..91ed061 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -66,6 +67,7 @@
 
     private final Rect mTmpRect = new Rect();
 
+    @UnsupportedAppUsage
     private ScaleState mState;
 
     ScaleDrawable() {
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 67c3412..8de8f81 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -63,6 +64,7 @@
 
     private static final boolean DEBUG = false;
 
+    @UnsupportedAppUsage
     private StateListState mStateListState;
     private boolean mMutated;
 
@@ -129,6 +131,7 @@
     /**
      * Updates the constant state from the values in the typed array.
      */
+    @UnsupportedAppUsage
     private void updateStateFromTypedArray(TypedArray a) {
         final StateListState state = mStateListState;
 
@@ -206,6 +209,7 @@
      * @param attrs The attribute set.
      * @return An array of state_ attributes.
      */
+    @UnsupportedAppUsage
     int[] extractStateSet(AttributeSet attrs) {
         int j = 0;
         final int numAttrs = attrs.getAttributeCount();
@@ -329,6 +333,7 @@
             mStateSets = stateSets;
         }
 
+        @UnsupportedAppUsage
         int addStateSet(int[] stateSet, Drawable drawable) {
             final int pos = addChild(drawable);
             mStateSets[pos] = stateSet;
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 3dfd680..276f366 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -65,10 +66,13 @@
     private boolean mReverse;
     private long mStartTimeMillis;
     private int mFrom;
+    @UnsupportedAppUsage
     private int mTo;
     private int mDuration;
     private int mOriginalDuration;
+    @UnsupportedAppUsage
     private int mAlpha = 0;
+    @UnsupportedAppUsage
     private boolean mCrossFade;
 
     /**
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index b5bd97f..040601c 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -16,6 +16,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.ComplexColor;
@@ -321,6 +322,7 @@
 
     private VectorDrawableState mVectorState;
 
+    @UnsupportedAppUsage
     private PorterDuffColorFilter mTintFilter;
     private ColorFilter mColorFilter;
 
@@ -389,6 +391,7 @@
         mMutated = false;
     }
 
+    @UnsupportedAppUsage
     Object getTargetByName(String name) {
         return mVectorState.mVGTargetsMap.get(name);
     }
@@ -867,6 +870,7 @@
         return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
     }
 
+    @UnsupportedAppUsage
     void setAllowCaching(boolean allowCaching) {
         nSetAllowCaching(mVectorState.getNativeRenderer(), allowCaching);
     }
@@ -1498,6 +1502,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setRotation(float rotation) {
             if (isTreeValid()) {
                 nSetRotation(mNativePtr, rotation);
@@ -1510,6 +1515,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setPivotX(float pivotX) {
             if (isTreeValid()) {
                 nSetPivotX(mNativePtr, pivotX);
@@ -1522,6 +1528,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setPivotY(float pivotY) {
             if (isTreeValid()) {
                 nSetPivotY(mNativePtr, pivotY);
@@ -1558,6 +1565,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setTranslateX(float translateX) {
             if (isTreeValid()) {
                 nSetTranslateX(mNativePtr, translateX);
@@ -1570,6 +1578,7 @@
         }
 
         @SuppressWarnings("unused")
+        @UnsupportedAppUsage
         public void setTranslateY(float translateY) {
             if (isTreeValid()) {
                 nSetTranslateY(mNativePtr, translateY);
diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java
index 1b7408a..2a902c5 100644
--- a/graphics/java/android/graphics/fonts/FontVariationAxis.java
+++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.text.TextUtils;
 
 import java.util.ArrayList;
@@ -27,8 +28,10 @@
  * Class that holds information about single font variation axis.
  */
 public final class FontVariationAxis {
+    @UnsupportedAppUsage
     private final int mTag;
     private final String mTagString;
+    @UnsupportedAppUsage
     private final float mStyleValue;
 
     /**
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index 4a91705..1836f00 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.Matrix;
@@ -118,6 +119,7 @@
 
     private ParcelFileDescriptor mInput;
 
+    @UnsupportedAppUsage
     private Page mCurrentPage;
 
     /** @hide */
@@ -242,6 +244,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void doClose() {
         if (mCurrentPage != null) {
             mCurrentPage.close();
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 8502309..4f4ca3f 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -128,7 +128,11 @@
     public static final int FLAG_STRONGBOX = 1 << 4;
 
     // States
-    public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
+    public enum State {
+        UNLOCKED,
+        LOCKED,
+        UNINITIALIZED
+    };
 
     private int mError = NO_ERROR;
 
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 61c412d..bcff5bf 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -1794,18 +1794,17 @@
     public @interface MediaError {}
 
     /* Do not change these values without updating their counterparts
-     * in include/media/mediaplayer2.h!
+     * in include/media/MediaPlayer2Types.h!
      */
     /** Unspecified media player info.
      * @see android.media.MediaPlayer2.EventCallback#onInfo
      */
     public static final int MEDIA_INFO_UNKNOWN = 1;
 
-    /** The player switched to this datas source because it is the
-     * next-to-be-played in the playlist.
+    /** The player just started the playback of this datas source.
      * @see android.media.MediaPlayer2.EventCallback#onInfo
      */
-    public static final int MEDIA_INFO_STARTED_AS_NEXT = 2;
+    public static final int MEDIA_INFO_DATA_SOURCE_START = 2;
 
     /** The player just pushed the very first video frame for rendering.
      * @see android.media.MediaPlayer2.EventCallback#onInfo
@@ -1820,12 +1819,13 @@
     /** The player just completed the playback of this data source.
      * @see android.media.MediaPlayer2.EventCallback#onInfo
      */
-    public static final int MEDIA_INFO_PLAYBACK_COMPLETE = 5;
+    public static final int MEDIA_INFO_DATA_SOURCE_END = 5;
 
-    /** The player just completed the playback of the full playlist.
+    /** The player just completed the playback of all data sources set by {@link #setDataSource},
+     * {@link #setNextDataSource} and {@link #setNextDataSources}.
      * @see android.media.MediaPlayer2.EventCallback#onInfo
      */
-    public static final int MEDIA_INFO_PLAYLIST_END = 6;
+    public static final int MEDIA_INFO_DATA_SOURCE_LIST_END = 6;
 
     /** The player just prepared a data source.
      * @see android.media.MediaPlayer2.EventCallback#onInfo
@@ -1927,11 +1927,11 @@
      */
     @IntDef(flag = false, prefix = "MEDIA_INFO", value = {
             MEDIA_INFO_UNKNOWN,
-            MEDIA_INFO_STARTED_AS_NEXT,
+            MEDIA_INFO_DATA_SOURCE_START,
             MEDIA_INFO_VIDEO_RENDERING_START,
             MEDIA_INFO_AUDIO_RENDERING_START,
-            MEDIA_INFO_PLAYBACK_COMPLETE,
-            MEDIA_INFO_PLAYLIST_END,
+            MEDIA_INFO_DATA_SOURCE_END,
+            MEDIA_INFO_DATA_SOURCE_LIST_END,
             MEDIA_INFO_PREPARED,
             MEDIA_INFO_VIDEO_TRACK_LAGGING,
             MEDIA_INFO_BUFFERING_START,
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index d5dd46c..95ba00f 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -210,6 +210,22 @@
             @Override
             void process() {
                 stayAwake(true);
+
+                // TODO: remove this block when native code sends MEDIA_INFO_DATA_SOURCE_START
+                // when pipeline is created.
+                if (getState() == PLAYER_STATE_PREPARED) {
+                    final DataSourceDesc dsd;
+                    synchronized (mSrcLock) {
+                        dsd = mCurrentDSD;
+                    }
+                    synchronized (mEventCbLock) {
+                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                            cb.first.execute(() -> cb.second.onInfo(
+                                    MediaPlayer2Impl.this, dsd, MEDIA_INFO_DATA_SOURCE_START, 0));
+                        }
+                    }
+                }
+
                 _start();
             }
         });
@@ -246,6 +262,22 @@
             @Override
             void process() {
                 stayAwake(false);
+
+                // TODO: remove this block when native code allows prepared -> pause
+                // and sends MEDIA_INFO_DATA_SOURCE_START when pipeline is created.
+                if (getState() == PLAYER_STATE_PREPARED) {
+                    final DataSourceDesc dsd;
+                    synchronized (mSrcLock) {
+                        dsd = mCurrentDSD;
+                    }
+                    synchronized (mEventCbLock) {
+                        for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                            cb.first.execute(() -> cb.second.onInfo(
+                                    MediaPlayer2Impl.this, dsd, MEDIA_INFO_DATA_SOURCE_START, 0));
+                        }
+                    }
+                }
+
                 _pause();
             }
         });
@@ -888,23 +920,30 @@
     private native void nativeHandleDataSourceCallback(
             boolean isCurrent, long srcId, Media2DataSource dataSource);
 
+    /**
+     * @return true if there is a next data source, false otherwise.
+     */
     // This function should be always called on |mHandlerThread|.
-    private void prepareNextDataSource() {
+    private boolean prepareNextDataSource() {
         if (Looper.myLooper() != mHandlerThread.getLooper()) {
             Log.e(TAG, "prepareNextDataSource: called on wrong looper");
         }
 
+        boolean hasNextDSD;
+        synchronized (mSrcLock) {
+            hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty());
+        }
+
         int state = getState();
         if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) {
             // Current source has not been prepared yet.
-            return;
+            return hasNextDSD;
         }
 
         synchronized (mSrcLock) {
-            if (mNextDSDs == null || mNextDSDs.isEmpty()
-                    || mNextSourceState != NEXT_SOURCE_STATE_INIT) {
+            if (!hasNextDSD || mNextSourceState != NEXT_SOURCE_STATE_INIT) {
                 // There is no next source or it's in preparing or prepared state.
-                return;
+                return hasNextDSD;
             }
 
             try {
@@ -919,9 +958,10 @@
                 // make a new SrcId to obsolete notification for previous one.
                 mNextSrcId = mSrcIdGenerator++;
                 mNextSourceState = NEXT_SOURCE_STATE_INIT;
-                prepareNextDataSource();
+                return prepareNextDataSource();
             }
         }
+        return hasNextDSD;
     }
 
     // This function should be always called on |mHandlerThread|.
@@ -930,40 +970,48 @@
             Log.e(TAG, "playNextDataSource: called on wrong looper");
         }
 
+        boolean hasNextDSD = false;
         synchronized (mSrcLock) {
-            if (mNextDSDs == null || mNextDSDs.isEmpty()) {
-                return;
-            }
+            if (mNextDSDs != null && !mNextDSDs.isEmpty()) {
+                hasNextDSD = true;
+                if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
+                    // Switch to next source only when it has been prepared.
+                    mCurrentDSD = mNextDSDs.get(0);
+                    mCurrentSrcId = mNextSrcId;
+                    mBufferedPercentageCurrent.set(mBufferedPercentageNext.get());
+                    mNextDSDs.remove(0);
+                    mNextSrcId = mSrcIdGenerator++;  // make it different from |mCurrentSrcId|
+                    mBufferedPercentageNext.set(0);
+                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
 
-            if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
-                // Switch to next source only when it has been prepared.
-                mCurrentDSD = mNextDSDs.get(0);
-                mCurrentSrcId = mNextSrcId;
-                mBufferedPercentageCurrent.set(mBufferedPercentageNext.get());
-                mNextDSDs.remove(0);
-                mNextSrcId = mSrcIdGenerator++;  // make it different from |mCurrentSrcId|
-                mBufferedPercentageNext.set(0);
-                mNextSourceState = NEXT_SOURCE_STATE_INIT;
+                    long srcId = mCurrentSrcId;
+                    try {
+                        nativePlayNextDataSource(srcId);
+                    } catch (Exception e) {
+                        Message msg2 = mTaskHandler.obtainMessage(
+                                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
+                        mTaskHandler.handleMessage(msg2, srcId);
+                        // Keep |mNextSourcePlayPending|
+                        hasNextDSD = prepareNextDataSource();
+                    }
+                    if (hasNextDSD) {
+                        stayAwake(true);
 
-                long srcId = mCurrentSrcId;
-                try {
-                    nativePlayNextDataSource(srcId);
-                } catch (Exception e) {
-                    Message msg2 = mTaskHandler.obtainMessage(
-                            MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
-                    mTaskHandler.handleMessage(msg2, srcId);
-                    // Keep |mNextSourcePlayPending|
-                    prepareNextDataSource();
-                    return;
+                        // Now a new current src is playing.
+                        // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source.
+                        mNextSourcePlayPending = false;
+                    }
+                } else if (mNextSourceState == NEXT_SOURCE_STATE_INIT) {
+                    hasNextDSD = prepareNextDataSource();
                 }
-                stayAwake(true);
+            }
+        }
 
-                // Now a new current src is playing.
-                // Wait for MEDIA2_INFO_STARTED_AS_NEXT to prepare next source.
-                mNextSourcePlayPending = false;
-            } else {
-                if (mNextSourceState == NEXT_SOURCE_STATE_INIT) {
-                    prepareNextDataSource();
+        if (!hasNextDSD) {
+            synchronized (mEventCbLock) {
+                for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                    cb.first.execute(() -> cb.second.onInfo(
+                            MediaPlayer2Impl.this, null, MEDIA_INFO_DATA_SOURCE_LIST_END, 0));
                 }
             }
         }
@@ -2767,7 +2815,7 @@
                     synchronized (mEventCbLock) {
                         for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                             cb.first.execute(() -> cb.second.onInfo(
-                                    mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+                                    mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0));
                         }
                     }
                     stayAwake(false);
@@ -2869,7 +2917,7 @@
                         cb.first.execute(() -> cb.second.onError(
                                 mMediaPlayer, dsd, what, extra));
                         cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0));
+                                mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0));
                     }
                 }
                 stayAwake(false);
@@ -2878,8 +2926,15 @@
 
             case MEDIA_INFO:
             {
+                synchronized (mEventCbLock) {
+                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                        cb.first.execute(() -> cb.second.onInfo(
+                                mMediaPlayer, dsd, what, extra));
+                    }
+                }
+
                 switch (msg.arg1) {
-                    case MEDIA_INFO_STARTED_AS_NEXT:
+                    case MEDIA_INFO_DATA_SOURCE_START:
                         if (isCurrentSrcId) {
                             prepareNextDataSource();
                         }
@@ -2916,13 +2971,6 @@
                         }
                         break;
                 }
-
-                synchronized (mEventCbLock) {
-                    for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                        cb.first.execute(() -> cb.second.onInfo(
-                                mMediaPlayer, dsd, what, extra));
-                    }
-                }
                 // No real default action so far.
                 return;
             }
@@ -3034,19 +3082,6 @@
         }
 
         switch (what) {
-        case MEDIA_INFO:
-            if (arg1 == MEDIA_INFO_STARTED_AS_NEXT) {
-                new Thread(new Runnable() {
-                    @Override
-                    public void run() {
-                        // this acquires the wakelock if needed, and sets the client side state
-                        mp.play();
-                    }
-                }).start();
-                Thread.yield();
-            }
-            break;
-
         case MEDIA_DRM_INFO:
             // We need to derive mDrmInfoImpl before prepare() returns so processing it here
             // before the notification is sent to TaskHandler below. TaskHandler runs in the
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index ff70e97..a7217ec 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -55,12 +55,6 @@
             <intent-filter>
                 <action android:name="android.service.autofill.AutofillFieldClassificationService" />
             </intent-filter>
-            <meta-data
-                android:name="android.autofill.field_classification.default_algorithm"
-                android:resource="@string/autofill_field_classification_default_algorithm" />
-            <meta-data
-                android:name="android.autofill.field_classification.available_algorithms"
-                android:resource="@array/autofill_field_classification_available_algorithms" />
         </service>
 
         <library android:name="android.ext.services"/>
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index a539b1f..9d19898 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -17,15 +17,16 @@
 package android.ext.services.notification;
 
 import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_NEGATIVE;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
-import android.ext.services.R;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -193,23 +194,27 @@
         if (DEBUG) Log.i(TAG, "ENQUEUED " + sbn.getKey());
         ArrayList<Notification.Action> actions =
                 mSmartActionsHelper.suggestActions(this, sbn);
-        if (actions.isEmpty()) {
-            return null;
-        }
-        return createEnqueuedNotificationAdjustment(sbn, actions);
+        ArrayList<CharSequence> replies = mSmartActionsHelper.suggestReplies(this, sbn);
+        return createEnqueuedNotificationAdjustment(sbn, actions, replies);
     }
 
     /** A convenience helper for creating an adjustment for an SBN. */
+    @Nullable
     private Adjustment createEnqueuedNotificationAdjustment(
             @NonNull StatusBarNotification statusBarNotification,
-            @NonNull ArrayList<Notification.Action> smartActions) {
+            @NonNull ArrayList<Notification.Action> smartActions,
+            @NonNull ArrayList<CharSequence> smartReplies) {
+        if (smartActions.isEmpty() && smartReplies.isEmpty()) {
+            return null;
+        }
         Bundle signals = new Bundle();
         signals.putParcelableArrayList(Adjustment.KEY_SMART_ACTIONS, smartActions);
+        signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies);
         return new Adjustment(
                 statusBarNotification.getPackageName(),
                 statusBarNotification.getKey(),
                 signals,
-                "smart action" /* explanation */,
+                "smart action, reply" /* explanation */,
                 statusBarNotification.getUserId());
     }
 
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index ed5cbab..9d33bd9 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -24,6 +24,7 @@
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.Process;
+import android.os.SystemProperties;
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -32,13 +33,13 @@
 import android.view.textclassifier.TextClassifier;
 import android.view.textclassifier.TextLinks;
 
-import com.android.internal.util.Preconditions;
-
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 
 public class SmartActionsHelper {
-    private static final ArrayList<Notification.Action> EMPTY_LIST = new ArrayList<>();
+    private static final ArrayList<Notification.Action> EMPTY_ACTION_LIST = new ArrayList<>();
+    private static final ArrayList<CharSequence> EMPTY_REPLY_LIST = new ArrayList<>();
 
     // If a notification has any of these flags set, it's inelgibile for actions being added.
     private static final int FLAG_MASK_INELGIBILE_FOR_ACTIONS =
@@ -49,6 +50,10 @@
     private static final int MAX_ACTION_EXTRACTION_TEXT_LENGTH = 400;
     private static final int MAX_ACTIONS_PER_LINK = 1;
     private static final int MAX_SMART_ACTIONS = Notification.MAX_ACTION_BUTTONS;
+    // Allow us to test out smart reply with dumb suggestions, it is disabled by default.
+    // TODO: Removed this once we have the model.
+    private static final String SYS_PROP_SMART_REPLIES_EXPERIMENT =
+            "persist.sys.smart_replies_experiment";
 
     SmartActionsHelper() {}
 
@@ -62,14 +67,14 @@
     ArrayList<Notification.Action> suggestActions(
             @Nullable Context context, @NonNull StatusBarNotification sbn) {
         if (!isEligibleForActionAdjustment(sbn)) {
-            return EMPTY_LIST;
+            return EMPTY_ACTION_LIST;
         }
         if (context == null) {
-            return EMPTY_LIST;
+            return EMPTY_ACTION_LIST;
         }
         TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class);
         if (tcm == null) {
-            return EMPTY_LIST;
+            return EMPTY_ACTION_LIST;
         }
         Notification.Action[] actions = sbn.getNotification().actions;
         int numOfExistingActions = actions == null ? 0: actions.length;
@@ -79,6 +84,18 @@
                 getMostSalientActionText(sbn.getNotification()), maxSmartActions);
     }
 
+    ArrayList<CharSequence> suggestReplies(
+            @Nullable Context context, @NonNull StatusBarNotification sbn) {
+        if (!isEligibleForReplyAdjustment(sbn)) {
+            return EMPTY_REPLY_LIST;
+        }
+        if (context == null) {
+            return EMPTY_REPLY_LIST;
+        }
+        // TODO: replaced this with our model when it is ready.
+        return new ArrayList<>(Arrays.asList("Yes, please", "No, thanks"));
+    }
+
     /**
      * Returns whether a notification is eligible for action adjustments.
      *
@@ -108,6 +125,17 @@
                 || hasInlineReply(notification);
     }
 
+    private boolean isEligibleForReplyAdjustment(@NonNull StatusBarNotification sbn) {
+        if (!SystemProperties.getBoolean(SYS_PROP_SMART_REPLIES_EXPERIMENT, false)) {
+            return false;
+        }
+        Notification notification = sbn.getNotification();
+        if (notification.actions == null) {
+            return false;
+        }
+        return hasInlineReply(sbn.getNotification());
+    }
+
     private boolean hasInlineReply(Notification notification) {
         Notification.Action[] actions = notification.actions;
         if (actions == null) {
@@ -151,7 +179,7 @@
             @NonNull TextClassificationManager tcm, @Nullable CharSequence text,
             int maxSmartActions) {
         if (TextUtils.isEmpty(text)) {
-            return EMPTY_LIST;
+            return EMPTY_ACTION_LIST;
         }
         TextClassifier textClassifier = tcm.getTextClassifier();
 
diff --git a/packages/PackageInstaller/res/layout/uninstall_confirm.xml b/packages/PackageInstaller/res/layout/uninstall_confirm.xml
deleted file mode 100644
index 4c81771..0000000
--- a/packages/PackageInstaller/res/layout/uninstall_confirm.xml
+++ /dev/null
@@ -1,130 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<!--
-
-  Defines the layout of the confirmation screen that gets displayed when an
-  application is about to be uninstalled. Includes ok and cancel buttons
-  to let the uinstallation continue or abort.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <LinearLayout
-        android:layout_weight="1"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentTop="true"
-        android:orientation="vertical"
-        android:paddingBottom="8dip">
-
-        <!-- If an activity was specified, explains what package it's in. -->
-        <TextView
-            android:id="@+id/activity_text"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:paddingStart="16dip"
-            android:paddingEnd="16dip"
-            android:textColor="?android:attr/textColorSecondary"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:visibility="gone" />
-
-        <!-- The snippet (title & icon) about the application being uninstalled. -->
-        <include
-            layout="@layout/app_details"
-            android:id="@+id/uninstall_activity_snippet" />
-
-        <FrameLayout
-                android:id="@+id/top_divider"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingTop="4dip"
-                android:paddingStart="16dip"
-                android:paddingEnd="16dip" >
-            <ProgressBar
-                    android:id="@+id/progress_bar"
-                    style="?android:attr/progressBarStyleHorizontal"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content" />
-        </FrameLayout>
-
-        <!-- uninstall application confirmation text -->
-        <TextView
-            android:id="@+id/uninstall_confirm"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textColor="?android:attr/textColorSecondary"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:paddingStart="24dip"
-            android:paddingEnd="24dip" />
-
-    </LinearLayout>
-
-    <!-- OK confirm and cancel buttons.  -->
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:divider="?android:attr/dividerHorizontal"
-            android:showDividers="beginning"
-            android:paddingTop="16dip">
-
-        <LinearLayout
-                style="?android:attr/buttonBarStyle"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:measureWithLargestChild="true">
-
-            <LinearLayout android:id="@+id/leftSpacer"
-                android:layout_weight="0.25"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:visibility="gone" />
-
-            <Button android:id="@+id/cancel_button"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_gravity="start"
-                android:layout_weight="1"
-                android:text="@string/cancel"
-                android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle" />
-
-            <Button android:id="@+id/ok_button"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:layout_gravity="end"
-                android:layout_weight="1"
-                android:text="@string/ok"
-                android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle" />
-
-            <LinearLayout android:id="@+id/rightSpacer"
-                android:layout_width="0dip"
-                android:layout_weight="0.25"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:visibility="gone" />
-
-        </LinearLayout>
-    </LinearLayout>
-</LinearLayout>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 50d9c17..d30be58 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -189,9 +189,9 @@
     <string name="vpn_settings_not_available" msgid="956841430176985598">"La configuració de la VPN no està disponible per a aquest usuari."</string>
     <string name="tethering_settings_not_available" msgid="6765770438438291012">"La configuració de compartició de xarxa no està disponible per a aquest usuari."</string>
     <string name="apn_settings_not_available" msgid="7873729032165324000">"La configuració del nom del punt d\'accés no està disponible per a aquest usuari."</string>
-    <string name="enable_adb" msgid="7982306934419797485">"Depuració USB"</string>
+    <string name="enable_adb" msgid="7982306934419797485">"Depuració per USB"</string>
     <string name="enable_adb_summary" msgid="4881186971746056635">"Activa el mode de depuració quan el dispositiu estigui connectat per USB"</string>
-    <string name="clear_adb_keys" msgid="4038889221503122743">"Revoca autoritzacions de depuració USB"</string>
+    <string name="clear_adb_keys" msgid="4038889221503122743">"Revoca autoritzacions de depuració per USB"</string>
     <string name="bugreport_in_power" msgid="7923901846375587241">"Drecera per a informe d\'errors"</string>
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostra un botó al menú d\'engegada per crear un informe d\'errors"</string>
     <string name="keep_screen_on" msgid="1146389631208760344">"Pantalla sempre activa"</string>
@@ -251,9 +251,9 @@
     <string name="debug_view_attributes" msgid="6485448367803310384">"Inspecció d\'atributs de visualització"</string>
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Mantén les dades mòbils sempre actives, fins i tot quan la Wi‑Fi està activada (per canviar de xarxa ràpidament)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Fes servir l\'acceleració per maquinari per compartir la xarxa, si està disponible"</string>
-    <string name="adb_warning_title" msgid="6234463310896563253">"Voleu permetre la depuració USB?"</string>
-    <string name="adb_warning_message" msgid="7316799925425402244">"La depuració USB només està indicada per a activitats de desenvolupament. Fes-la servir intercanviar dades entre l\'ordinador i el dispositiu, per instal·lar aplicacions al dispositiu sense rebre notificacions i per llegir dades de registre."</string>
-    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Vols revocar l\'accés a la depuració d\'USB dels ordinadors que has autoritzat anteriorment?"</string>
+    <string name="adb_warning_title" msgid="6234463310896563253">"Voleu permetre la depuració per USB?"</string>
+    <string name="adb_warning_message" msgid="7316799925425402244">"La depuració per USB només està indicada per a activitats de desenvolupament. Fes-la servir intercanviar dades entre l\'ordinador i el dispositiu, per instal·lar aplicacions al dispositiu sense rebre notificacions i per llegir dades de registre."</string>
+    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Vols revocar l\'accés a la depuració per USB dels ordinadors que has autoritzat anteriorment?"</string>
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"Vols permetre la conf. de desenvolupament?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"Aquesta configuració només està prevista per a usos de desenvolupament. Pot fer que el dispositiu i que les aplicacions s\'interrompin o tinguin un comportament inadequat."</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifica aplicacions per USB"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 1579d8f..a90231a 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -189,9 +189,9 @@
     <string name="vpn_settings_not_available" msgid="956841430176985598">"Nastavení sítě VPN pro tohoto uživatele není dostupné."</string>
     <string name="tethering_settings_not_available" msgid="6765770438438291012">"Nastavení sdíleného připojení pro tohoto uživatele není dostupné."</string>
     <string name="apn_settings_not_available" msgid="7873729032165324000">"Nastavení přístupového bodu pro tohoto uživatele není dostupné."</string>
-    <string name="enable_adb" msgid="7982306934419797485">"Ladění USB"</string>
+    <string name="enable_adb" msgid="7982306934419797485">"Ladění přes USB"</string>
     <string name="enable_adb_summary" msgid="4881186971746056635">"Povolit režim ladění s připojeným zařízením USB"</string>
-    <string name="clear_adb_keys" msgid="4038889221503122743">"Zrušit autorizace k ladění USB"</string>
+    <string name="clear_adb_keys" msgid="4038889221503122743">"Zrušit autorizace k ladění přes USB"</string>
     <string name="bugreport_in_power" msgid="7923901846375587241">"Zástupce hlášení chyb"</string>
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Zobrazit v hlavní nabídce tlačítko k vygenerování chybového hlášení"</string>
     <string name="keep_screen_on" msgid="1146389631208760344">"Nevypínat obrazovku"</string>
@@ -251,9 +251,9 @@
     <string name="debug_view_attributes" msgid="6485448367803310384">"Kontrola atributu zobrazení"</string>
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Mobilní data budou vždy ponechána aktivní, i když bude aktivní Wi-Fi (za účelem rychlého přepínání sítí)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Pokud je k dispozici hardwarová akceleraci tetheringu, použít ji"</string>
-    <string name="adb_warning_title" msgid="6234463310896563253">"Povolit ladění USB?"</string>
+    <string name="adb_warning_title" msgid="6234463310896563253">"Povolit ladění přes USB?"</string>
     <string name="adb_warning_message" msgid="7316799925425402244">"Ladění prostřednictvím rozhraní USB je určeno pouze pro účely vývoje. Použijte je ke kopírování dat mezi počítačem a zařízením, instalaci aplikací do zařízení bez upozornění a čtení dat protokolů."</string>
-    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Zrušit přístup k ladění USB ze všech počítačů, které jste v minulosti autorizovali?"</string>
+    <string name="adb_keys_warning_message" msgid="5659849457135841625">"Zrušit přístup k ladění přes USB ze všech počítačů, které jste v minulosti autorizovali?"</string>
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"Povolit nastavení pro vývojáře?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"Tato nastavení jsou určena pouze pro vývojáře. Mohou způsobit rozbití nebo nesprávné fungování zařízení a nainstalovaných aplikací."</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Ověřit aplikace z USB"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index ec7bf98..0410977 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -165,7 +165,7 @@
     <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> motorraren ezarpenak"</string>
     <string name="tts_engine_settings_button" msgid="1030512042040722285">"Abiarazi motorraren ezarpenak"</string>
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor hobetsia"</string>
-    <string name="tts_general_section_title" msgid="4402572014604490502">"Orokorra"</string>
+    <string name="tts_general_section_title" msgid="4402572014604490502">"Orokorrak"</string>
     <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Berrezarri ahots-tonua"</string>
     <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Berrezarri testua esateko ahots-tonu lehenetsia."</string>
   <string-array name="tts_rate_entries">
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 5eac8fa..e94dd73 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -371,10 +371,10 @@
     <string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
     <string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Temps restant en fonction de votre utilisation (<xliff:g id="LEVEL">%2$s</xliff:g>) : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Temps restant : <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de l\'utilisation (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de l\'utilisation"</string>
-    <string name="power_discharge_by" msgid="6453537733650125582">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only" msgid="107616694963545745">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Temps restant estimé en fonction de votre utilisation : <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
+    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Temps restant estimé en fonction de votre utilisation : <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by" msgid="6453537733650125582">"Temps restant estimé : <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
+    <string name="power_discharge_by_only" msgid="107616694963545745">"Temps restant estimé : <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index d80e4ff..33c5551 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -162,7 +162,7 @@
 
 Draws decorations about the screen in software (e.g. rounded corners, cutouts).
 
-### [com.android.systemui.fingerprint.FingerprintDialogImpl](/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java)
+### [com.android.systemui.biometrics.BiometricDialogImpl](/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java)
 
 Fingerprint UI.
 
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index e6452e7..fa4c8b5 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -39,6 +39,6 @@
 -keep class ** extends androidx.preference.PreferenceFragment
 -keep class com.android.systemui.tuner.*
 -keep class com.android.systemui.plugins.** {
-    public protected *;
+    *;
 }
 -keep class androidx.core.app.CoreComponentFactory
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index 8379dbb..ee8d357 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -28,7 +28,7 @@
     <ImageView android:id="@+id/user_avatar"
         android:layout_width="@dimen/car_user_switcher_image_avatar_size"
         android:layout_height="@dimen/car_user_switcher_image_avatar_size"
-        android:background="@drawable/car_button_ripple_background_inverse"
+        android:background="@drawable/car_button_ripple_background_light"
         android:gravity="center"/>
 
     <TextView android:id="@+id/user_name"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index aecf494..19492a0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -354,7 +354,7 @@
         <item>com.android.systemui.LatencyTester</item>
         <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
         <item>com.android.systemui.ScreenDecorations</item>
-        <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
+        <item>com.android.systemui.biometrics.BiometricDialogImpl</item>
         <item>com.android.systemui.SliceBroadcastRelayHandler</item>
     </string-array>
 
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
similarity index 63%
rename from packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
rename to packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index a81043e..6e62b0d 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.systemui.fingerprint;
+package com.android.systemui.biometrics;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -31,25 +31,28 @@
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.CommandQueue;
 
-public class FingerprintDialogImpl extends SystemUI implements CommandQueue.Callbacks {
+/**
+ * Receives messages sent from AuthenticationClient and shows the appropriate biometric UI (e.g.
+ * FingerprintDialogView).
+ */
+public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callbacks {
     private static final String TAG = "FingerprintDialogImpl";
     private static final boolean DEBUG = true;
 
-    protected static final int MSG_SHOW_DIALOG = 1;
-    protected static final int MSG_FINGERPRINT_AUTHENTICATED = 2;
-    protected static final int MSG_FINGERPRINT_HELP = 3;
-    protected static final int MSG_FINGERPRINT_ERROR = 4;
-    protected static final int MSG_HIDE_DIALOG = 5;
-    protected static final int MSG_BUTTON_NEGATIVE = 6;
-    protected static final int MSG_USER_CANCELED = 7;
-    protected static final int MSG_BUTTON_POSITIVE = 8;
-    protected static final int MSG_CLEAR_MESSAGE = 9;
-
+    private static final int MSG_SHOW_DIALOG = 1;
+    private static final int MSG_BIOMETRIC_AUTHENTICATED = 2;
+    private static final int MSG_BIOMETRIC_HELP = 3;
+    private static final int MSG_BIOMETRIC_ERROR = 4;
+    private static final int MSG_HIDE_DIALOG = 5;
+    private static final int MSG_BUTTON_NEGATIVE = 6;
+    private static final int MSG_USER_CANCELED = 7;
+    private static final int MSG_BUTTON_POSITIVE = 8;
 
     private FingerprintDialogView mDialogView;
     private WindowManager mWindowManager;
     private IBiometricPromptReceiver mReceiver;
     private boolean mDialogShowing;
+    private Callback mCallback = new Callback();
 
     private Handler mHandler = new Handler() {
         @Override
@@ -58,14 +61,14 @@
                 case MSG_SHOW_DIALOG:
                     handleShowDialog((SomeArgs) msg.obj);
                     break;
-                case MSG_FINGERPRINT_AUTHENTICATED:
-                    handleFingerprintAuthenticated();
+                case MSG_BIOMETRIC_AUTHENTICATED:
+                    handleBiometricAuthenticated();
                     break;
-                case MSG_FINGERPRINT_HELP:
-                    handleFingerprintHelp((String) msg.obj);
+                case MSG_BIOMETRIC_HELP:
+                    handleBiometricHelp((String) msg.obj);
                     break;
-                case MSG_FINGERPRINT_ERROR:
-                    handleFingerprintError((String) msg.obj);
+                case MSG_BIOMETRIC_ERROR:
+                    handleBiometricError((String) msg.obj);
                     break;
                 case MSG_HIDE_DIALOG:
                     handleHideDialog((Boolean) msg.obj);
@@ -79,13 +82,33 @@
                 case MSG_BUTTON_POSITIVE:
                     handleButtonPositive();
                     break;
-                case MSG_CLEAR_MESSAGE:
-                    handleClearMessage();
-                    break;
             }
         }
     };
 
+    private class Callback implements DialogViewCallback {
+        @Override
+        public void onUserCanceled() {
+            mHandler.obtainMessage(BiometricDialogImpl.MSG_USER_CANCELED).sendToTarget();
+        }
+
+        @Override
+        public void onErrorShown() {
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_HIDE_DIALOG,
+                    false /* userCanceled */), BiometricPrompt.HIDE_DIALOG_DELAY);
+        }
+
+        @Override
+        public void onNegativePressed() {
+            mHandler.obtainMessage(BiometricDialogImpl.MSG_BUTTON_NEGATIVE).sendToTarget();
+        }
+
+        @Override
+        public void onPositivePressed() {
+            mHandler.obtainMessage(BiometricDialogImpl.MSG_BUTTON_POSITIVE).sendToTarget();
+        }
+    }
+
     @Override
     public void start() {
         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
@@ -93,16 +116,16 @@
         }
         getComponent(CommandQueue.class).addCallbacks(this);
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        mDialogView = new FingerprintDialogView(mContext, mHandler);
+        mDialogView = new FingerprintDialogView(mContext, mCallback);
     }
 
     @Override
-    public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
-        if (DEBUG) Log.d(TAG, "showFingerprintDialog");
+    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
+        if (DEBUG) Log.d(TAG, "showBiometricDialog");
         // Remove these messages as they are part of the previous client
-        mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
-        mHandler.removeMessages(MSG_FINGERPRINT_HELP);
-        mHandler.removeMessages(MSG_FINGERPRINT_AUTHENTICATED);
+        mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
+        mHandler.removeMessages(MSG_BIOMETRIC_HELP);
+        mHandler.removeMessages(MSG_BIOMETRIC_AUTHENTICATED);
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = bundle;
         args.arg2 = receiver;
@@ -110,26 +133,26 @@
     }
 
     @Override
-    public void onFingerprintAuthenticated() {
-        if (DEBUG) Log.d(TAG, "onFingerprintAuthenticated");
-        mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
+    public void onBiometricAuthenticated() {
+        if (DEBUG) Log.d(TAG, "onBiometricAuthenticated");
+        mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED).sendToTarget();
     }
 
     @Override
-    public void onFingerprintHelp(String message) {
-        if (DEBUG) Log.d(TAG, "onFingerprintHelp: " + message);
-        mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
+    public void onBiometricHelp(String message) {
+        if (DEBUG) Log.d(TAG, "onBiometricHelp: " + message);
+        mHandler.obtainMessage(MSG_BIOMETRIC_HELP, message).sendToTarget();
     }
 
     @Override
-    public void onFingerprintError(String error) {
-        if (DEBUG) Log.d(TAG, "onFingerprintError: " + error);
-        mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
+    public void onBiometricError(String error) {
+        if (DEBUG) Log.d(TAG, "onBiometricError: " + error);
+        mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, error).sendToTarget();
     }
 
     @Override
-    public void hideFingerprintDialog() {
-        if (DEBUG) Log.d(TAG, "hideFingerprintDialog");
+    public void hideBiometricDialog() {
+        if (DEBUG) Log.d(TAG, "hideBiometricDialog");
         mHandler.obtainMessage(MSG_HIDE_DIALOG, false /* userCanceled */).sendToTarget();
     }
 
@@ -148,21 +171,23 @@
         mDialogShowing = true;
     }
 
-    private void handleFingerprintAuthenticated() {
-        if (DEBUG) Log.d(TAG, "handleFingerprintAuthenticated");
+    private void handleBiometricAuthenticated() {
+        if (DEBUG) Log.d(TAG, "handleBiometricAuthenticated");
+
+        // TODO: announce correct string depending on modality
         mDialogView.announceForAccessibility(
                 mContext.getResources().getText(
                         com.android.internal.R.string.fingerprint_authenticated));
         handleHideDialog(false /* userCanceled */);
     }
 
-    private void handleFingerprintHelp(String message) {
-        if (DEBUG) Log.d(TAG, "handleFingerprintHelp: " + message);
+    private void handleBiometricHelp(String message) {
+        if (DEBUG) Log.d(TAG, "handleBiometricHelp: " + message);
         mDialogView.showHelpMessage(message);
     }
 
-    private void handleFingerprintError(String error) {
-        if (DEBUG) Log.d(TAG, "handleFingerprintError: " + error);
+    private void handleBiometricError(String error) {
+        if (DEBUG) Log.d(TAG, "handleBiometricError: " + error);
         if (!mDialogShowing) {
             if (DEBUG) Log.d(TAG, "Dialog already dismissed");
             return;
@@ -216,10 +241,6 @@
         handleHideDialog(false /* userCanceled */);
     }
 
-    private void handleClearMessage() {
-        mDialogView.resetMessage();
-    }
-
     private void handleUserCanceled() {
         handleHideDialog(true /* userCanceled */);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java b/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java
new file mode 100644
index 0000000..f388d9c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java
@@ -0,0 +1,46 @@
+/*
+ * 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.biometrics;
+
+/**
+ * Callback interface for dialog views. These should be implemented by the controller (e.g.
+ * FingerprintDialogImpl) and passed into their views (e.g. FingerprintDialogView).
+ */
+public interface DialogViewCallback {
+    /**
+     * Invoked when the user cancels authentication by tapping outside the prompt, etc. The dialog
+     * should be dismissed.
+     */
+    void onUserCanceled();
+
+    /**
+     * Invoked when an error is shown. The dialog should be dismissed after a set amount of time.
+     */
+    void onErrorShown();
+
+    /**
+     * Invoked when the negative button is pressed. The client should be notified and the dialog
+     * should be dismissed.
+     */
+    void onNegativePressed();
+
+    /**
+     * Invoked when the positive button is pressed. The client should be notified and the dialog
+     * should be dismissed.
+     */
+    void onPositivePressed();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
similarity index 92%
rename from packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
rename to packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
index 8013a9e..68c2c42 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FingerprintDialogView.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.systemui.fingerprint;
+package com.android.systemui.biometrics;
 
 import android.content.Context;
 import android.graphics.Color;
@@ -26,6 +26,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -56,6 +57,8 @@
     private static final int ANIMATION_DURATION_SHOW = 250; // ms
     private static final int ANIMATION_DURATION_AWAY = 350; // ms
 
+    private static final int MSG_CLEAR_MESSAGE = 1;
+
     private static final int STATE_NONE = 0;
     private static final int STATE_FINGERPRINT = 1;
     private static final int STATE_FINGERPRINT_ERROR = 2;
@@ -68,18 +71,17 @@
     private final int mErrorColor;
     private final int mTextColor;
     private final int mFingerprintColor;
+    private final float mDisplayWidth;
+    private final DialogViewCallback mCallback;
 
     private ViewGroup mLayout;
     private final TextView mErrorText;
-    private Handler mHandler;
     private Bundle mBundle;
     private final LinearLayout mDialog;
     private int mLastState;
     private boolean mAnimatingAway;
     private boolean mWasForceRemoved;
 
-    private final float mDisplayWidth;
-
     private final Runnable mShowAnimationRunnable = new Runnable() {
         @Override
         public void run() {
@@ -98,9 +100,23 @@
         }
     };
 
-    public FingerprintDialogView(Context context, Handler handler) {
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+                case MSG_CLEAR_MESSAGE:
+                    handleClearMessage();
+                    break;
+                default:
+                    Log.e(TAG, "Unhandled message: " + msg.what);
+                    break;
+            }
+        }
+    };
+
+    public FingerprintDialogView(Context context, DialogViewCallback callback) {
         super(context);
-        mHandler = handler;
+        mCallback = callback;
         mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         mAnimationTranslationOffset = getResources()
@@ -138,7 +154,7 @@
                     downPressed = false;
                 } else if (event.getAction() == KeyEvent.ACTION_UP && downPressed == true) {
                     downPressed = false;
-                    mHandler.obtainMessage(FingerprintDialogImpl.MSG_USER_CANCELED).sendToTarget();
+                    mCallback.onUserCanceled();
                 }
                 return true;
             }
@@ -155,11 +171,11 @@
         setDismissesDialog(rightSpace);
 
         negative.setOnClickListener((View v) -> {
-            mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_NEGATIVE).sendToTarget();
+            mCallback.onNegativePressed();
         });
 
         positive.setOnClickListener((View v) -> {
-            mHandler.obtainMessage(FingerprintDialogImpl.MSG_BUTTON_POSITIVE).sendToTarget();
+            mCallback.onPositivePressed();
         });
 
         mLayout.setFocusableInTouchMode(true);
@@ -230,8 +246,7 @@
     private void setDismissesDialog(View v) {
         v.setClickable(true);
         v.setOnTouchListener((View view, MotionEvent event) -> {
-            mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG, true /* userCanceled */)
-                    .sendToTarget();
+            mCallback.onUserCanceled();
             return true;
         });
     }
@@ -289,7 +304,7 @@
     }
 
     // Clears the temporary message and shows the help message.
-    protected void resetMessage() {
+    private void handleClearMessage() {
         updateFingerprintIcon(STATE_FINGERPRINT);
         mErrorText.setText(R.string.fingerprint_dialog_touch_sensor);
         mErrorText.setTextColor(mTextColor);
@@ -297,12 +312,12 @@
 
     // Shows an error/help message
     private void showTemporaryMessage(String message) {
-        mHandler.removeMessages(FingerprintDialogImpl.MSG_CLEAR_MESSAGE);
+        mHandler.removeMessages(MSG_CLEAR_MESSAGE);
         updateFingerprintIcon(STATE_FINGERPRINT_ERROR);
         mErrorText.setText(message);
         mErrorText.setTextColor(mErrorColor);
         mErrorText.setContentDescription(message);
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_CLEAR_MESSAGE),
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_MESSAGE),
                 BiometricPrompt.HIDE_DIALOG_DELAY);
     }
 
@@ -312,8 +327,7 @@
 
     public void showErrorMessage(String error) {
         showTemporaryMessage(error);
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG,
-                false /* userCanceled */), BiometricPrompt.HIDE_DIALOG_DELAY);
+        mCallback.onErrorShown();
     }
 
     private void updateFingerprintIcon(int newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 8f30edd..03a573e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -65,6 +65,7 @@
     private static final boolean ENABLE_FLING_DISMISS = false;
 
     private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 225;
+    private static final int BOTTOM_OFFSET_BUFFER_DP = 1;
 
     // Allow dragging the PIP to a location to close it
     private final boolean mEnableDimissDragToEdge;
@@ -314,8 +315,10 @@
                 // above the position as if shelf/IME shows, don't move the PIP window.
                 int movementBoundsAdjustment = toMovementBounds.bottom - mMovementBounds.bottom;
                 int offsetAdjustment = fromImeAdjustment ? mImeOffset : mShelfHeight;
+                final float bottomOffsetBufferInPx = BOTTOM_OFFSET_BUFFER_DP
+                        * mContext.getResources().getDisplayMetrics().density;
                 if (toAdjustedBounds.bottom >= mMovementBounds.bottom
-                        && animatingBounds.top
+                        && animatingBounds.top + Math.round(bottomOffsetBufferInPx)
                         < toAdjustedBounds.bottom - movementBoundsAdjustment - offsetAdjustment) {
                     return;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 145a246..909cd79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -85,11 +85,11 @@
     private static final int MSG_SHOW_SHUTDOWN_UI              = 36 << MSG_SHIFT;
     private static final int MSG_SET_TOP_APP_HIDES_STATUS_BAR  = 37 << MSG_SHIFT;
     private static final int MSG_ROTATION_PROPOSAL             = 38 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_SHOW              = 39 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_AUTHENTICATED     = 40 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_HELP              = 41 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_ERROR             = 42 << MSG_SHIFT;
-    private static final int MSG_FINGERPRINT_HIDE              = 43 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_SHOW                = 39 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_AUTHENTICATED       = 40 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_HELP                = 41 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_ERROR               = 42 << MSG_SHIFT;
+    private static final int MSG_BIOMETRIC_HIDE                = 43 << MSG_SHIFT;
     private static final int MSG_SHOW_CHARGING_ANIMATION       = 44 << MSG_SHIFT;
     private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
     private static final int MSG_SHOW_PINNING_TOAST_ESCAPE     = 46 << MSG_SHIFT;
@@ -160,11 +160,11 @@
 
         default void onRotationProposal(int rotation, boolean isValid) { }
 
-        default void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) { }
-        default void onFingerprintAuthenticated() { }
-        default void onFingerprintHelp(String message) { }
-        default void onFingerprintError(String error) { }
-        default void hideFingerprintDialog() { }
+        default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) { }
+        default void onBiometricAuthenticated() { }
+        default void onBiometricHelp(String message) { }
+        default void onBiometricError(String error) { }
+        default void hideBiometricDialog() { }
     }
 
     @VisibleForTesting
@@ -513,41 +513,41 @@
     }
 
     @Override
-    public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
+    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
         synchronized (mLock) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = bundle;
             args.arg2 = receiver;
-            mHandler.obtainMessage(MSG_FINGERPRINT_SHOW, args)
+            mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args)
                     .sendToTarget();
         }
     }
 
     @Override
-    public void onFingerprintAuthenticated() {
+    public void onBiometricAuthenticated() {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED).sendToTarget();
         }
     }
 
     @Override
-    public void onFingerprintHelp(String message) {
+    public void onBiometricHelp(String message) {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_HELP, message).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_HELP, message).sendToTarget();
         }
     }
 
     @Override
-    public void onFingerprintError(String error) {
+    public void onBiometricError(String error) {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, error).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, error).sendToTarget();
         }
     }
 
     @Override
-    public void hideFingerprintDialog() {
+    public void hideBiometricDialog() {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_HIDE).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_HIDE).sendToTarget();
         }
     }
 
@@ -752,34 +752,34 @@
                         mCallbacks.get(i).onRotationProposal(msg.arg1, msg.arg2 != 0);
                     }
                     break;
-                case MSG_FINGERPRINT_SHOW:
-                    mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
-                    mHandler.removeMessages(MSG_FINGERPRINT_HELP);
-                    mHandler.removeMessages(MSG_FINGERPRINT_AUTHENTICATED);
+                case MSG_BIOMETRIC_SHOW:
+                    mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
+                    mHandler.removeMessages(MSG_BIOMETRIC_HELP);
+                    mHandler.removeMessages(MSG_BIOMETRIC_AUTHENTICATED);
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).showFingerprintDialog(
+                        mCallbacks.get(i).showBiometricDialog(
                                 (Bundle)((SomeArgs)msg.obj).arg1,
                                 (IBiometricPromptReceiver)((SomeArgs)msg.obj).arg2);
                     }
                     break;
-                case MSG_FINGERPRINT_AUTHENTICATED:
+                case MSG_BIOMETRIC_AUTHENTICATED:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).onFingerprintAuthenticated();
+                        mCallbacks.get(i).onBiometricAuthenticated();
                     }
                     break;
-                case MSG_FINGERPRINT_HELP:
+                case MSG_BIOMETRIC_HELP:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).onFingerprintHelp((String) msg.obj);
+                        mCallbacks.get(i).onBiometricHelp((String) msg.obj);
                     }
                     break;
-                case MSG_FINGERPRINT_ERROR:
+                case MSG_BIOMETRIC_ERROR:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).onFingerprintError((String) msg.obj);
+                        mCallbacks.get(i).onBiometricError((String) msg.obj);
                     }
                     break;
-                case MSG_FINGERPRINT_HIDE:
+                case MSG_BIOMETRIC_HIDE:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).hideFingerprintDialog();
+                        mCallbacks.get(i).hideBiometricDialog();
                     }
                     break;
                 case MSG_SHOW_CHARGING_ANIMATION:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
index 92bf821..47b7fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
@@ -27,6 +27,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -38,18 +39,21 @@
 
     public final String key;
     public final List<Notification.Action> smartActions;
+    public final CharSequence[] smartReplies;
 
     @VisibleForTesting
-    NotificationUiAdjustment(String key, List<Notification.Action> smartActions) {
+    NotificationUiAdjustment(
+            String key, List<Notification.Action> smartActions, CharSequence[] smartReplies) {
         this.key = key;
         this.smartActions = smartActions == null
                 ? Collections.emptyList()
                 : new ArrayList<>(smartActions);
+        this.smartReplies = smartReplies == null ? new CharSequence[0] : smartReplies.clone();
     }
 
     public static NotificationUiAdjustment extractFromNotificationEntry(
             NotificationData.Entry entry) {
-        return new NotificationUiAdjustment(entry.key, entry.smartActions);
+        return new NotificationUiAdjustment(entry.key, entry.smartActions, entry.smartReplies);
     }
 
     public static boolean needReinflate(
@@ -58,7 +62,13 @@
         if (oldAdjustment == newAdjustment) {
             return false;
         }
-        return areDifferent(oldAdjustment.smartActions, newAdjustment.smartActions);
+        if (areDifferent(oldAdjustment.smartActions, newAdjustment.smartActions)) {
+            return true;
+        }
+        if (!Arrays.equals(oldAdjustment.smartReplies, newAdjustment.smartReplies)) {
+            return true;
+        }
+        return false;
     }
 
     public static boolean areDifferent(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
index 81d6191..32fd054 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
@@ -147,7 +147,7 @@
                 return;
             }
             view.setTemp(mHvacManager.getFloatProperty(id, zone));
-        } catch (CarNotConnectedException e) {
+        } catch (Exception e) {
             view.setTemp(Float.NaN);
             Log.e(TAG, "Failed to get value from hvac service", e);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index ce8f224..804e842 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -112,6 +112,7 @@
         public int userSentiment = Ranking.USER_SENTIMENT_NEUTRAL;
         @NonNull
         public List<Notification.Action> smartActions = Collections.emptyList();
+        public CharSequence[] smartReplies = new CharSequence[0];
 
         private int mCachedContrastColor = COLOR_INVALID;
         private int mCachedContrastColorIsFor = COLOR_INVALID;
@@ -155,6 +156,9 @@
             userSentiment = ranking.getUserSentiment();
             smartActions = ranking.getSmartActions() == null
                     ? Collections.emptyList() : ranking.getSmartActions();
+            smartReplies = ranking.getSmartReplies() == null
+                    ? new CharSequence[0]
+                    : ranking.getSmartReplies().toArray(new CharSequence[0]);
         }
 
         public void setInterruption() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index da1fd3b..0110610 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -36,6 +36,7 @@
 import android.widget.LinearLayout;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
@@ -1229,32 +1230,40 @@
         boolean hasRemoteInput = false;
         RemoteInput remoteInputWithChoices = null;
         PendingIntent pendingIntentWithChoices = null;
+        CharSequence[] choices = null;
 
         Notification.Action[] actions = entry.notification.getNotification().actions;
         if (actions != null) {
             for (Notification.Action a : actions) {
-                if (a.getRemoteInputs() != null) {
-                    for (RemoteInput ri : a.getRemoteInputs()) {
-                        boolean showRemoteInputView = ri.getAllowFreeFormInput();
-                        boolean showSmartReplyView = enableSmartReplies && ri.getChoices() != null
-                                && ri.getChoices().length > 0;
-                        if (showRemoteInputView) {
-                            hasRemoteInput = true;
+                if (a.getRemoteInputs() == null) {
+                    continue;
+                }
+                for (RemoteInput ri : a.getRemoteInputs()) {
+                    boolean showRemoteInputView = ri.getAllowFreeFormInput();
+                    boolean showSmartReplyView = enableSmartReplies
+                            && (ArrayUtils.isEmpty(ri.getChoices())
+                            || (showRemoteInputView && !ArrayUtils.isEmpty(entry.smartReplies)));
+                    if (showRemoteInputView) {
+                        hasRemoteInput = true;
+                    }
+                    if (showSmartReplyView) {
+                        remoteInputWithChoices = ri;
+                        pendingIntentWithChoices = a.actionIntent;
+                        if (!ArrayUtils.isEmpty(ri.getChoices())) {
+                            choices = ri.getChoices();
+                        } else {
+                            choices = entry.smartReplies;
                         }
-                        if (showSmartReplyView) {
-                            remoteInputWithChoices = ri;
-                            pendingIntentWithChoices = a.actionIntent;
-                        }
-                        if (showRemoteInputView || showSmartReplyView) {
-                            break;
-                        }
+                    }
+                    if (showRemoteInputView || showSmartReplyView) {
+                        break;
                     }
                 }
             }
         }
 
         applyRemoteInput(entry, hasRemoteInput);
-        applySmartReplyView(remoteInputWithChoices, pendingIntentWithChoices, entry);
+        applySmartReplyView(remoteInputWithChoices, pendingIntentWithChoices, entry, choices);
     }
 
     private void applyRemoteInput(NotificationData.Entry entry, boolean hasRemoteInput) {
@@ -1356,10 +1365,10 @@
     }
 
     private void applySmartReplyView(RemoteInput remoteInput, PendingIntent pendingIntent,
-            NotificationData.Entry entry) {
+            NotificationData.Entry entry, CharSequence[] choices) {
         if (mExpandedChild != null) {
             mExpandedSmartReplyView =
-                    applySmartReplyView(mExpandedChild, remoteInput, pendingIntent, entry);
+                    applySmartReplyView(mExpandedChild, remoteInput, pendingIntent, entry, choices);
             if (mExpandedSmartReplyView != null && remoteInput != null
                     && remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) {
                 mSmartReplyController.smartRepliesAdded(entry, remoteInput.getChoices().length);
@@ -1369,7 +1378,7 @@
 
     private SmartReplyView applySmartReplyView(
             View view, RemoteInput remoteInput, PendingIntent pendingIntent,
-            NotificationData.Entry entry) {
+            NotificationData.Entry entry, CharSequence[] choices) {
         View smartReplyContainerCandidate = view.findViewById(
                 com.android.internal.R.id.smart_reply_container);
         if (!(smartReplyContainerCandidate instanceof LinearLayout)) {
@@ -1406,7 +1415,8 @@
         }
         if (smartReplyView != null) {
             smartReplyView.setRepliesFromRemoteInput(remoteInput, pendingIntent,
-                    mSmartReplyController, entry, smartReplyContainer);
+                    mSmartReplyController, entry, smartReplyContainer, choices
+            );
             smartReplyContainer.setVisibility(View.VISIBLE);
         }
         return smartReplyView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 252ab22..c76a4b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -173,14 +173,14 @@
                 Math.max(getChildCount(), 1), DECREASING_MEASURED_WIDTH_WITHOUT_PADDING_COMPARATOR);
     }
 
-    public void setRepliesFromRemoteInput(RemoteInput remoteInput, PendingIntent pendingIntent,
+    public void setRepliesFromRemoteInput(
+            RemoteInput remoteInput, PendingIntent pendingIntent,
             SmartReplyController smartReplyController, NotificationData.Entry entry,
-            View smartReplyContainer) {
+            View smartReplyContainer, CharSequence[] choices) {
         mSmartReplyContainer = smartReplyContainer;
         removeAllViews();
         mCurrentBackgroundColor = mDefaultBackgroundColor;
         if (remoteInput != null && pendingIntent != null) {
-            CharSequence[] choices = remoteInput.getChoices();
             if (choices != null) {
                 for (int i = 0; i < choices.length; ++i) {
                     Button replyButton = inflateReplyButton(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 7855b47..02babac 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -148,6 +148,7 @@
     private SafetyWarningDialog mSafetyWarning;
     private boolean mHovering = false;
     private boolean mShowActiveStreamOnly;
+    private boolean mConfigChanged = false;
 
     public VolumeDialogImpl(Context context) {
         mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
@@ -551,6 +552,11 @@
         rescheduleTimeoutH();
         mShowing = true;
 
+        if (mConfigChanged) {
+            initDialog();
+            mConfigurableTexts.update();
+            mConfigChanged = false;
+        }
         initSettingsH();
         mDialog.show();
         Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
@@ -1102,8 +1108,7 @@
         @Override
         public void onConfigurationChanged() {
             mDialog.dismiss();
-            initDialog();
-            mConfigurableTexts.update();
+            mConfigChanged = true;
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
index ce47e60..db1e049 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationUiAdjustmentTest.java
@@ -30,6 +30,7 @@
 import org.junit.Test;
 
 import java.util.Collections;
+import java.util.List;
 
 @SmallTest
 public class NotificationUiAdjustmentTest extends SysuiTestCase {
@@ -41,8 +42,8 @@
         Notification.Action action =
                 createActionBuilder("first", R.drawable.ic_corp_icon, pendingIntent).build();
         assertThat(NotificationUiAdjustment.needReinflate(
-                new NotificationUiAdjustment("first", Collections.emptyList()),
-                new NotificationUiAdjustment("second", Collections.singletonList(action))))
+                createUiAdjustmentFromSmartActions("first", Collections.emptyList()),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(action))))
                 .isTrue();
     }
 
@@ -56,8 +57,8 @@
                 createActionBuilder("second", R.drawable.ic_corp_icon, pendingIntent).build();
 
         assertThat(NotificationUiAdjustment.needReinflate(
-                new NotificationUiAdjustment("first", Collections.singletonList(firstAction)),
-                new NotificationUiAdjustment("second", Collections.singletonList(secondAction))))
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
                 .isTrue();
     }
 
@@ -72,8 +73,8 @@
                         .build();
 
         assertThat(NotificationUiAdjustment.needReinflate(
-                new NotificationUiAdjustment("first", Collections.singletonList(firstAction)),
-                new NotificationUiAdjustment("second", Collections.singletonList(secondAction))))
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
                 .isTrue();
     }
 
@@ -91,8 +92,8 @@
                         .build();
 
         assertThat(NotificationUiAdjustment.needReinflate(
-                new NotificationUiAdjustment("first", Collections.singletonList(firstAction)),
-                new NotificationUiAdjustment("second", Collections.singletonList(secondAction))))
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
                 .isTrue();
     }
 
@@ -116,8 +117,8 @@
                         .build();
 
         assertThat(NotificationUiAdjustment.needReinflate(
-                new NotificationUiAdjustment("first", Collections.singletonList(firstAction)),
-                new NotificationUiAdjustment("second", Collections.singletonList(secondAction))))
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
                 .isTrue();
     }
 
@@ -141,8 +142,8 @@
                         .build();
 
         assertThat(NotificationUiAdjustment.needReinflate(
-                new NotificationUiAdjustment("first", Collections.singletonList(firstAction)),
-                new NotificationUiAdjustment("second", Collections.singletonList(secondAction))))
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions("second", Collections.singletonList(secondAction))))
                 .isTrue();
     }
 
@@ -163,8 +164,25 @@
                         .addRemoteInput(secondRemoteInput).build();
 
         assertThat(NotificationUiAdjustment.needReinflate(
-                new NotificationUiAdjustment("first", Collections.singletonList(firstAction)),
-                new NotificationUiAdjustment("second", Collections.singletonList(secondAction))))
+                createUiAdjustmentFromSmartActions("first", Collections.singletonList(firstAction)),
+                createUiAdjustmentFromSmartActions(
+                        "second", Collections.singletonList(secondAction))))
+                .isFalse();
+    }
+
+    @Test
+    public void needReinflate_differentSmartReplies() {
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartReplies("first", new CharSequence[]{"a", "b"}),
+                createUiAdjustmentFromSmartReplies("first", new CharSequence[] {"b", "a"})))
+                .isTrue();
+    }
+
+    @Test
+    public void needReinflate_sameSmartReplies() {
+        assertThat(NotificationUiAdjustment.needReinflate(
+                createUiAdjustmentFromSmartReplies("first", new CharSequence[] {"a", "b"}),
+                createUiAdjustmentFromSmartReplies("first", new CharSequence[] {"a", "b"})))
                 .isFalse();
     }
 
@@ -177,4 +195,14 @@
     private RemoteInput createRemoteInput(String resultKey, String label, CharSequence[] choices) {
         return new RemoteInput.Builder(resultKey).setLabel(label).setChoices(choices).build();
     }
+
+    private NotificationUiAdjustment createUiAdjustmentFromSmartActions(
+            String key, List<Notification.Action> actions) {
+        return new NotificationUiAdjustment(key, actions, new CharSequence[0]);
+    }
+
+    private NotificationUiAdjustment createUiAdjustmentFromSmartReplies(
+            String key, CharSequence[] replies) {
+        return new NotificationUiAdjustment(key, Collections.emptyList(), replies);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
index c3683b3..de5a8a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
@@ -430,21 +430,22 @@
                         outRanking.getImportance(), outRanking.getImportanceExplanation(),
                         outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
                         outRanking.canShowBadge(), outRanking.getUserSentiment(), true,
-                        null);
+                        null, null);
             } else if (key.equals(TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY)) {
                 outRanking.populate(key, outRanking.getRank(),
                         outRanking.matchesInterruptionFilter(),
                         outRanking.getVisibilityOverride(), 255,
                         outRanking.getImportance(), outRanking.getImportanceExplanation(),
                         outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
-                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true, null);
+                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true, null, null);
             } else {
                 outRanking.populate(key, outRanking.getRank(),
                         outRanking.matchesInterruptionFilter(),
                         outRanking.getVisibilityOverride(), outRanking.getSuppressedVisualEffects(),
                         outRanking.getImportance(), outRanking.getImportanceExplanation(),
                         outRanking.getOverrideGroupKey(), NOTIFICATION_CHANNEL, null, null,
-                        outRanking.canShowBadge(), outRanking.getUserSentiment(), false, null);
+                        outRanking.canShowBadge(), outRanking.getUserSentiment(), false, null,
+                        null);
             }
             return true;
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 61c1ecb..6543bdb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -157,7 +157,7 @@
                     0,
                     NotificationManager.IMPORTANCE_DEFAULT,
                     null, null,
-                    null, null, null, true, sentiment, false, null);
+                    null, null, null, true, sentiment, false, null, null);
             return true;
         }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
     }
@@ -176,7 +176,7 @@
                     null, null,
                     null, null, null, true,
                     NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false,
-                    smartActions);
+                    smartActions, null);
             return true;
         }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index 5ac2190..01e6307 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -375,7 +375,7 @@
         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
                 new Intent(TEST_ACTION), 0);
         RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).setChoices(choices).build();
-        mView.setRepliesFromRemoteInput(input, pendingIntent, mLogger, mEntry, mContainer);
+        mView.setRepliesFromRemoteInput(input, pendingIntent, mLogger, mEntry, mContainer, choices);
     }
 
     /** Builds a {@link ViewGroup} whose measures and layout mirror a {@link SmartReplyView}. */
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 11b2343..cf08681 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -22,10 +22,8 @@
 import android.util.DebugUtils;
 import android.util.ExceptionUtils;
 import android.util.Log;
-import android.util.Pools.SimplePool;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
-import android.view.Choreographer;
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.InputFilter;
@@ -104,31 +102,12 @@
             | FLAG_FEATURE_AUTOCLICK | FLAG_FEATURE_TOUCH_EXPLORATION
             | FLAG_FEATURE_SCREEN_MAGNIFIER | FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER;
 
-    private final Runnable mProcessBatchedEventsRunnable = new Runnable() {
-        @Override
-        public void run() {
-            final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
-            if (DEBUG) {
-                Slog.i(TAG, "Begin batch processing for frame: " + frameTimeNanos);
-            }
-            processBatchedEvents(frameTimeNanos);
-            if (DEBUG) {
-                Slog.i(TAG, "End batch processing.");
-            }
-            if (mEventQueue != null) {
-                scheduleProcessBatchedEvents();
-            }
-        }
-    };
-
     private final Context mContext;
 
     private final PowerManager mPm;
 
     private final AccessibilityManagerService mAms;
 
-    private final Choreographer mChoreographer;
-
     private boolean mInstalled;
 
     private int mUserId;
@@ -147,8 +126,6 @@
 
     private EventStreamTransformation mEventHandler;
 
-    private MotionEventHolder mEventQueue;
-
     private EventStreamState mMouseStreamState;
 
     private EventStreamState mTouchScreenStreamState;
@@ -160,7 +137,6 @@
         mContext = context;
         mAms = service;
         mPm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mChoreographer = Choreographer.getInstance();
     }
 
     @Override
@@ -274,7 +250,7 @@
             return;
         }
 
-        batchMotionEvent(event, policyFlags);
+        handleMotionEvent(event, policyFlags);
     }
 
     private void processKeyEvent(EventStreamState state, KeyEvent event, int policyFlags) {
@@ -285,68 +261,14 @@
         mEventHandler.onKeyEvent(event, policyFlags);
     }
 
-    private void scheduleProcessBatchedEvents() {
-        mChoreographer.postCallback(Choreographer.CALLBACK_INPUT,
-                mProcessBatchedEventsRunnable, null);
-    }
-
-    private void batchMotionEvent(MotionEvent event, int policyFlags) {
-        if (DEBUG) {
-            Slog.i(TAG, "Batching event: " + event + ", policyFlags: " + policyFlags);
-        }
-        if (mEventQueue == null) {
-            mEventQueue = MotionEventHolder.obtain(event, policyFlags);
-            scheduleProcessBatchedEvents();
-            return;
-        }
-        if (mEventQueue.event.addBatch(event)) {
-            return;
-        }
-        MotionEventHolder holder = MotionEventHolder.obtain(event, policyFlags);
-        holder.next = mEventQueue;
-        mEventQueue.previous = holder;
-        mEventQueue = holder;
-    }
-
-    private void processBatchedEvents(long frameNanos) {
-        MotionEventHolder current = mEventQueue;
-        if (current == null) {
-            return;
-        }
-        while (current.next != null) {
-            current = current.next;
-        }
-        while (true) {
-            if (current == null) {
-                mEventQueue = null;
-                break;
-            }
-            if (current.event.getEventTimeNano() >= frameNanos) {
-                // Finished with this choreographer frame. Do the rest on the next one.
-                current.next = null;
-                break;
-            }
-            handleMotionEvent(current.event, current.policyFlags);
-            MotionEventHolder prior = current;
-            current = current.previous;
-            prior.recycle();
-        }
-    }
-
     private void handleMotionEvent(MotionEvent event, int policyFlags) {
         if (DEBUG) {
-            Slog.i(TAG, "Handling batched event: " + event + ", policyFlags: " + policyFlags);
+            Slog.i(TAG, "Handling motion event: " + event + ", policyFlags: " + policyFlags);
         }
-        // Since we do batch processing it is possible that by the time the
-        // next batch is processed the event handle had been set to null.
-        if (mEventHandler != null) {
-            mPm.userActivity(event.getEventTime(), false);
-            MotionEvent transformedEvent = MotionEvent.obtain(event);
-            mEventHandler.onMotionEvent(transformedEvent, event, policyFlags);
-            transformedEvent.recycle();
-        } else {
-            if (DEBUG) Slog.d(TAG, "mEventHandler == null for " + event);
-        }
+        mPm.userActivity(event.getEventTime(), false);
+        MotionEvent transformedEvent = MotionEvent.obtain(event);
+        mEventHandler.onMotionEvent(transformedEvent, event, policyFlags);
+        transformedEvent.recycle();
     }
 
     @Override
@@ -469,9 +391,6 @@
     }
 
     private void disableFeatures() {
-        // Give the features a chance to process any batched events so we'll keep a consistent
-        // event stream
-        processBatchedEvents(Long.MAX_VALUE);
         if (mMotionEventInjector != null) {
             mAms.setMotionEventInjector(null);
             mMotionEventInjector.onDestroy();
@@ -515,36 +434,6 @@
         /* ignore */
     }
 
-    private static class MotionEventHolder {
-        private static final int MAX_POOL_SIZE = 32;
-        private static final SimplePool<MotionEventHolder> sPool =
-                new SimplePool<MotionEventHolder>(MAX_POOL_SIZE);
-
-        public int policyFlags;
-        public MotionEvent event;
-        public MotionEventHolder next;
-        public MotionEventHolder previous;
-
-        public static MotionEventHolder obtain(MotionEvent event, int policyFlags) {
-            MotionEventHolder holder = sPool.acquire();
-            if (holder == null) {
-                holder = new MotionEventHolder();
-            }
-            holder.event = MotionEvent.obtain(event);
-            holder.policyFlags = policyFlags;
-            return holder;
-        }
-
-        public void recycle() {
-            event.recycle();
-            event = null;
-            policyFlags = 0;
-            next = null;
-            previous = null;
-            sPool.release(this);
-        }
-    }
-
     /**
      * Keeps state of event streams observed for an input device with a certain source.
      * Provides information about whether motion and key events should be processed by accessibility
diff --git a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
index 293f908e..8ee6571 100644
--- a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
+++ b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
@@ -17,8 +17,8 @@
 
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sVerbose;
-import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS;
-import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM;
+import static android.service.autofill.AutofillFieldClassificationService.RESOURCE_AVAILABLE_ALGORITHMS;
+import static android.service.autofill.AutofillFieldClassificationService.RESOURCE_DEFAULT_ALGORITHM;
 
 import android.Manifest;
 import android.annotation.MainThread;
@@ -226,7 +226,7 @@
      */
     @Nullable
     String[] getAvailableAlgorithms() {
-        return getMetadataValue(SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS,
+        return getMetadataValue(RESOURCE_AVAILABLE_ALGORITHMS, "array",
                 (res, id) -> res.getStringArray(id));
     }
 
@@ -235,11 +235,12 @@
      */
     @Nullable
     String getDefaultAlgorithm() {
-        return getMetadataValue(SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM, (res, id) -> res.getString(id));
+        return getMetadataValue(RESOURCE_DEFAULT_ALGORITHM, "string",
+                (res, id) -> res.getString(id));
     }
 
     @Nullable
-    private <T> T getMetadataValue(String field, MetadataParser<T> parser) {
+    private <T> T getMetadataValue(String field, String type, MetadataParser<T> parser) {
         final ServiceInfo serviceInfo = getServiceInfo();
         if (serviceInfo == null) return null;
 
@@ -253,7 +254,7 @@
             return null;
         }
 
-        final int resourceId = serviceInfo.metaData.getInt(field);
+        final int resourceId = res.getIdentifier(field, type, serviceInfo.packageName);
         return parser.get(res, resourceId);
     }
 
diff --git a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
index ae2a36b..30ec8ab 100644
--- a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
@@ -9,6 +9,7 @@
 
 import android.app.ApplicationThreadConstants;
 import android.app.IBackupAgent;
+import android.app.backup.IBackupCallback;
 import android.app.backup.FullBackup;
 import android.app.backup.FullBackupDataOutput;
 import android.content.pm.ApplicationInfo;
@@ -20,6 +21,7 @@
 import android.util.Slog;
 
 import com.android.internal.util.Preconditions;
+import com.android.server.backup.remote.ServiceBackupCallback;
 import com.android.server.backup.utils.FullBackupUtils;
 
 import libcore.io.IoUtils;
@@ -158,10 +160,17 @@
             mBackupManagerService.prepareOperationTimeout(token, kvBackupAgentTimeoutMillis, null,
                     OP_TYPE_BACKUP_WAIT);
 
+            IBackupCallback callback =
+                    new ServiceBackupCallback(
+                            mBackupManagerService.getBackupManagerBinder(), token);
             // Start backup and wait for BackupManagerService to get callback for success or timeout
             agent.doBackup(
-                    mSavedState, mBackupData, mNewState, Long.MAX_VALUE, token,
-                    mBackupManagerService.getBackupManagerBinder(), /*transportFlags=*/ 0);
+                    mSavedState,
+                    mBackupData,
+                    mNewState,
+                    /* quotaBytes */ Long.MAX_VALUE,
+                    callback,
+                    /* transportFlags */ 0);
             if (!mBackupManagerService.waitUntilOperationComplete(token)) {
                 Slog.e(TAG, "Key-value backup failed on package " + packageName);
                 return false;
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 69f08ae..66b6b37 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -38,7 +38,6 @@
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.DataChangedJournal;
-import com.android.server.backup.transport.TransportClient;
 import com.android.server.backup.TransportManager;
 import com.android.server.backup.fullbackup.PerformAdbBackupTask;
 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
@@ -52,6 +51,7 @@
 import com.android.server.backup.params.RestoreParams;
 import com.android.server.backup.restore.PerformAdbRestoreTask;
 import com.android.server.backup.restore.PerformUnifiedRestoreTask;
+import com.android.server.backup.transport.TransportClient;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -150,17 +150,22 @@
                 if (queue.size() > 0) {
                     // Spin up a backup state sequence and set it running
                     try {
-                        String dirName = transport.transportDirName();
                         OnTaskFinishedListener listener =
                                 caller ->
                                         transportManager
                                                 .disposeOfTransportClient(transportClient, caller);
-                        PerformBackupTask pbt = new PerformBackupTask(
-                                backupManagerService, transportClient, dirName, queue,
-                                oldJournal, null, null, listener, Collections.emptyList(), false,
-                                false /* nonIncremental */);
-                        Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
-                        sendMessage(pbtMessage);
+                        PerformBackupTask.start(
+                                backupManagerService,
+                                transportClient,
+                                transport.transportDirName(),
+                                queue,
+                                oldJournal,
+                                /* observer */ null,
+                                /* monitor */ null,
+                                listener,
+                                Collections.emptyList(),
+                                /* userInitiated */ false,
+                                /* nonIncremental */ false);
                     } catch (Exception e) {
                         // unable to ask the transport its dir name -- transient failure, since
                         // the above check succeeded.  Try again next time.
@@ -405,13 +410,18 @@
                 backupManagerService.setBackupRunning(true);
                 backupManagerService.getWakelock().acquire();
 
-                PerformBackupTask pbt = new PerformBackupTask(
+                PerformBackupTask.start(
                         backupManagerService,
-                        params.transportClient, params.dirName,
-                        kvQueue, null, params.observer, params.monitor, params.listener,
-                        params.fullPackages, true, params.nonIncrementalBackup);
-                Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
-                sendMessage(pbtMessage);
+                        params.transportClient,
+                        params.dirName,
+                        kvQueue,
+                        /* dataChangedJournal */ null,
+                        params.observer,
+                        params.monitor,
+                        params.listener,
+                        params.fullPackages,
+                        /* userInitiated */ true,
+                        params.nonIncrementalBackup);
                 break;
             }
 
diff --git a/services/backup/java/com/android/server/backup/internal/BackupState.java b/services/backup/java/com/android/server/backup/internal/BackupState.java
index 937b167..320b555 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupState.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupState.java
@@ -7,5 +7,6 @@
     INITIAL,
     BACKUP_PM,
     RUNNING_QUEUE,
+    CANCELLED,
     FINAL
 }
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 551b80f..c5df82e 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -16,16 +16,11 @@
 
 package com.android.server.backup.internal;
 
-import static com.android.server.backup.BackupManagerService.DEBUG;
 import static com.android.server.backup.BackupManagerService.DEBUG_BACKUP_TRACE;
 import static com.android.server.backup.BackupManagerService.KEY_WIDGET_STATE;
-import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
 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.PACKAGE_MANAGER_SENTINEL;
-import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT;
-import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
 
 import android.annotation.Nullable;
 import android.app.ApplicationThreadConstants;
@@ -36,14 +31,16 @@
 import android.app.backup.BackupManager;
 import android.app.backup.BackupManagerMonitor;
 import android.app.backup.BackupTransport;
+import android.app.backup.IBackupCallback;
+import android.app.backup.IBackupManager;
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IBackupObserver;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Message;
+import android.os.ConditionVariable;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SELinux;
 import android.os.UserHandle;
@@ -51,23 +48,24 @@
 import android.system.ErrnoException;
 import android.system.Os;
 import android.util.EventLog;
+import android.util.Pair;
 import android.util.Slog;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.backup.IBackupTransport;
 import com.android.internal.util.Preconditions;
 import com.android.server.AppWidgetBackupBridge;
 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;
 import com.android.server.backup.KeyValueBackupJob;
-import com.android.server.backup.PackageManagerBackupAgent;
-import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
+import com.android.server.backup.remote.RemoteCall;
+import com.android.server.backup.remote.RemoteCallable;
+import com.android.server.backup.remote.RemoteResult;
 import com.android.server.backup.transport.TransportClient;
-import com.android.server.backup.transport.TransportUtils;
 import com.android.server.backup.utils.AppBackupUtils;
 import com.android.server.backup.utils.BackupManagerMonitorUtils;
 import com.android.server.backup.utils.BackupObserverUtils;
@@ -85,85 +83,225 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
- * This class handles the process of backing up a given list of key/value backup packages.
- * Also takes in a list of pending dolly backups and kicks them off when key/value backups
- * are done.
+ * Represents the task of performing a sequence of key-value backups for a given list of packages.
+ * Method {@link #run()} executes the backups to the transport specified via the {@code
+ * transportClient} parameter in the constructor.
  *
- * Flow:
- * If required, backup @pm@.
- * For each pending key/value backup package:
- *     - Bind to agent.
- *     - Call agent.doBackup()
- *     - Wait either for cancel/timeout or operationComplete() callback from the agent.
- * Start task to perform dolly backups.
+ * <p>A few definitions:
  *
- * There are three entry points into this class:
- *     - execute() [Called from the handler thread]
- *     - operationComplete(long result) [Called from the handler thread]
- *     - handleCancel(boolean cancelAll) [Can be called from any thread]
- * These methods synchronize on mCancelLock.
+ * <ul>
+ *   <li>State directory: {@link BackupManagerService#getBaseStateDir()}/&lt;transport&gt;
+ *   <li>State file: {@link
+ *       BackupManagerService#getBaseStateDir()}/&lt;transport&gt;/&lt;package&gt;<br>
+ *       Represents the state of the backup data for a specific package in the current dataset.
+ *   <li>Stage directory: {@link BackupManagerService#getDataDir()}
+ *   <li>Stage file: {@link BackupManagerService#getDataDir()}/&lt;package&gt;.data<br>
+ *       Contains staged data that the agents wrote via {@link BackupDataOutput}, to be transmitted
+ *       to the transport.
+ * </ul>
  *
- * Interaction with mCurrentOperations:
- *     - An entry for this task is put into mCurrentOperations for the entire lifetime of the
- *       task. This is useful to cancel the task if required.
- *     - An ephemeral entry is put into mCurrentOperations each time we are waiting on for
- *       response from a backup agent. This is used to plumb timeouts and completion callbacks.
+ * If there is no PackageManager (PM) pseudo-package state file in the state directory, the
+ * specified transport will be initialized with {@link IBackupTransport#initializeDevice()}.
+ *
+ * <p>The PM pseudo-package is the first package to be backed-up and sent to the transport in case
+ * of incremental choice. If non-incremental, PM will only be backed-up if specified in the queue,
+ * and if it's the case it will be re-positioned at the head of the queue.
+ *
+ * <p>Before starting, this task will register itself in {@link BackupManagerService} current
+ * operations.
+ *
+ * <p>In summary, this task will for each package:
+ *
+ * <ul>
+ *   <li>Bind to its {@link IBackupAgent}.
+ *   <li>Request transport quota and flags.
+ *   <li>Call {@link IBackupAgent#doBackup(ParcelFileDescriptor, ParcelFileDescriptor,
+ *       ParcelFileDescriptor, long, int, IBackupManager, int)} via {@link RemoteCall} passing the
+ *       old state file descriptor (read), the backup data file descriptor (write), the new state
+ *       file descriptor (write), the quota and the transport flags. This will call {@link
+ *       BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)} with
+ *       the old state file to be read, a {@link BackupDataOutput} object to write the backup data
+ *       and the new state file to write. By writing to {@link BackupDataOutput}, the agent will
+ *       write data to the stage file. The task will block waiting for either:
+ *       <ul>
+ *         <li>Agent response.
+ *         <li>Agent time-out (specified via {@link
+ *             BackupManagerService#getAgentTimeoutParameters()}.
+ *         <li>External cancellation or thread interrupt.
+ *       </ul>
+ *   <li>Unbind the agent.
+ *   <li>Assuming agent response, send the staged data that the agent wrote to disk to the transport
+ *       via {@link IBackupTransport#performBackup(PackageInfo, ParcelFileDescriptor, int)}.
+ *   <li>Call {@link IBackupTransport#finishBackup()} if previous call was successful.
+ *   <li>Save the new state in the state file. During the agent call it was being written to
+ *       &lt;state file&gt;.new, here we rename it and replace the old one.
+ *   <li>Delete the stage file.
+ * </ul>
+ *
+ * In the end, this task will:
+ *
+ * <ul>
+ *   <li>Mark data-changed for the remaining packages in the queue (skipped packages).
+ *   <li>Delete the {@link DataChangedJournal} provided. Note that this should not be the current
+ *       journal.
+ *   <li>Set {@link BackupManagerService} current token as {@link
+ *       IBackupTransport#getCurrentRestoreSet()}, if applicable.
+ *   <li>Add the transport to the list of transports pending initialization ({@link
+ *       BackupManagerService#getPendingInits()}) and kick-off initialization if the transport ever
+ *       returned {@link BackupTransport#TRANSPORT_NOT_INITIALIZED}.
+ *   <li>Unregister the task in current operations.
+ *   <li>Release the wakelock.
+ *   <li>Kick-off {@link PerformFullTransportBackupTask} if a list of full-backup packages was
+ *       provided.
+ * </ul>
+ *
+ * The caller can specify whether this should be an incremental or non-incremental backup. In the
+ * case of non-incremental the agents will be passed an empty old state file, which signals that a
+ * complete backup should be performed.
+ *
+ * <p>This task is designed to run on a dedicated thread, with the exception of the {@link
+ * #handleCancel(boolean)} method, which can be called from any thread.
  */
-public class PerformBackupTask implements BackupRestoreTask {
+// TODO: Stop poking into BMS state and doing things for it (e.g. synchronizing on public locks)
+// TODO: Consider having the caller responsible for some clean-up (like resetting state)
+// TODO: Distinguish between cancel and time-out where possible for logging/monitoring/observing
+public class PerformBackupTask implements BackupRestoreTask, Runnable {
     private static final String TAG = "PerformBackupTask";
+    private static final boolean DEBUG = BackupManagerService.DEBUG || true;
+    private static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || false;
+    private static final int THREAD_PRIORITY = Process.THREAD_PRIORITY_BACKGROUND;
+    private static final AtomicInteger THREAD_COUNT = new AtomicInteger();
     private static final String BLANK_STATE_FILE_NAME = "blank_state";
     @VisibleForTesting
     public static final String STAGING_FILE_SUFFIX = ".data";
     @VisibleForTesting
     public static final String NEW_STATE_FILE_SUFFIX = ".new";
 
-    private BackupManagerService backupManagerService;
-    private final Object mCancelLock = new Object();
+    /**
+     * Creates a new {@link PerformBackupTask} for key-value backup operation, spins up a new
+     * dedicated thread and kicks off the operation in it.
+     *
+     * @param backupManagerService The {@link BackupManagerService} system service.
+     * @param transportClient The {@link TransportClient} that contains the transport used for the
+     *     operation.
+     * @param transportDirName The value of {@link IBackupTransport#transportDirName()} for the
+     *     transport whose {@link TransportClient} was provided above.
+     * @param queue The list of packages that will be backed-up, in the form of {@link
+     *     BackupRequest}.
+     * @param dataChangedJournal The old data-changed journal file that will be deleted when the
+     *     operation finishes (successfully or not) or {@code null}.
+     * @param observer A {@link IBackupObserver}.
+     * @param monitor A {@link IBackupManagerMonitor}.
+     * @param listener A {@link OnTaskFinishedListener} or {@code null}.
+     * @param pendingFullBackups The list of packages that will be passed for a new {@link
+     *     PerformFullTransportBackupTask} operation, which will be started when this finishes.
+     * @param userInitiated Whether this was user-initiated or not.
+     * @param nonIncremental If {@code true}, this will be a complete backup for each package,
+     *     otherwise it will be just an incremental one over the current dataset.
+     * @return The {@link PerformBackupTask} that was started.
+     */
+    public static PerformBackupTask start(
+            BackupManagerService backupManagerService,
+            TransportClient transportClient,
+            String transportDirName,
+            ArrayList<BackupRequest> queue,
+            @Nullable DataChangedJournal dataChangedJournal,
+            IBackupObserver observer,
+            IBackupManagerMonitor monitor,
+            @Nullable OnTaskFinishedListener listener,
+            List<String> pendingFullBackups,
+            boolean userInitiated,
+            boolean nonIncremental) {
+        PerformBackupTask task =
+                new PerformBackupTask(
+                        backupManagerService,
+                        transportClient,
+                        transportDirName,
+                        queue,
+                        dataChangedJournal,
+                        observer,
+                        monitor,
+                        listener,
+                        pendingFullBackups,
+                        userInitiated,
+                        nonIncremental);
+        Thread thread = new Thread(task, "key-value-backup-" + THREAD_COUNT.incrementAndGet());
+        if (DEBUG) {
+            Slog.d(TAG, "Spinning thread " + thread.getName());
+        }
+        thread.start();
+        return task;
+    }
 
-    private ArrayList<BackupRequest> mQueue;
-    private ArrayList<BackupRequest> mOriginalQueue;
-    private File mStateDir;
-    @Nullable private DataChangedJournal mJournal;
-    private BackupState mCurrentState;
-    private List<String> mPendingFullBackups;
-    private IBackupObserver mObserver;
-    private IBackupManagerMonitor mMonitor;
-
+    private final BackupManagerService mBackupManagerService;
     private final TransportClient mTransportClient;
+    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
+    private final IBackupObserver mObserver;
     private final OnTaskFinishedListener mListener;
-    private final PerformFullTransportBackupTask mFullBackupTask;
+    private final boolean mUserInitiated;
+    private final boolean mNonIncremental;
     private final int mCurrentOpToken;
-    private volatile int mEphemeralOpToken;
+    private final File mStateDir;
+    private final ArrayList<BackupRequest> mOriginalQueue;
+    private final ArrayList<BackupRequest> mQueue;
+    private final List<String> mPendingFullBackups;
+    @Nullable private final DataChangedJournal mJournal;
+    private IBackupManagerMonitor mMonitor;
+    @Nullable private PerformFullTransportBackupTask mFullBackupTask;
 
-    // carried information about the current in-flight operation
     private IBackupAgent mAgentBinder;
     private PackageInfo mCurrentPackage;
-    private File mSavedStateName;
-    private File mBackupDataName;
-    private File mNewStateName;
+    private File mSavedStateFile;
+    private File mBackupDataFile;
+    private File mNewStateFile;
     private ParcelFileDescriptor mSavedState;
     private ParcelFileDescriptor mBackupData;
     private ParcelFileDescriptor mNewState;
     private int mStatus;
-    private boolean mFinished;
-    private final boolean mUserInitiated;
-    private final boolean mNonIncremental;
-    private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
 
-    private volatile boolean mCancelAll;
+    /**
+     * This {@link ConditionVariable} is used to signal that the cancel operation has been
+     * received by the task and that no more transport calls will be made. Anyone can call {@link
+     * ConditionVariable#block()} to wait for these conditions to hold true, but there should only
+     * be one place where {@link ConditionVariable#open()} is called. Also there should be no calls
+     * to {@link ConditionVariable#close()}, which means there is only one cancel per backup -
+     * subsequent calls to block will return immediately.
+     */
+    private final ConditionVariable mCancelAcknowledged = new ConditionVariable(false);
 
-    public PerformBackupTask(BackupManagerService backupManagerService,
-            TransportClient transportClient, String dirName,
-            ArrayList<BackupRequest> queue, @Nullable DataChangedJournal journal,
-            IBackupObserver observer, IBackupManagerMonitor monitor,
-            @Nullable OnTaskFinishedListener listener, List<String> pendingFullBackups,
-            boolean userInitiated, boolean nonIncremental) {
-        this.backupManagerService = backupManagerService;
+    /**
+     * Set it to {@code true} and block on {@code mCancelAcknowledged} to wait for the cancellation.
+     * DO NOT set it to {@code false}.
+     */
+    private volatile boolean mCancelled = false;
+
+    /**
+     * If non-{@code null} there is a pending agent call being made. This call can be cancelled (and
+     * control returned to this task) with {@link RemoteCall#cancel()}.
+     */
+    @Nullable private volatile RemoteCall mPendingCall;
+
+    @VisibleForTesting
+    public PerformBackupTask(
+            BackupManagerService backupManagerService,
+            TransportClient transportClient,
+            String transportDirName,
+            ArrayList<BackupRequest> queue,
+            @Nullable DataChangedJournal journal,
+            IBackupObserver observer,
+            IBackupManagerMonitor monitor,
+            @Nullable OnTaskFinishedListener listener,
+            List<String> pendingFullBackups,
+            boolean userInitiated,
+            boolean nonIncremental) {
+        mBackupManagerService = backupManagerService;
         mTransportClient = transportClient;
         mOriginalQueue = queue;
-        mQueue = new ArrayList<>();
+        // We need to retain the original queue contents in case of transport failure
+        mQueue = new ArrayList<>(mOriginalQueue);
         mJournal = journal;
         mObserver = observer;
         mMonitor = monitor;
@@ -171,92 +309,80 @@
         mPendingFullBackups = pendingFullBackups;
         mUserInitiated = userInitiated;
         mNonIncremental = nonIncremental;
-        mAgentTimeoutParameters = Preconditions.checkNotNull(
-                backupManagerService.getAgentTimeoutParameters(),
-                "Timeout parameters cannot be null");
-
-        mStateDir = new File(backupManagerService.getBaseStateDir(), dirName);
+        mAgentTimeoutParameters =
+                Preconditions.checkNotNull(
+                        backupManagerService.getAgentTimeoutParameters(),
+                        "Timeout parameters cannot be null");
+        mStateDir = new File(backupManagerService.getBaseStateDir(), transportDirName);
         mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
-
-        mFinished = false;
-
-        synchronized (backupManagerService.getCurrentOpLock()) {
-            if (backupManagerService.isBackupOperationInProgress()) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Skipping backup since one is already in progress.");
-                }
-                mCancelAll = true;
-                mFullBackupTask = null;
-                mCurrentState = BackupState.FINAL;
-                backupManagerService.addBackupTrace("Skipped. Backup already in progress.");
-            } else {
-                mCurrentState = BackupState.INITIAL;
-                CountDownLatch latch = new CountDownLatch(1);
-                String[] fullBackups =
-                        mPendingFullBackups.toArray(new String[mPendingFullBackups.size()]);
-                mFullBackupTask =
-                        new PerformFullTransportBackupTask(backupManagerService,
-                                transportClient,
-                                /*fullBackupRestoreObserver*/ null,
-                                fullBackups, /*updateSchedule*/ false, /*runningJob*/ null,
-                                latch,
-                                mObserver, mMonitor, mListener, mUserInitiated);
-
-                registerTask();
-                backupManagerService.addBackupTrace("STATE => INITIAL");
-            }
-        }
     }
 
-    /**
-     * Put this task in the repository of running tasks.
-     */
     private void registerTask() {
-        backupManagerService.putOperation(
+        mBackupManagerService.putOperation(
                 mCurrentOpToken, new Operation(OP_PENDING, this, OP_TYPE_BACKUP));
     }
 
-    /**
-     * Remove this task from repository of running tasks.
-     */
     private void unregisterTask() {
-        backupManagerService.removeOperation(mCurrentOpToken);
+        mBackupManagerService.removeOperation(mCurrentOpToken);
     }
 
-    // Main entry point: perform one chunk of work, updating the state as appropriate
-    // and reposting the next chunk to the primary backup handler thread.
     @Override
-    @GuardedBy("mCancelLock")
-    public void execute() {
-        synchronized (mCancelLock) {
-            switch (mCurrentState) {
-                case INITIAL:
-                    beginBackup();
-                    break;
+    public void run() {
+        Process.setThreadPriority(THREAD_PRIORITY);
 
+        BackupState state = beginBackup();
+        while (state == BackupState.RUNNING_QUEUE || state == BackupState.BACKUP_PM) {
+            if (mCancelled) {
+                state = BackupState.CANCELLED;
+            }
+            switch (state) {
                 case BACKUP_PM:
-                    backupPm();
+                    state = backupPm();
                     break;
-
                 case RUNNING_QUEUE:
-                    invokeNextAgent();
-                    break;
-
-                case FINAL:
-                    if (!mFinished) {
-                        finalizeBackup();
-                    } else {
-                        Slog.e(TAG, "Duplicate finish of K/V pass");
+                    Pair<BackupState, RemoteResult> stateAndResult = invokeNextAgent();
+                    state = stateAndResult.first;
+                    if (state == null) {
+                        state = processAgentInvocation(stateAndResult.second);
                     }
                     break;
             }
         }
+        if (state == BackupState.CANCELLED) {
+            finalizeCancelledBackup();
+        } else {
+            finalizeBackup();
+        }
     }
 
-    // We're starting a backup pass.  Initialize the transport if we haven't already.
-    private void beginBackup() {
+    private BackupState processAgentInvocation(RemoteResult result) {
+        if (result == RemoteResult.FAILED_THREAD_INTERRUPTED) {
+            // Not an explicit cancel, we need to flag it
+            mCancelled = true;
+            handleAgentCancelled();
+            return BackupState.CANCELLED;
+        }
+        if (result == RemoteResult.FAILED_CANCELLED) {
+            handleAgentCancelled();
+            return BackupState.CANCELLED;
+        }
+        if (result == RemoteResult.FAILED_TIMED_OUT) {
+            handleAgentTimeout();
+            return BackupState.RUNNING_QUEUE;
+        }
+        Preconditions.checkState(result.succeeded());
+        return handleAgentResult(result.get());
+    }
+
+    @Override
+    public void execute() {}
+
+    @Override
+    public void operationComplete(long unusedResult) {}
+
+    private BackupState beginBackup() {
         if (DEBUG_BACKUP_TRACE) {
-            backupManagerService.clearBackupTrace();
+            mBackupManagerService.clearBackupTrace();
             StringBuilder b = new StringBuilder(256);
             b.append("beginBackup: [");
             for (BackupRequest req : mOriginalQueue) {
@@ -264,8 +390,34 @@
                 b.append(req.packageName);
             }
             b.append(" ]");
-            backupManagerService.addBackupTrace(b.toString());
+            mBackupManagerService.addBackupTrace(b.toString());
         }
+        synchronized (mBackupManagerService.getCurrentOpLock()) {
+            if (mBackupManagerService.isBackupOperationInProgress()) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Skipping backup since one is already in progress.");
+                }
+                mBackupManagerService.addBackupTrace("Skipped. Backup already in progress.");
+                return BackupState.FINAL;
+            }
+        }
+
+        String[] fullBackups = mPendingFullBackups.toArray(new String[mPendingFullBackups.size()]);
+        mFullBackupTask =
+                new PerformFullTransportBackupTask(
+                        mBackupManagerService,
+                        mTransportClient,
+                        /* fullBackupRestoreObserver */ null,
+                        fullBackups,
+                        /* updateSchedule */ false,
+                        /* runningJob */ null,
+                        new CountDownLatch(1),
+                        mObserver,
+                        mMonitor,
+                        mListener,
+                        mUserInitiated);
+        registerTask();
+        mBackupManagerService.addBackupTrace("STATE => INITIAL");
 
         mAgentBinder = null;
         mStatus = BackupTransport.TRANSPORT_OK;
@@ -273,16 +425,10 @@
         // Sanity check: if the queue is empty we have no work to do.
         if (mOriginalQueue.isEmpty() && mPendingFullBackups.isEmpty()) {
             Slog.w(TAG, "Backup begun with an empty queue - nothing to do.");
-            backupManagerService.addBackupTrace("queue empty at begin");
-            executeNextState(BackupState.FINAL);
-            return;
+            mBackupManagerService.addBackupTrace("queue empty at begin");
+            return BackupState.FINAL;
         }
 
-        // We need to retain the original queue contents in case of transport
-        // failure, but we want a working copy that we can manipulate along
-        // the way.
-        mQueue = (ArrayList<BackupRequest>) mOriginalQueue.clone();
-
         // When the transport is forcing non-incremental key/value payloads, we send the
         // metadata only if it explicitly asks for it.
         boolean skipPm = mNonIncremental;
@@ -292,8 +438,7 @@
         // we performed a backup.  Drop it from the working queue now that
         // we're committed to evaluating it for backup regardless.
         for (int i = 0; i < mQueue.size(); i++) {
-            if (PACKAGE_MANAGER_SENTINEL.equals(
-                    mQueue.get(i).packageName)) {
+            if (PACKAGE_MANAGER_SENTINEL.equals(mQueue.get(i).packageName)) {
                 if (MORE_DEBUG) {
                     Slog.i(TAG, "Metadata in queue; eliding");
                 }
@@ -309,17 +454,17 @@
         File pmState = new File(mStateDir, PACKAGE_MANAGER_SENTINEL);
         try {
             IBackupTransport transport = mTransportClient.connectOrThrow("PBT.beginBackup()");
-            final String transportName = transport.transportDirName();
+            String transportName = transport.name();
             EventLog.writeEvent(EventLogTags.BACKUP_START, transportName);
 
             // If we haven't stored package manager metadata yet, we must init the transport.
-            if (mStatus == BackupTransport.TRANSPORT_OK && pmState.length() <= 0) {
+            if (pmState.length() <= 0) {
                 Slog.i(TAG, "Initializing (wiping) backup state and transport storage");
-                backupManagerService.addBackupTrace("initializing transport " + transportName);
-                backupManagerService.resetBackupState(mStateDir);  // Just to make sure.
+                mBackupManagerService.addBackupTrace("initializing transport " + transportName);
+                mBackupManagerService.resetBackupState(mStateDir);  // Just to make sure.
                 mStatus = transport.initializeDevice();
 
-                backupManagerService.addBackupTrace("transport.initializeDevice() == " + mStatus);
+                mBackupManagerService.addBackupTrace("transport.initializeDevice() == " + mStatus);
                 if (mStatus == BackupTransport.TRANSPORT_OK) {
                     EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
                 } else {
@@ -327,82 +472,81 @@
                     Slog.e(TAG, "Transport error in initializeDevice()");
                 }
             }
-
-            if (skipPm) {
-                Slog.d(TAG, "Skipping backup of package metadata.");
-                executeNextState(BackupState.RUNNING_QUEUE);
-            } else {
-                // As the package manager is running here in the system process we can just set up
-                // its agent directly. Thus we always run this pass because it's cheap and this way
-                // we guarantee that we don't get out of step even if we're selecting among various
-                // transports at run time.
-                if (mStatus == BackupTransport.TRANSPORT_OK) {
-                    executeNextState(BackupState.BACKUP_PM);
-                }
-            }
         } catch (Exception e) {
             Slog.e(TAG, "Error in backup thread during init", e);
-            backupManagerService.addBackupTrace("Exception in backup thread during init: " + e);
+            mBackupManagerService.addBackupTrace("Exception in backup thread during init: " + e);
             mStatus = BackupTransport.TRANSPORT_ERROR;
-        } finally {
-            // If we've succeeded so far, we will move to the BACKUP_PM state. If something has gone
-            // wrong then that won't have happen so cleanup.
-            backupManagerService.addBackupTrace("exiting prelim: " + mStatus);
-            if (mStatus != BackupTransport.TRANSPORT_OK) {
-                // if things went wrong at this point, we need to
-                // restage everything and try again later.
-                backupManagerService.resetBackupState(mStateDir);  // Just to make sure.
-                // In case of any other error, it's backup transport error.
-                executeNextState(BackupState.FINAL);
-            }
         }
+        mBackupManagerService.addBackupTrace("exiting prelim: " + mStatus);
+
+        if (mStatus != BackupTransport.TRANSPORT_OK) {
+            // if things went wrong at this point, we need to
+            // restage everything and try again later.
+            mBackupManagerService.resetBackupState(mStateDir);  // Just to make sure.
+            return BackupState.FINAL;
+        }
+
+        if (skipPm) {
+            Slog.d(TAG, "Skipping backup of package metadata.");
+            return BackupState.RUNNING_QUEUE;
+        }
+
+        return BackupState.BACKUP_PM;
     }
 
-    private void backupPm() {
+    private BackupState backupPm() {
+        RemoteResult agentResult = null;
+        BackupState nextState;
         try {
             // The package manager doesn't have a proper <application> etc, but since it's running
             // here in the system process we can just set up its agent directly and use a synthetic
             // BackupRequest.
-            BackupAgent pmAgent = backupManagerService.makeMetadataAgent();
-            mStatus = invokeAgentForBackup(
-                    PACKAGE_MANAGER_SENTINEL,
-                    IBackupAgent.Stub.asInterface(pmAgent.onBind()));
-            backupManagerService.addBackupTrace("PMBA invoke: " + mStatus);
+            BackupAgent pmAgent = mBackupManagerService.makeMetadataAgent();
+            Pair<Integer, RemoteResult> statusAndResult =
+                    invokeAgentForBackup(
+                            PACKAGE_MANAGER_SENTINEL,
+                            IBackupAgent.Stub.asInterface(pmAgent.onBind()));
+            mStatus = statusAndResult.first;
+            agentResult = statusAndResult.second;
 
-            // Because the PMBA is a local instance, it has already executed its backup callback and
-            // returned.  Blow away the lingering (spurious) pending timeout message for it.
-            backupManagerService.getBackupHandler().removeMessages(
-                    MSG_BACKUP_OPERATION_TIMEOUT);
+            mBackupManagerService.addBackupTrace("PMBA invoke: " + mStatus);
         } catch (Exception e) {
             Slog.e(TAG, "Error in backup thread during pm", e);
-            backupManagerService.addBackupTrace("Exception in backup thread during pm: " + e);
+            mBackupManagerService.addBackupTrace("Exception in backup thread during pm: " + e);
             mStatus = BackupTransport.TRANSPORT_ERROR;
-        } finally {
-            // If we've succeeded so far, invokeAgentForBackup() will have run the PM
-            // metadata and its completion/timeout callback will continue the state
-            // machine chain.  If it failed that won't happen; we handle that now.
-            backupManagerService.addBackupTrace("exiting backupPm: " + mStatus);
-            if (mStatus != BackupTransport.TRANSPORT_OK) {
-                // if things went wrong at this point, we need to
-                // restage everything and try again later.
-                backupManagerService.resetBackupState(mStateDir);  // Just to make sure.
-                executeNextState(BackupState.FINAL);
-            }
         }
+        mBackupManagerService.addBackupTrace("exiting backupPm: " + mStatus);
+
+        if (mStatus == BackupTransport.TRANSPORT_OK) {
+            Preconditions.checkNotNull(agentResult);
+            nextState = processAgentInvocation(agentResult);
+        } else {
+            // if things went wrong at this point, we need to
+            // restage everything and try again later.
+            mBackupManagerService.resetBackupState(mStateDir);  // Just to make sure.
+            nextState = BackupState.FINAL;
+        }
+
+        return nextState;
     }
 
-    // Transport has been initialized and the PM metadata submitted successfully
-    // if that was warranted.  Now we process the single next thing in the queue.
-    private void invokeNextAgent() {
+    /**
+     * Returns either:
+     *
+     * <ul>
+     *   <li>(next state, {@code null}): In case we failed to call the agent.
+     *   <li>({@code null}, agent result): In case we successfully called the agent.
+     * </ul>
+     */
+    private Pair<BackupState, RemoteResult> invokeNextAgent() {
         mStatus = BackupTransport.TRANSPORT_OK;
-        backupManagerService.addBackupTrace("invoke q=" + mQueue.size());
+        mBackupManagerService.addBackupTrace("invoke q=" + mQueue.size());
 
         // Sanity check that we have work to do.  If not, skip to the end where
         // we reestablish the wakelock invariants etc.
         if (mQueue.isEmpty()) {
             if (MORE_DEBUG) Slog.i(TAG, "queue now empty");
-            executeNextState(BackupState.FINAL);
-            return;
+            return Pair.create(BackupState.FINAL, null);
         }
 
         // pop the entry we're going to process on this step
@@ -410,15 +554,16 @@
         mQueue.remove(0);
 
         Slog.d(TAG, "starting key/value backup of " + request);
-        backupManagerService.addBackupTrace("launch agent for " + request.packageName);
+        mBackupManagerService.addBackupTrace("launch agent for " + request.packageName);
 
         // Verify that the requested app exists; it might be something that
         // requested a backup but was then uninstalled.  The request was
         // journalled and rather than tamper with the journal it's safer
         // to sanity-check here.  This also gives us the classname of the
         // package's backup agent.
+        RemoteResult agentResult = null;
         try {
-            PackageManager pm = backupManagerService.getPackageManager();
+            PackageManager pm = mBackupManagerService.getPackageManager();
             mCurrentPackage = pm.getPackageInfo(request.packageName,
                     PackageManager.GET_SIGNING_CERTIFICATES);
             if (!AppBackupUtils.appIsEligibleForBackup(mCurrentPackage.applicationInfo, pm)) {
@@ -427,14 +572,13 @@
                 // backups.
                 Slog.i(TAG, "Package " + request.packageName
                         + " no longer supports backup; skipping");
-                backupManagerService.addBackupTrace("skipping - not eligible, completion is noop");
+                mBackupManagerService.addBackupTrace("skipping - not eligible, completion is noop");
                 // Shouldn't happen in case of requested backup, as pre-check was done in
                 // #requestBackup(), except to app update done concurrently
                 BackupObserverUtils.sendBackupOnPackageResult(mObserver,
                         mCurrentPackage.packageName,
                         BackupManager.ERROR_BACKUP_NOT_ALLOWED);
-                executeNextState(BackupState.RUNNING_QUEUE);
-                return;
+                return Pair.create(BackupState.RUNNING_QUEUE, null);
             }
 
             if (AppBackupUtils.appGetsFullBackup(mCurrentPackage)) {
@@ -443,42 +587,41 @@
                 // Don't proceed with a key/value backup for it in this case.
                 Slog.i(TAG, "Package " + request.packageName
                         + " requests full-data rather than key/value; skipping");
-                backupManagerService.addBackupTrace(
+                mBackupManagerService.addBackupTrace(
                         "skipping - fullBackupOnly, completion is noop");
                 // Shouldn't happen in case of requested backup, as pre-check was done in
                 // #requestBackup()
                 BackupObserverUtils.sendBackupOnPackageResult(mObserver,
                         mCurrentPackage.packageName,
                         BackupManager.ERROR_BACKUP_NOT_ALLOWED);
-                executeNextState(BackupState.RUNNING_QUEUE);
-                return;
+                return Pair.create(BackupState.RUNNING_QUEUE, null);
             }
 
             if (AppBackupUtils.appIsStopped(mCurrentPackage.applicationInfo)) {
                 // The app has been force-stopped or cleared or just installed,
                 // and not yet launched out of that state, so just as it won't
                 // receive broadcasts, we won't run it for backup.
-                backupManagerService.addBackupTrace("skipping - stopped");
+                mBackupManagerService.addBackupTrace("skipping - stopped");
                 BackupObserverUtils.sendBackupOnPackageResult(mObserver,
                         mCurrentPackage.packageName,
                         BackupManager.ERROR_BACKUP_NOT_ALLOWED);
-                executeNextState(BackupState.RUNNING_QUEUE);
-                return;
+                return Pair.create(BackupState.RUNNING_QUEUE, null);
             }
 
-            IBackupAgent agent = null;
             try {
-                backupManagerService.setWorkSource(
+                mBackupManagerService.setWorkSource(
                         new WorkSource(mCurrentPackage.applicationInfo.uid));
-                agent = backupManagerService.bindToAgentSynchronous(mCurrentPackage.applicationInfo,
-                        ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
-                backupManagerService.addBackupTrace("agent bound; a? = " + (agent != null));
+                IBackupAgent agent =
+                        mBackupManagerService.bindToAgentSynchronous(
+                                mCurrentPackage.applicationInfo,
+                                ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
+                mBackupManagerService.addBackupTrace("agent bound; a? = " + (agent != null));
                 if (agent != null) {
                     mAgentBinder = agent;
-                    mStatus = invokeAgentForBackup(request.packageName, agent);
-                    // at this point we'll either get a completion callback from the
-                    // agent, or a timeout message on the main handler.  either way, we're
-                    // done here as long as we're successful so far.
+                    Pair<Integer, RemoteResult> statusAndResult =
+                            invokeAgentForBackup(request.packageName, agent);
+                    mStatus = statusAndResult.first;
+                    agentResult = statusAndResult.second;
                 } else {
                     // Timeout waiting for the agent
                     mStatus = BackupTransport.AGENT_ERROR;
@@ -487,62 +630,59 @@
                 // Try for the next one.
                 Slog.d(TAG, "error in bind/backup", ex);
                 mStatus = BackupTransport.AGENT_ERROR;
-                backupManagerService.addBackupTrace("agent SE");
+                mBackupManagerService.addBackupTrace("agent SE");
             }
-        } catch (NameNotFoundException e) {
+        } catch (PackageManager.NameNotFoundException e) {
             Slog.d(TAG, "Package does not exist; skipping");
-            backupManagerService.addBackupTrace("no such package");
+            mBackupManagerService.addBackupTrace("no such package");
             mStatus = BackupTransport.AGENT_UNKNOWN;
         } finally {
-            backupManagerService.setWorkSource(null);
-
-            // If there was an agent error, no timeout/completion handling will occur.
-            // That means we need to direct to the next state ourselves.
-            if (mStatus != BackupTransport.TRANSPORT_OK) {
-                BackupState nextState = BackupState.RUNNING_QUEUE;
-                mAgentBinder = null;
-
-                // An agent-level failure means we reenqueue this one agent for
-                // a later retry, but otherwise proceed normally.
-                if (mStatus == BackupTransport.AGENT_ERROR) {
-                    if (MORE_DEBUG) {
-                        Slog.i(TAG, "Agent failure for " + request.packageName
-                                + " - restaging");
-                    }
-                    backupManagerService.dataChangedImpl(request.packageName);
-                    mStatus = BackupTransport.TRANSPORT_OK;
-                    if (mQueue.isEmpty()) nextState = BackupState.FINAL;
-                    BackupObserverUtils
-                            .sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
-                                    BackupManager.ERROR_AGENT_FAILURE);
-                } else if (mStatus == BackupTransport.AGENT_UNKNOWN) {
-                    // Failed lookup of the app, so we couldn't bring up an agent, but
-                    // we're otherwise fine.  Just drop it and go on to the next as usual.
-                    mStatus = BackupTransport.TRANSPORT_OK;
-                    BackupObserverUtils
-                            .sendBackupOnPackageResult(mObserver, request.packageName,
-                                    BackupManager.ERROR_PACKAGE_NOT_FOUND);
-                } else {
-                    // Transport-level failure means we reenqueue everything
-                    revertAndEndBackup();
-                    nextState = BackupState.FINAL;
-                }
-
-                executeNextState(nextState);
-            } else {
-                // success case
-                backupManagerService.addBackupTrace("expecting completion/timeout callback");
-            }
+            mBackupManagerService.setWorkSource(null);
         }
+
+        if (mStatus != BackupTransport.TRANSPORT_OK) {
+            BackupState nextState = BackupState.RUNNING_QUEUE;
+            mAgentBinder = null;
+
+            // An agent-level failure means we re-enqueue this one agent for
+            // a later retry, but otherwise proceed normally.
+            if (mStatus == BackupTransport.AGENT_ERROR) {
+                if (MORE_DEBUG) {
+                    Slog.i(TAG, "Agent failure for " + request.packageName + " - restaging");
+                }
+                mBackupManagerService.dataChangedImpl(request.packageName);
+                mStatus = BackupTransport.TRANSPORT_OK;
+                BackupObserverUtils
+                        .sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
+                                BackupManager.ERROR_AGENT_FAILURE);
+            } else if (mStatus == BackupTransport.AGENT_UNKNOWN) {
+                // Failed lookup of the app, so we couldn't bring up an agent, but
+                // we're otherwise fine.  Just drop it and go on to the next as usual.
+                mStatus = BackupTransport.TRANSPORT_OK;
+                BackupObserverUtils
+                        .sendBackupOnPackageResult(mObserver, request.packageName,
+                                BackupManager.ERROR_PACKAGE_NOT_FOUND);
+            } else {
+                // Transport-level failure means we re-enqueue everything
+                revertAndEndBackup();
+                nextState = BackupState.FINAL;
+            }
+
+            return Pair.create(nextState, null);
+        }
+
+        // Success: caller will figure out the state based on call result
+        mBackupManagerService.addBackupTrace("call made; result = " + agentResult);
+        return Pair.create(null, agentResult);
     }
 
     private void finalizeBackup() {
-        backupManagerService.addBackupTrace("finishing");
+        mBackupManagerService.addBackupTrace("finishing");
 
         // Mark packages that we didn't backup (because backup was cancelled, etc.) as needing
         // backup.
         for (BackupRequest req : mQueue) {
-            backupManagerService.dataChangedImpl(req.packageName);
+            mBackupManagerService.dataChangedImpl(req.packageName);
         }
 
         // Either backup was successful, in which case we of course do not need
@@ -557,65 +697,62 @@
         // done a backup, we can now record what the current backup dataset token
         // is.
         String callerLogString = "PBT.finalizeBackup()";
-        if ((backupManagerService.getCurrentToken() == 0) && (mStatus
+        if ((mBackupManagerService.getCurrentToken() == 0) && (mStatus
                 == BackupTransport.TRANSPORT_OK)) {
-            backupManagerService.addBackupTrace("success; recording token");
+            mBackupManagerService.addBackupTrace("success; recording token");
             try {
-                IBackupTransport transport =
-                        mTransportClient.connectOrThrow(callerLogString);
-                backupManagerService.setCurrentToken(transport.getCurrentRestoreSet());
-                backupManagerService.writeRestoreTokens();
+                IBackupTransport transport = mTransportClient.connectOrThrow(callerLogString);
+                mBackupManagerService.setCurrentToken(transport.getCurrentRestoreSet());
+                mBackupManagerService.writeRestoreTokens();
             } catch (Exception e) {
                 // nothing for it at this point, unfortunately, but this will be
                 // recorded the next time we fully succeed.
                 Slog.e(TAG, "Transport threw reporting restore set: " + e.getMessage());
-                backupManagerService.addBackupTrace("transport threw returning token");
+                mBackupManagerService.addBackupTrace("transport threw returning token");
             }
         }
 
         // Set up the next backup pass - at this point we can set mBackupRunning
-        // to false to allow another pass to fire, because we're done with the
-        // state machine sequence and the wakelock is refcounted.
-        synchronized (backupManagerService.getQueueLock()) {
-            backupManagerService.setBackupRunning(false);
+        // to false to allow another pass to fire
+        synchronized (mBackupManagerService.getQueueLock()) {
+            mBackupManagerService.setBackupRunning(false);
             if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
                 // Make sure we back up everything and perform the one-time init
                 if (MORE_DEBUG) {
                     Slog.d(TAG, "Server requires init; rerunning");
                 }
-                backupManagerService.addBackupTrace("init required; rerunning");
+                mBackupManagerService.addBackupTrace("init required; rerunning");
                 try {
-                    String name = backupManagerService.getTransportManager()
+                    String name = mBackupManagerService.getTransportManager()
                             .getTransportName(mTransportClient.getTransportComponent());
-                    backupManagerService.getPendingInits().add(name);
+                    mBackupManagerService.getPendingInits().add(name);
                 } catch (Exception e) {
                     Slog.w(TAG, "Failed to query transport name for init: " + e.getMessage());
                     // swallow it and proceed; we don't rely on this
                 }
                 clearMetadata();
-                backupManagerService.backupNow();
+                mBackupManagerService.backupNow();
             }
         }
 
-        backupManagerService.clearBackupTrace();
+        mBackupManagerService.clearBackupTrace();
 
         unregisterTask();
 
-        if (!mCancelAll && mStatus == BackupTransport.TRANSPORT_OK &&
+        if (!mCancelled && mStatus == BackupTransport.TRANSPORT_OK &&
                 mPendingFullBackups != null && !mPendingFullBackups.isEmpty()) {
             Slog.d(TAG, "Starting full backups for: " + mPendingFullBackups);
             // Acquiring wakelock for PerformFullTransportBackupTask before its start.
-            backupManagerService.getWakelock().acquire();
+            mBackupManagerService.getWakelock().acquire();
             // The full-backup task is now responsible for calling onFinish() on mListener, which
             // was the listener we passed it.
             (new Thread(mFullBackupTask, "full-transport-requested")).start();
-        } else if (mCancelAll) {
+        } else if (mCancelled) {
             mListener.onFinished(callerLogString);
             if (mFullBackupTask != null) {
                 mFullBackupTask.unregisterTask();
             }
-            BackupObserverUtils.sendBackupFinished(mObserver,
-                    BackupManager.ERROR_BACKUP_CANCELLED);
+            BackupObserverUtils.sendBackupFinished(mObserver, BackupManager.ERROR_BACKUP_CANCELLED);
         } else {
             mListener.onFinished(callerLogString);
             mFullBackupTask.unregisterTask();
@@ -623,8 +760,7 @@
                 case BackupTransport.TRANSPORT_OK:
                 case BackupTransport.TRANSPORT_QUOTA_EXCEEDED:
                 case BackupTransport.TRANSPORT_PACKAGE_REJECTED:
-                    BackupObserverUtils.sendBackupFinished(mObserver,
-                            BackupManager.SUCCESS);
+                    BackupObserverUtils.sendBackupFinished(mObserver, BackupManager.SUCCESS);
                     break;
                 case BackupTransport.TRANSPORT_NOT_INITIALIZED:
                     BackupObserverUtils.sendBackupFinished(mObserver,
@@ -637,10 +773,9 @@
                     break;
             }
         }
-        mFinished = true;
         Slog.i(TAG, "K/V backup pass finished.");
         // Only once we're entirely finished do we release the wakelock for k/v backup.
-        backupManagerService.getWakelock().release();
+        mBackupManagerService.getWakelock().release();
     }
 
     // Remove the PM metadata state. This will generate an init on the next pass.
@@ -649,27 +784,34 @@
         if (pmState.exists()) pmState.delete();
     }
 
-    // Invoke an agent's doBackup() and start a timeout message spinning on the main
-    // handler in case it doesn't get back to us.
-    private int invokeAgentForBackup(String packageName, IBackupAgent agent) {
+    /**
+     * Returns a {@link Pair}. The first of the pair contains the status. In case the status is
+     * {@link BackupTransport#TRANSPORT_OK}, the second of the pair contains the agent result,
+     * otherwise {@code null}.
+     */
+    private Pair<Integer, RemoteResult> invokeAgentForBackup(
+            String packageName, IBackupAgent agent) {
         if (DEBUG) {
             Slog.d(TAG, "invokeAgentForBackup on " + packageName);
         }
-        backupManagerService.addBackupTrace("invoking " + packageName);
+        mBackupManagerService.addBackupTrace("invoking " + packageName);
 
-        File blankStateName = new File(mStateDir, BLANK_STATE_FILE_NAME);
-        mSavedStateName = new File(mStateDir, packageName);
-        mBackupDataName =
-                new File(backupManagerService.getDataDir(), packageName + STAGING_FILE_SUFFIX);
-        mNewStateName = new File(mStateDir, packageName + NEW_STATE_FILE_SUFFIX);
-        if (MORE_DEBUG) Slog.d(TAG, "data file: " + mBackupDataName);
+        File blankStateFile = new File(mStateDir, BLANK_STATE_FILE_NAME);
+        mSavedStateFile = new File(mStateDir, packageName);
+        mBackupDataFile =
+                new File(mBackupManagerService.getDataDir(), packageName + STAGING_FILE_SUFFIX);
+        mNewStateFile = new File(mStateDir, packageName + NEW_STATE_FILE_SUFFIX);
+        if (MORE_DEBUG) {
+            Slog.d(TAG, "data file: " + mBackupDataFile);
+        }
+
 
         mSavedState = null;
         mBackupData = null;
         mNewState = null;
 
         boolean callingAgent = false;
-        mEphemeralOpToken = backupManagerService.generateRandomIntegerToken();
+        final RemoteResult agentResult;
         try {
             // Look up the package info & signatures.  This is first so that if it
             // throws an exception, there's no file setup yet that would need to
@@ -681,24 +823,21 @@
                 mCurrentPackage.packageName = packageName;
             }
 
-            // In a full backup, we pass a null ParcelFileDescriptor as
-            // the saved-state "file". For key/value backups we pass the old state if
-            // an incremental backup is required, and a blank state otherwise.
             mSavedState = ParcelFileDescriptor.open(
-                    mNonIncremental ? blankStateName : mSavedStateName,
+                    (mNonIncremental) ? blankStateFile : mSavedStateFile,
                     ParcelFileDescriptor.MODE_READ_ONLY |
                             ParcelFileDescriptor.MODE_CREATE);  // Make an empty file if necessary
 
-            mBackupData = ParcelFileDescriptor.open(mBackupDataName,
+            mBackupData = ParcelFileDescriptor.open(mBackupDataFile,
                     ParcelFileDescriptor.MODE_READ_WRITE |
                             ParcelFileDescriptor.MODE_CREATE |
                             ParcelFileDescriptor.MODE_TRUNCATE);
 
-            if (!SELinux.restorecon(mBackupDataName)) {
-                Slog.e(TAG, "SELinux restorecon failed on " + mBackupDataName);
+            if (!SELinux.restorecon(mBackupDataFile)) {
+                Slog.e(TAG, "SELinux restorecon failed on " + mBackupDataFile);
             }
 
-            mNewState = ParcelFileDescriptor.open(mNewStateName,
+            mNewState = ParcelFileDescriptor.open(mNewStateFile,
                     ParcelFileDescriptor.MODE_READ_WRITE |
                             ParcelFileDescriptor.MODE_CREATE |
                             ParcelFileDescriptor.MODE_TRUNCATE);
@@ -710,36 +849,36 @@
             callingAgent = true;
 
             // Initiate the target's backup pass
-            backupManagerService.addBackupTrace("setting timeout");
             long kvBackupAgentTimeoutMillis =
                     mAgentTimeoutParameters.getKvBackupAgentTimeoutMillis();
-            backupManagerService.prepareOperationTimeout(
-                    mEphemeralOpToken, kvBackupAgentTimeoutMillis, this, OP_TYPE_BACKUP_WAIT);
-            backupManagerService.addBackupTrace("calling agent doBackup()");
+            mBackupManagerService.addBackupTrace("calling agent doBackup()");
 
-            agent.doBackup(
-                    mSavedState, mBackupData, mNewState, quota, mEphemeralOpToken,
-                    backupManagerService.getBackupManagerBinder(), transport.getTransportFlags());
+            agentResult =
+                    remoteCall(
+                            callback ->
+                                    agent.doBackup(
+                                            mSavedState,
+                                            mBackupData,
+                                            mNewState,
+                                            quota,
+                                            callback,
+                                            transport.getTransportFlags()),
+                            kvBackupAgentTimeoutMillis);
         } catch (Exception e) {
             Slog.e(TAG, "Error invoking for backup on " + packageName + ". " + e);
-            backupManagerService.addBackupTrace("exception: " + e);
-            EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName,
-                    e.toString());
+            mBackupManagerService.addBackupTrace("exception: " + e);
+            EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName, e.toString());
             errorCleanup();
-            return callingAgent ? BackupTransport.AGENT_ERROR
-                    : BackupTransport.TRANSPORT_ERROR;
+            int status =
+                    callingAgent ? BackupTransport.AGENT_ERROR : BackupTransport.TRANSPORT_ERROR;
+            return Pair.create(status, null);
         } finally {
             if (mNonIncremental) {
-                blankStateName.delete();
+                blankStateFile.delete();
             }
         }
 
-        // At this point the agent is off and running.  The next thing to happen will
-        // either be a callback from the agent, at which point we'll process its data
-        // for transport, or a timeout.  Either way the next phase will happen in
-        // response to the TimeoutHandler interface callbacks.
-        backupManagerService.addBackupTrace("invoke success");
-        return BackupTransport.TRANSPORT_OK;
+        return Pair.create(BackupTransport.TRANSPORT_OK, agentResult);
     }
 
     private void failAgent(IBackupAgent agent, String message) {
@@ -829,327 +968,319 @@
         }
     }
 
-    @Override
-    @GuardedBy("mCancelLock")
-    public void operationComplete(long unusedResult) {
-        backupManagerService.removeOperation(mEphemeralOpToken);
-        synchronized (mCancelLock) {
-            // The agent reported back to us!
-            if (mFinished) {
-                Slog.d(TAG, "operationComplete received after task finished.");
-                return;
-            }
+    private BackupState handleAgentResult(long unusedResult) {
+        Preconditions.checkState(mBackupData != null);
 
-            if (mBackupData == null) {
-                // This callback was racing with our timeout, so we've cleaned up the
-                // agent state already and are on to the next thing.  We have nothing
-                // further to do here: agent state having been cleared means that we've
-                // initiated the appropriate next operation.
-                final String pkg = (mCurrentPackage != null)
-                        ? mCurrentPackage.packageName : "[none]";
-                if (MORE_DEBUG) {
-                    Slog.i(TAG, "Callback after agent teardown: " + pkg);
-                }
-                backupManagerService.addBackupTrace("late opComplete; curPkg = " + pkg);
-                return;
-            }
-
-            final String pkgName = mCurrentPackage.packageName;
-            final long filepos = mBackupDataName.length();
-            FileDescriptor fd = mBackupData.getFileDescriptor();
-            try {
-                // If it's a 3rd party app, see whether they wrote any protected keys
-                // and complain mightily if they are attempting shenanigans.
-                if (mCurrentPackage.applicationInfo != null &&
-                        (mCurrentPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
-                                == 0) {
-                    ParcelFileDescriptor readFd = ParcelFileDescriptor.open(mBackupDataName,
-                            ParcelFileDescriptor.MODE_READ_ONLY);
-                    BackupDataInput in = new BackupDataInput(readFd.getFileDescriptor());
-                    try {
-                        while (in.readNextHeader()) {
-                            final String key = in.getKey();
-                            if (key != null && key.charAt(0) >= 0xff00) {
-                                // Not okay: crash them and bail.
-                                failAgent(mAgentBinder, "Illegal backup key: " + key);
-                                backupManagerService
-                                        .addBackupTrace("illegal key " + key + " from " + pkgName);
-                                EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
-                                        "bad key");
-                                mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
-                                        BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY,
-                                        mCurrentPackage,
-                                        BackupManagerMonitor
-                                                .LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                        BackupManagerMonitorUtils.putMonitoringExtra(null,
-                                                BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY,
-                                                key));
-                                backupManagerService.getBackupHandler().removeMessages(
-                                        MSG_BACKUP_OPERATION_TIMEOUT);
-                                BackupObserverUtils
-                                        .sendBackupOnPackageResult(mObserver, pkgName,
-                                                BackupManager.ERROR_AGENT_FAILURE);
-                                errorCleanup();
-                                if (MORE_DEBUG) {
-                                    Slog.i(TAG, "Agent failure for " + pkgName
-                                            + " with illegal key: " + key + "; dropped");
-                                }
-                                executeNextState(mQueue.isEmpty() ? BackupState.FINAL
-                                        : BackupState.RUNNING_QUEUE);
-                                return;
+        final String pkgName = mCurrentPackage.packageName;
+        final long filepos = mBackupDataFile.length();
+        FileDescriptor fd = mBackupData.getFileDescriptor();
+        try {
+            // If it's a 3rd party app, see whether they wrote any protected keys
+            // and complain mightily if they are attempting shenanigans.
+            if (mCurrentPackage.applicationInfo != null &&
+                    (mCurrentPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
+                            == 0) {
+                ParcelFileDescriptor readFd = ParcelFileDescriptor.open(mBackupDataFile,
+                        ParcelFileDescriptor.MODE_READ_ONLY);
+                BackupDataInput in = new BackupDataInput(readFd.getFileDescriptor());
+                try {
+                    while (in.readNextHeader()) {
+                        final String key = in.getKey();
+                        if (key != null && key.charAt(0) >= 0xff00) {
+                            // Not okay: crash them and bail.
+                            failAgent(mAgentBinder, "Illegal backup key: " + key);
+                            mBackupManagerService
+                                    .addBackupTrace("illegal key " + key + " from " + pkgName);
+                            EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
+                                    "bad key");
+                            mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
+                                    BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY,
+                                    mCurrentPackage,
+                                    BackupManagerMonitor
+                                            .LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                    BackupManagerMonitorUtils.putMonitoringExtra(null,
+                                            BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY,
+                                            key));
+                            BackupObserverUtils
+                                    .sendBackupOnPackageResult(mObserver, pkgName,
+                                            BackupManager.ERROR_AGENT_FAILURE);
+                            errorCleanup();
+                            if (MORE_DEBUG) {
+                                Slog.i(TAG, "Agent failure for " + pkgName
+                                        + " with illegal key: " + key + "; dropped");
                             }
-                            in.skipEntityData();
+
+                            return BackupState.RUNNING_QUEUE;
                         }
-                    } finally {
-                        if (readFd != null) {
-                            readFd.close();
-                        }
+                        in.skipEntityData();
+                    }
+                } finally {
+                    if (readFd != null) {
+                        readFd.close();
                     }
                 }
-
-                // Piggyback the widget state payload, if any
-                writeWidgetPayloadIfAppropriate(fd, pkgName);
-            } catch (IOException e) {
-                // Hard disk error; recovery/failure policy TBD.  For now roll back,
-                // but we may want to consider this a transport-level failure (i.e.
-                // we're in such a bad state that we can't contemplate doing backup
-                // operations any more during this pass).
-                Slog.w(TAG, "Unable to save widget state for " + pkgName);
-                try {
-                    Os.ftruncate(fd, filepos);
-                } catch (ErrnoException ee) {
-                    Slog.w(TAG, "Unable to roll back!");
-                }
             }
 
-            // Spin the data off to the transport and proceed with the next stage.
-            if (MORE_DEBUG) {
-                Slog.v(TAG, "operationComplete(): sending data to transport for "
-                        + pkgName);
-            }
-            backupManagerService.getBackupHandler().removeMessages(MSG_BACKUP_OPERATION_TIMEOUT);
-            clearAgentState();
-            backupManagerService.addBackupTrace("operation complete");
-
-            IBackupTransport transport = mTransportClient.connect("PBT.operationComplete()");
-            ParcelFileDescriptor backupData = null;
-            mStatus = BackupTransport.TRANSPORT_OK;
-            long size = 0;
+            // Piggyback the widget state payload, if any
+            writeWidgetPayloadIfAppropriate(fd, pkgName);
+        } catch (IOException e) {
+            // Hard disk error; recovery/failure policy TBD.  For now roll back,
+            // but we may want to consider this a transport-level failure (i.e.
+            // we're in such a bad state that we can't contemplate doing backup
+            // operations any more during this pass).
+            Slog.w(TAG, "Unable read backup data or to save widget state for " + pkgName);
             try {
-                TransportUtils.checkTransportNotNull(transport);
-                size = mBackupDataName.length();
-                if (size > 0) {
-                    boolean isNonIncremental = mSavedStateName.length() == 0;
-                    if (mStatus == BackupTransport.TRANSPORT_OK) {
-                        backupData = ParcelFileDescriptor.open(mBackupDataName,
-                                ParcelFileDescriptor.MODE_READ_ONLY);
-                        backupManagerService.addBackupTrace("sending data to transport");
+                Os.ftruncate(fd, filepos);
+            } catch (ErrnoException ee) {
+                Slog.w(TAG, "Unable to roll back!");
+            }
+        }
 
-                        int userInitiatedFlag =
-                                mUserInitiated ? BackupTransport.FLAG_USER_INITIATED : 0;
-                        int incrementalFlag =
-                                isNonIncremental
+        clearAgentState();
+        mBackupManagerService.addBackupTrace("operation complete");
+
+        ParcelFileDescriptor backupData = null;
+        mStatus = BackupTransport.TRANSPORT_OK;
+        long size = 0;
+        try {
+            IBackupTransport transport = mTransportClient.connectOrThrow("PBT.handleAgentResult()");
+            size = mBackupDataFile.length();
+            if (size > 0) {
+                if (MORE_DEBUG) {
+                    Slog.v(TAG, "Sending non-empty data to transport for " + pkgName);
+                }
+                boolean isNonIncremental = mSavedStateFile.length() == 0;
+                if (mStatus == BackupTransport.TRANSPORT_OK) {
+                    backupData = ParcelFileDescriptor.open(mBackupDataFile,
+                            ParcelFileDescriptor.MODE_READ_ONLY);
+                    mBackupManagerService.addBackupTrace("sending data to transport");
+
+                    int userInitiatedFlag =
+                            mUserInitiated ? BackupTransport.FLAG_USER_INITIATED : 0;
+                    int incrementalFlag =
+                            isNonIncremental
                                     ? BackupTransport.FLAG_NON_INCREMENTAL
                                     : BackupTransport.FLAG_INCREMENTAL;
-                        int flags = userInitiatedFlag | incrementalFlag;
+                    int flags = userInitiatedFlag | incrementalFlag;
 
-                        mStatus = transport.performBackup(mCurrentPackage, backupData, flags);
-                    }
+                    mStatus = transport.performBackup(mCurrentPackage, backupData, flags);
+                }
 
-                    if (isNonIncremental
+                if (isNonIncremental
                         && mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
-                        // TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED is only valid if the backup was
-                        // incremental, as if the backup is non-incremental there is no state to
-                        // clear. This avoids us ending up in a retry loop if the transport always
-                        // returns this code.
-                        Slog.w(TAG,
-                                "Transport requested non-incremental but already the case, error");
-                        backupManagerService.addBackupTrace(
-                                "Transport requested non-incremental but already the case, error");
-                        mStatus = BackupTransport.TRANSPORT_ERROR;
-                    }
-
-                    // TODO - We call finishBackup() for each application backed up, because
-                    // we need to know now whether it succeeded or failed.  Instead, we should
-                    // hold off on finishBackup() until the end, which implies holding off on
-                    // renaming *all* the output state files (see below) until that happens.
-
-                    backupManagerService.addBackupTrace("data delivered: " + mStatus);
-                    if (mStatus == BackupTransport.TRANSPORT_OK) {
-                        backupManagerService.addBackupTrace("finishing op on transport");
-                        mStatus = transport.finishBackup();
-                        backupManagerService.addBackupTrace("finished: " + mStatus);
-                    } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
-                        backupManagerService.addBackupTrace("transport rejected package");
-                    }
-                } else {
-                    if (MORE_DEBUG) {
-                        Slog.i(TAG, "no backup data written; not calling transport");
-                    }
-                    backupManagerService.addBackupTrace("no data to send");
-                    mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
-                            BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
-                            mCurrentPackage,
-                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                            null);
+                    // TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED is only valid if the backup was
+                    // incremental, as if the backup is non-incremental there is no state to
+                    // clear. This avoids us ending up in a retry loop if the transport always
+                    // returns this code.
+                    Slog.w(TAG, "Transport requested non-incremental but already the case, error");
+                    mBackupManagerService.addBackupTrace(
+                            "Transport requested non-incremental but already the case, error");
+                    mStatus = BackupTransport.TRANSPORT_ERROR;
                 }
 
+                mBackupManagerService.addBackupTrace("data delivered: " + mStatus);
                 if (mStatus == BackupTransport.TRANSPORT_OK) {
-                    // After successful transport, delete the now-stale data
-                    // and juggle the files so that next time we supply the agent
-                    // with the new state file it just created.
-                    mBackupDataName.delete();
-                    mNewStateName.renameTo(mSavedStateName);
-                    BackupObserverUtils
-                            .sendBackupOnPackageResult(mObserver, pkgName, BackupManager.SUCCESS);
-                    EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, pkgName, size);
-                    backupManagerService.logBackupComplete(pkgName);
+                    mBackupManagerService.addBackupTrace("finishing op on transport");
+                    mStatus = transport.finishBackup();
+                    mBackupManagerService.addBackupTrace("finished: " + mStatus);
                 } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
-                    // The transport has rejected backup of this specific package.  Roll it
-                    // back but proceed with running the rest of the queue.
-                    mBackupDataName.delete();
-                    mNewStateName.delete();
-                    BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
-                            BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
-                    EventLogTags.writeBackupAgentFailure(pkgName, "Transport rejected");
-                } else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
-                    BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
-                            BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
-                    EventLog.writeEvent(EventLogTags.BACKUP_QUOTA_EXCEEDED, pkgName);
-
-                } else if (mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
-                    Slog.i(TAG, "Transport lost data, retrying package");
-                    backupManagerService.addBackupTrace(
-                            "Transport lost data, retrying package:" + pkgName);
-                    BackupManagerMonitorUtils.monitorEvent(
-                            mMonitor,
-                            BackupManagerMonitor
-                                    .LOG_EVENT_ID_TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED,
-                            mCurrentPackage,
-                            BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
-                            /*extras=*/ null);
-
-                    mBackupDataName.delete();
-                    mSavedStateName.delete();
-                    mNewStateName.delete();
-
-                    // Immediately retry the package by adding it back to the front of the queue.
-                    // We cannot add @pm@ to the queue because we back it up separately at the start
-                    // of the backup pass in state BACKUP_PM. Instead we retry this state (see
-                    // below).
-                    if (!PACKAGE_MANAGER_SENTINEL.equals(pkgName)) {
-                        mQueue.add(0, new BackupRequest(pkgName));
-                    }
-
-                } else {
-                    // Actual transport-level failure to communicate the data to the backend
-                    BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
-                            BackupManager.ERROR_TRANSPORT_ABORTED);
-                    EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
+                    mBackupManagerService.addBackupTrace("transport rejected package");
                 }
-            } catch (Exception e) {
-                BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
-                        BackupManager.ERROR_TRANSPORT_ABORTED);
-                Slog.e(TAG, "Transport error backing up " + pkgName, e);
-                EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
-                mStatus = BackupTransport.TRANSPORT_ERROR;
-            } finally {
-                try {
-                    if (backupData != null) backupData.close();
-                } catch (IOException e) {
+            } else {
+                if (MORE_DEBUG) {
+                    Slog.i(TAG, "No backup data written; not calling transport");
                 }
+                mBackupManagerService.addBackupTrace("no data to send");
+                mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
+                        mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                        null);
             }
 
-            final BackupState nextState;
-            if (mStatus == BackupTransport.TRANSPORT_OK
-                    || mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
-                // Success or single-package rejection.  Proceed with the next app if any,
-                // otherwise we're done.
-                nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE;
+            if (mStatus == BackupTransport.TRANSPORT_OK) {
+                // After successful transport, delete the now-stale data
+                // and juggle the files so that next time we supply the agent
+                // with the new state file it just created.
+                mBackupDataFile.delete();
+                mNewStateFile.renameTo(mSavedStateFile);
+                BackupObserverUtils.sendBackupOnPackageResult(
+                        mObserver, pkgName, BackupManager.SUCCESS);
+                EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, pkgName, size);
+                mBackupManagerService.logBackupComplete(pkgName);
+            } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
+                // The transport has rejected backup of this specific package.  Roll it
+                // back but proceed with running the rest of the queue.
+                mBackupDataFile.delete();
+                mNewStateFile.delete();
+                BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
+                        BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
+                EventLogTags.writeBackupAgentFailure(pkgName, "Transport rejected");
+            } else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
+                BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
+                        BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
+                EventLog.writeEvent(EventLogTags.BACKUP_QUOTA_EXCEEDED, pkgName);
 
             } else if (mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
-                // We want to immediately retry the current package.
-                if (PACKAGE_MANAGER_SENTINEL.equals(pkgName)) {
-                    nextState = BackupState.BACKUP_PM;
-                } else {
-                    // This is an ordinary package so we will have added it back into the queue
-                    // above. Thus, we proceed processing the queue.
-                    nextState = BackupState.RUNNING_QUEUE;
+                Slog.i(TAG, "Transport lost data, retrying package");
+                mBackupManagerService.addBackupTrace(
+                        "Transport lost data, retrying package:" + pkgName);
+                BackupManagerMonitorUtils.monitorEvent(
+                        mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED,
+                        mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT,
+                        /*extras=*/ null);
+
+                mBackupDataFile.delete();
+                mSavedStateFile.delete();
+                mNewStateFile.delete();
+
+                // Immediately retry the package by adding it back to the front of the queue.
+                // We cannot add @pm@ to the queue because we back it up separately at the start
+                // of the backup pass in state BACKUP_PM. Instead we retry this state (see
+                // below).
+                if (!PACKAGE_MANAGER_SENTINEL.equals(pkgName)) {
+                    mQueue.add(0, new BackupRequest(pkgName));
                 }
 
-            } else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
-                if (MORE_DEBUG) {
-                    Slog.d(TAG, "Package " + mCurrentPackage.packageName +
-                            " hit quota limit on k/v backup");
-                }
-                if (mAgentBinder != null) {
-                    try {
-                        TransportUtils.checkTransportNotNull(transport);
-                        long quota = transport.getBackupQuota(mCurrentPackage.packageName, false);
-                        mAgentBinder.doQuotaExceeded(size, quota);
-                    } catch (Exception e) {
-                        Slog.e(TAG, "Unable to notify about quota exceeded: " + e.getMessage());
-                    }
-                }
-                nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE;
             } else {
-                // Any other error here indicates a transport-level failure.  That means
-                // we need to halt everything and reschedule everything for next time.
-                revertAndEndBackup();
-                nextState = BackupState.FINAL;
+                // Actual transport-level failure to communicate the data to the backend
+                BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
+                        BackupManager.ERROR_TRANSPORT_ABORTED);
+                EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
+            }
+        } catch (Exception e) {
+            BackupObserverUtils.sendBackupOnPackageResult(mObserver, pkgName,
+                    BackupManager.ERROR_TRANSPORT_ABORTED);
+            Slog.e(TAG, "Transport error backing up " + pkgName, e);
+            EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
+            mStatus = BackupTransport.TRANSPORT_ERROR;
+        } finally {
+            try {
+                if (backupData != null) {
+                    backupData.close();
+                }
+            } catch (IOException e) {
+                Slog.w(TAG, "Error closing backup data fd");
+            }
+        }
+
+        final BackupState nextState;
+        if (mStatus == BackupTransport.TRANSPORT_OK
+                || mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
+            // Success or single-package rejection.  Proceed with the next app if any,
+            // otherwise we're done.
+            nextState = BackupState.RUNNING_QUEUE;
+
+        } else if (mStatus == BackupTransport.TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED) {
+            // We want to immediately retry the current package.
+            if (PACKAGE_MANAGER_SENTINEL.equals(pkgName)) {
+                nextState = BackupState.BACKUP_PM;
+            } else {
+                // This is an ordinary package so we will have added it back into the queue
+                // above. Thus, we proceed processing the queue.
+                nextState = BackupState.RUNNING_QUEUE;
             }
 
-            executeNextState(nextState);
+        } else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
+            if (MORE_DEBUG) {
+                Slog.d(TAG, "Package " + mCurrentPackage.packageName +
+                        " hit quota limit on k/v backup");
+            }
+            if (mAgentBinder != null) {
+                try {
+                    IBackupTransport transport =
+                            mTransportClient.connectOrThrow("PBT.handleAgentResult()");
+                    long quota = transport.getBackupQuota(mCurrentPackage.packageName, false);
+                    mAgentBinder.doQuotaExceeded(size, quota);
+                } catch (Exception e) {
+                    Slog.e(TAG, "Unable to notify about quota exceeded: " + e.getMessage());
+                }
+            }
+            nextState = BackupState.RUNNING_QUEUE;
+        } else {
+            // Any other error here indicates a transport-level failure.  That means
+            // we need to halt everything and reschedule everything for next time.
+            revertAndEndBackup();
+            nextState = BackupState.FINAL;
         }
+
+        return nextState;
     }
 
-
+    /**
+     * Cancels this task. After this method returns there will be no more calls to the transport.
+     *
+     * <p>If this method is executed while an agent is performing a backup, we will stop waiting for
+     * it, disregard its backup data and finalize the task. However, if this method is executed in
+     * between agent calls, the backup data of the last called agent will be sent to
+     * the transport and we will not consider the next agent (nor the rest of the queue), proceeding
+     * to finalize the backup.
+     *
+     * @param cancelAll MUST be {@code true}. Will be removed.
+     */
     @Override
-    @GuardedBy("mCancelLock")
     public void handleCancel(boolean cancelAll) {
-        backupManagerService.removeOperation(mEphemeralOpToken);
-        synchronized (mCancelLock) {
-            if (mFinished) {
-                // We have already cancelled this operation.
-                if (MORE_DEBUG) {
-                    Slog.d(TAG, "Ignoring stale cancel. cancelAll=" + cancelAll);
-                }
-                return;
-            }
-            mCancelAll = cancelAll;
-            final String logPackageName = (mCurrentPackage != null)
-                    ? mCurrentPackage.packageName
-                    : "no_package_yet";
-            Slog.i(TAG, "Cancel backing up " + logPackageName);
-            EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, logPackageName);
-            backupManagerService.addBackupTrace(
-                    "cancel of " + logPackageName + ", cancelAll=" + cancelAll);
-            mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
-                    BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
-                    mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
-                    BackupManagerMonitorUtils.putMonitoringExtra(null,
-                            BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL,
-                            mCancelAll));
-            errorCleanup();
-            if (!cancelAll) {
-                // The current agent either timed out or was cancelled running doBackup().
-                // Restage it for the next time we run a backup pass.
-                // !!! TODO: keep track of failure counts per agent, and blacklist those which
-                // fail repeatedly (i.e. have proved themselves to be buggy).
-                executeNextState(
-                        mQueue.isEmpty() ? BackupState.FINAL : BackupState.RUNNING_QUEUE);
-                backupManagerService.dataChangedImpl(mCurrentPackage.packageName);
-            } else {
-                finalizeBackup();
-            }
+        Preconditions.checkArgument(cancelAll, "Can't partially cancel a key-value backup task");
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "Cancel received");
         }
+        mCancelled = true;
+        RemoteCall pendingCall = mPendingCall;
+        if (pendingCall != null) {
+            pendingCall.cancel();
+        }
+        mCancelAcknowledged.block();
+    }
+
+    private void handleAgentTimeout() {
+        String packageName = getPackageNameForLog();
+        Slog.i(TAG, "Agent " + packageName + " timed out");
+        EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
+        mBackupManagerService.addBackupTrace("timeout of " + packageName);
+        mMonitor =
+                BackupManagerMonitorUtils.monitorEvent(
+                        mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
+                        mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
+                        BackupManagerMonitorUtils.putMonitoringExtra(
+                                null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, false));
+        errorCleanup();
+    }
+
+    private void handleAgentCancelled() {
+        String packageName = getPackageNameForLog();
+        Slog.i(TAG, "Cancel backing up " + packageName);
+        EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
+        mBackupManagerService.addBackupTrace("cancel of " + packageName);
+        errorCleanup();
+    }
+
+    private void finalizeCancelledBackup() {
+        mMonitor =
+                BackupManagerMonitorUtils.monitorEvent(
+                        mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
+                        mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
+                        BackupManagerMonitorUtils.putMonitoringExtra(
+                                null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, true));
+        finalizeBackup();
+        // finalizeBackup() may call the transport, so we only acknowledge the cancellation here.
+        mCancelAcknowledged.open();
+    }
+
+    private String getPackageNameForLog() {
+        return (mCurrentPackage != null) ? mCurrentPackage.packageName : "no_package_yet";
     }
 
     private void revertAndEndBackup() {
         if (MORE_DEBUG) {
             Slog.i(TAG, "Reverting backup queue - restaging everything");
         }
-        backupManagerService.addBackupTrace("transport error; reverting");
+        mBackupManagerService.addBackupTrace("transport error; reverting");
 
         // We want to reset the backup schedule based on whatever the transport suggests
         // by way of retry/backoff time.
@@ -1162,59 +1293,65 @@
             Slog.w(TAG, "Unable to contact transport for recommended backoff: " + e.getMessage());
             delay = 0;  // use the scheduler's default
         }
-        KeyValueBackupJob.schedule(backupManagerService.getContext(), delay,
-                backupManagerService.getConstants());
+        KeyValueBackupJob.schedule(mBackupManagerService.getContext(), delay,
+                mBackupManagerService.getConstants());
 
         for (BackupRequest request : mOriginalQueue) {
-            backupManagerService.dataChangedImpl(request.packageName);
+            mBackupManagerService.dataChangedImpl(request.packageName);
         }
-
     }
 
     private void errorCleanup() {
-        mBackupDataName.delete();
-        mNewStateName.delete();
+        mBackupDataFile.delete();
+        mNewStateFile.delete();
         clearAgentState();
     }
 
     // Cleanup common to both success and failure cases
     private void clearAgentState() {
         try {
-            if (mSavedState != null) mSavedState.close();
+            if (mSavedState != null) {
+                mSavedState.close();
+            }
         } catch (IOException e) {
+            Slog.w(TAG, "Error closing old state fd");
         }
         try {
-            if (mBackupData != null) mBackupData.close();
+            if (mBackupData != null) {
+                mBackupData.close();
+            }
         } catch (IOException e) {
+            Slog.w(TAG, "Error closing backup data fd");
         }
         try {
-            if (mNewState != null) mNewState.close();
+            if (mNewState != null) {
+                mNewState.close();
+            }
         } catch (IOException e) {
+            Slog.w(TAG, "Error closing new state fd");
         }
-        synchronized (backupManagerService.getCurrentOpLock()) {
+        synchronized (mBackupManagerService.getCurrentOpLock()) {
             // Current-operation callback handling requires the validity of these various
             // bits of internal state as an invariant of the operation still being live.
             // This means we make sure to clear all of the state in unison inside the lock.
-            backupManagerService.getCurrentOperations().remove(mEphemeralOpToken);
             mSavedState = mBackupData = mNewState = null;
         }
 
-        // If this was a pseudopackage there's no associated Activity Manager state
+        // If this was a pseudo-package there's no associated Activity Manager state
         if (mCurrentPackage.applicationInfo != null) {
-            backupManagerService.addBackupTrace("unbinding " + mCurrentPackage.packageName);
-            backupManagerService.unbindAgent(mCurrentPackage.applicationInfo);
+            mBackupManagerService.addBackupTrace("unbinding " + mCurrentPackage.packageName);
+            mBackupManagerService.unbindAgent(mCurrentPackage.applicationInfo);
         }
     }
 
-    private void executeNextState(BackupState nextState) {
+    private RemoteResult remoteCall(RemoteCallable<IBackupCallback> remoteCallable, long timeoutMs)
+            throws RemoteException {
+        mPendingCall = new RemoteCall(mCancelled, remoteCallable, timeoutMs);
+        RemoteResult result = mPendingCall.call();
         if (MORE_DEBUG) {
-            Slog.i(TAG, " => executing next step on "
-                    + this + " nextState=" + nextState);
+            Slog.v(TAG, "Agent call returned " + result);
         }
-        backupManagerService.addBackupTrace("executeNextState => " + nextState);
-        mCurrentState = nextState;
-        Message msg = backupManagerService.getBackupHandler().obtainMessage(
-                MSG_BACKUP_RESTORE_STEP, this);
-        backupManagerService.getBackupHandler().sendMessage(msg);
+        mPendingCall = null;
+        return result;
     }
 }
diff --git a/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java b/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java
new file mode 100644
index 0000000..1445cc3
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java
@@ -0,0 +1,39 @@
+/*
+ * 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.backup.remote;
+
+import android.app.backup.IBackupCallback;
+import android.os.RemoteException;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * An implementation of {@link IBackupCallback} that completes the {@link CompletableFuture}
+ * provided in the constructor with a successful {@link RemoteResult}.
+ */
+public class FutureBackupCallback extends IBackupCallback.Stub {
+    private final CompletableFuture<RemoteResult> mFuture;
+
+    FutureBackupCallback(CompletableFuture<RemoteResult> future) {
+        mFuture = future;
+    }
+
+    @Override
+    public void operationComplete(long result) throws RemoteException {
+        mFuture.complete(RemoteResult.successful(result));
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/remote/RemoteCall.java b/services/backup/java/com/android/server/backup/remote/RemoteCall.java
new file mode 100644
index 0000000..ac84811
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/RemoteCall.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.server.backup.remote;
+
+import android.annotation.WorkerThread;
+import android.app.backup.IBackupCallback;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * A wrapper that encapsulates an outbound call from the system process, converting an asynchronous
+ * operation into a synchronous operation with time-out and cancellation built-in. This was built to
+ * be able to call one-way binder methods that accept a {@link IBackupCallback} as a callback and
+ * handle the result inline.
+ *
+ * <p>Create one {@link RemoteCall} object providing the actual call in the form of a {@link
+ * RemoteCallable} that accepts a {@link IBackupCallback}. Perform the call by calling {@link
+ * #call()}, at which point {@link RemoteCall} will execute the callable providing an implementation
+ * of the callback that communicates the result back to this object. Even if the call returns
+ * straight away (which is the case for one-way methods) the method will only return when either the
+ * callback is called, time-out happens, or someone calls {@link #cancel()}.
+ *
+ * <p>This class was designed to have the method {@link #call()} called only once.
+ */
+// TODO: Kick-off callable in dedicated thread (because of local calls, which are synchronous)
+public class RemoteCall {
+    private final RemoteCallable<IBackupCallback> mCallable;
+    private final CompletableFuture<RemoteResult> mFuture;
+    private final long mTimeoutMs;
+
+    /**
+     * Creates a new {@link RemoteCall} object for a given callable.
+     *
+     * @param callable A function that signals its completion by calling {@link
+     *     IBackupCallback#operationComplete(long)} on the object provided as a parameter.
+     * @param timeoutMs The time in milliseconds after which {@link #call()} will return with {@link
+     *     RemoteResult#FAILED_TIMED_OUT} if the callable hasn't completed and no one canceled. The
+     *     time starts to be counted in {@link #call()}.
+     */
+    public RemoteCall(RemoteCallable<IBackupCallback> callable, long timeoutMs) {
+        this(false, callable, timeoutMs);
+    }
+
+    /**
+     * Same as {@link #RemoteCall(RemoteCallable, long)} but with parameter {@code cancelled}.
+     *
+     * @param cancelled Whether the call has already been canceled. It has the same effect of
+     *     calling {@link #cancel()} before {@link #call()}.
+     * @see #RemoteCall(RemoteCallable, long)
+     */
+    public RemoteCall(boolean cancelled, RemoteCallable<IBackupCallback> callable, long timeoutMs) {
+        mCallable = callable;
+        mTimeoutMs = timeoutMs;
+        mFuture = new CompletableFuture<>();
+        if (cancelled) {
+            cancel();
+        }
+    }
+
+    /**
+     * Kicks-off the callable provided in the constructor and blocks before returning, waiting for
+     * the first of these to happen:
+     *
+     * <ul>
+     *   <li>The callback passed to {@link RemoteCallable} is called with the result. We return a
+     *       successful {@link RemoteResult} with the result.
+     *   <li>Time-out happens. We return {@link RemoteResult#FAILED_TIMED_OUT}.
+     *   <li>Someone calls {@link #cancel()} on this object. We return {@link
+     *       RemoteResult#FAILED_CANCELLED}.
+     * </ul>
+     *
+     * <p>This method can't be called from the main thread and was designed to be called only once.
+     *
+     * @return A {@link RemoteResult} with the result of the operation.
+     * @throws RemoteException If the callable throws it.
+     */
+    @WorkerThread
+    public RemoteResult call() throws RemoteException {
+        // If called on the main-thread we would never get a time-out != 0
+        Preconditions.checkState(
+                !Looper.getMainLooper().isCurrentThread(), "Can't call call() on main thread");
+
+        if (!mFuture.isDone()) {
+            if (mTimeoutMs == 0L) {
+                timeOut();
+            } else {
+                Handler.getMain().postDelayed(this::timeOut, mTimeoutMs);
+                mCallable.call(new FutureBackupCallback(mFuture));
+            }
+        }
+        try {
+            return mFuture.get();
+        } catch (InterruptedException e) {
+            return RemoteResult.FAILED_THREAD_INTERRUPTED;
+        } catch (ExecutionException e) {
+            throw new IllegalStateException("Future unexpectedly completed with an exception");
+        }
+    }
+
+    /**
+     * Attempts to cancel the operation. It will only be successful if executed before the callback
+     * is called and before the time-out.
+     *
+     * <p>This method can be called from any thread, any time, including the same thread that called
+     * {@link #call()} (which is obviously only possible if the former is called before the latter).
+     */
+    public void cancel() {
+        mFuture.complete(RemoteResult.FAILED_CANCELLED);
+    }
+
+    private void timeOut() {
+        mFuture.complete(RemoteResult.FAILED_TIMED_OUT);
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/remote/RemoteCallable.java b/services/backup/java/com/android/server/backup/remote/RemoteCallable.java
new file mode 100644
index 0000000..d2671ff
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/RemoteCallable.java
@@ -0,0 +1,28 @@
+/*
+ * 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.backup.remote;
+
+import android.os.RemoteException;
+
+/**
+ * Implementations should perform a remote call in {@link #call(Object)}, possibly throwing {@link
+ * RemoteException}.
+ */
+@FunctionalInterface
+public interface RemoteCallable<T> {
+    void call(T input) throws RemoteException;
+}
diff --git a/services/backup/java/com/android/server/backup/remote/RemoteResult.java b/services/backup/java/com/android/server/backup/remote/RemoteResult.java
new file mode 100644
index 0000000..7f4f469
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/RemoteResult.java
@@ -0,0 +1,116 @@
+/*
+ * 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.backup.remote;
+
+import android.annotation.IntDef;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Represents the result of a {@link RemoteCall}. It can be either {@link #FAILED_TIMED_OUT}, {@link
+ * #FAILED_CANCELLED}, {@link #FAILED_THREAD_INTERRUPTED} or a successful result, in which case
+ * {@link #get()} returns its value.
+ *
+ * <p>Use {@link #succeeded()} to check for successful result, or direct identity comparison to
+ * check for specific failures, like {@code result == RemoteResult.FAILED_CANCELLED}.
+ */
+public class RemoteResult {
+    public static final RemoteResult FAILED_TIMED_OUT = new RemoteResult(Type.FAILED_TIMED_OUT, 0);
+    public static final RemoteResult FAILED_CANCELLED = new RemoteResult(Type.FAILED_CANCELLED, 0);
+    public static final RemoteResult FAILED_THREAD_INTERRUPTED =
+            new RemoteResult(Type.FAILED_THREAD_INTERRUPTED, 0);
+
+    public static RemoteResult successful(long value) {
+        return new RemoteResult(Type.SUCCESS, value);
+    }
+
+    @Type private final int mType;
+    private final long mValue;
+
+    private RemoteResult(@Type int type, long value) {
+        mType = type;
+        mValue = value;
+    }
+
+    public boolean succeeded() {
+        return mType == Type.SUCCESS;
+    }
+
+    /**
+     * Returns the value of this result.
+     *
+     * @throws IllegalStateException in case this is not a successful result.
+     */
+    public long get() {
+        Preconditions.checkState(succeeded(), "Can't obtain value of failed result");
+        return mValue;
+    }
+
+    @Override
+    public String toString() {
+        return "RemoteResult{" + toStringDescription() + "}";
+    }
+
+    private String toStringDescription() {
+        switch (mType) {
+            case Type.SUCCESS:
+                return Long.toString(mValue);
+            case Type.FAILED_TIMED_OUT:
+                return "FAILED_TIMED_OUT";
+            case Type.FAILED_CANCELLED:
+                return "FAILED_CANCELLED";
+            case Type.FAILED_THREAD_INTERRUPTED:
+                return "FAILED_THREAD_INTERRUPTED";
+        }
+        throw new AssertionError("Unknown type");
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof RemoteResult)) {
+            return false;
+        }
+        RemoteResult that = (RemoteResult) o;
+        return mType == that.mType && mValue == that.mValue;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mType, mValue);
+    }
+
+    @IntDef({
+        Type.SUCCESS,
+        Type.FAILED_TIMED_OUT,
+        Type.FAILED_CANCELLED,
+        Type.FAILED_THREAD_INTERRUPTED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface Type {
+        int SUCCESS = 0;
+        int FAILED_TIMED_OUT = 1;
+        int FAILED_CANCELLED = 2;
+        int FAILED_THREAD_INTERRUPTED = 3;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/remote/ServiceBackupCallback.java b/services/backup/java/com/android/server/backup/remote/ServiceBackupCallback.java
new file mode 100644
index 0000000..28d85a6
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/remote/ServiceBackupCallback.java
@@ -0,0 +1,43 @@
+/*
+ * 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.backup.remote;
+
+import android.app.backup.IBackupCallback;
+import android.app.backup.IBackupManager;
+import android.os.RemoteException;
+
+import com.android.server.backup.BackupManagerService;
+
+/**
+ * An implementation of {@link IBackupCallback} that routes the result to {@link
+ * BackupManagerService} via {@link IBackupManager#opComplete(int, long)} passing the token provided
+ * in the constructor.
+ */
+public class ServiceBackupCallback extends IBackupCallback.Stub {
+    private final IBackupManager mBackupManager;
+    private final int mToken;
+
+    public ServiceBackupCallback(IBackupManager backupManager, int token) {
+        mBackupManager = backupManager;
+        mToken = token;
+    }
+
+    @Override
+    public void operationComplete(long result) throws RemoteException {
+        mBackupManager.opComplete(mToken, result);
+    }
+}
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index c63b8f4..9a7c345 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -34,7 +34,6 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.BinderInternal;
-import com.android.server.LocalServices;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -131,6 +130,7 @@
 
     public static class LifeCycle extends SystemService {
         private BinderCallsStatsService mService;
+        private BinderCallsStats mBinderCallsStats;
 
         public LifeCycle(Context context) {
             super(context);
@@ -138,9 +138,9 @@
 
         @Override
         public void onStart() {
-            BinderCallsStats binderCallsStats = new BinderCallsStats(new Random());
-            mService = new BinderCallsStatsService(binderCallsStats);
-            LocalServices.addService(Internal.class, new Internal(binderCallsStats));
+            mBinderCallsStats = new BinderCallsStats(new BinderCallsStats.Injector());
+            mService = new BinderCallsStatsService(mBinderCallsStats);
+            publishLocalService(Internal.class, new Internal(mBinderCallsStats));
             publishBinderService("binder_calls_stats", mService);
             boolean detailedTrackingEnabled = SystemProperties.getBoolean(
                     PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, false);
@@ -149,7 +149,7 @@
                 Slog.i(TAG, "Enabled CPU usage tracking for binder calls. Controlled by "
                         + PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
                         + " or via dumpsys binder_calls_stats --enable-detailed-tracking");
-                binderCallsStats.setDetailedTracking(true);
+                mBinderCallsStats.setDetailedTracking(true);
             }
         }
 
@@ -157,6 +157,7 @@
         public void onBootPhase(int phase) {
             if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
                 mService.systemReady(getContext());
+                mBinderCallsStats.systemReady(getContext());
             }
         }
     }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 2054e0a..6b3f8f8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -500,6 +500,9 @@
 
     private final IpConnectivityLog mMetricsLog;
 
+    @GuardedBy("mBandwidthRequests")
+    private final SparseArray<Integer> mBandwidthRequests = new SparseArray(10);
+
     @VisibleForTesting
     final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
 
@@ -2107,6 +2110,18 @@
                 pw.println("currently holding WakeLock for: " + (duration / 1000) + "s");
             }
             mWakelockLogs.reverseDump(fd, pw, args);
+
+            pw.println();
+            pw.println("bandwidth update requests (by uid):");
+            pw.increaseIndent();
+            synchronized (mBandwidthRequests) {
+                for (int i = 0; i < mBandwidthRequests.size(); i++) {
+                    pw.println("[" + mBandwidthRequests.keyAt(i)
+                            + "]: " + mBandwidthRequests.valueAt(i));
+                }
+            }
+            pw.decreaseIndent();
+
             pw.decreaseIndent();
         }
     }
@@ -4267,6 +4282,14 @@
         }
         if (nai != null) {
             nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
+            synchronized (mBandwidthRequests) {
+                final int uid = Binder.getCallingUid();
+                Integer uidReqs = mBandwidthRequests.get(uid);
+                if (uidReqs == null) {
+                    uidReqs = new Integer(0);
+                }
+                mBandwidthRequests.put(uid, ++uidReqs);
+            }
             return true;
         }
         return false;
@@ -5863,4 +5886,4 @@
             pw.println("    Get airplane mode.");
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 9631e46..abcd6ef 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1495,10 +1495,9 @@
             }
 
             try {
-                mConnector.execute("idletimer", "add", iface, Integer.toString(timeout),
-                        Integer.toString(type));
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+                mNetdService.idletimerAddInterface(iface, timeout, Integer.toString(type));
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
             mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
 
@@ -1529,10 +1528,10 @@
             }
 
             try {
-                mConnector.execute("idletimer", "remove", iface,
-                        Integer.toString(params.timeout), Integer.toString(params.type));
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+                mNetdService.idletimerRemoveInterface(iface,
+                        params.timeout, Integer.toString(params.type));
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
             mActiveIdleTimers.remove(iface);
             mDaemonHandler.post(new Runnable() {
diff --git a/services/core/java/com/android/server/biometrics/common/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/common/AuthenticationClient.java
index 02cc6d5..10a1b90 100644
--- a/services/core/java/com/android/server/biometrics/common/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/common/AuthenticationClient.java
@@ -114,7 +114,7 @@
         if (mBundle != null) {
             try {
                 if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
-                    mStatusBarService.onFingerprintHelp(
+                    mStatusBarService.onBiometricHelp(
                             mFingerprintManager.getAcquiredString(acquiredInfo, vendorCode));
                 }
                 return false; // acquisition continues
@@ -143,7 +143,7 @@
         }
         if (mBundle != null) {
             try {
-                mStatusBarService.onFingerprintError(
+                mStatusBarService.onBiometricError(
                         mFingerprintManager.getErrorString(error, vendorCode));
             } catch (RemoteException e) {
                 Slog.e(getLogTag(), "Remote exception when sending error", e);
@@ -162,9 +162,9 @@
         if (mBundle != null) {
             try {
                 if (authenticated) {
-                    mStatusBarService.onFingerprintAuthenticated();
+                    mStatusBarService.onBiometricAuthenticated();
                 } else {
-                    mStatusBarService.onFingerprintHelp(getContext().getResources().getString(
+                    mStatusBarService.onBiometricHelp(getContext().getResources().getString(
                             com.android.internal.R.string.fingerprint_not_recognized));
                 }
             } catch (RemoteException e) {
@@ -224,7 +224,7 @@
 
                     // Send the lockout message to the system dialog
                     if (mBundle != null) {
-                        mStatusBarService.onFingerprintError(
+                        mStatusBarService.onBiometricError(
                                 mFingerprintManager.getErrorString(errorCode, 0 /* vendorCode */));
                     }
                 } catch (RemoteException e) {
@@ -263,7 +263,7 @@
             // If authenticating with system dialog, show the dialog
             if (mBundle != null) {
                 try {
-                    mStatusBarService.showFingerprintDialog(mBundle, mDialogReceiver);
+                    mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver);
                 } catch (RemoteException e) {
                     Slog.e(getLogTag(), "Unable to show fingerprint dialog", e);
                 }
@@ -301,7 +301,7 @@
             // after BiometricPrompt.HIDE_DIALOG_DELAY
             if (mBundle != null && !mDialogDismissed && !mInLockout) {
                 try {
-                    mStatusBarService.hideFingerprintDialog();
+                    mStatusBarService.hideBiometricDialog();
                 } catch (RemoteException e) {
                     Slog.e(getLogTag(), "Unable to hide fingerprint dialog", e);
                 }
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index dea9309..d154830 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -318,6 +318,17 @@
     static final String PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT =
         "persist.sys.hdmi.property_sytem_audio_device_arc_port";
 
+    /**
+     * Property to strip local audio of amplifier and use local speaker
+     * when TV does not support system audio mode.
+     *
+     * <p>This property applies to device with both audio system/playback types.
+     * <p>True means using local speaker when TV does not support system audio.
+     * <p>False means passing audio to TV. Default is true.
+     */
+    static final String PROPERTY_STRIP_AUDIO_TV_NO_SYSTEM_AUDIO =
+        "persist.sys.hdmi.property_strip_audio_tv_no_system_audio";
+
     static final int RECORDING_TYPE_DIGITAL_RF = 1;
     static final int RECORDING_TYPE_ANALOGUE_RF = 2;
     static final int RECORDING_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 3;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index ca85249..14af15f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -327,18 +327,7 @@
             !isPhysicalAddressMeOrBelow(targetPhysicalAddress)) {
             switchToAudioInput();
         }
-        // Mute device when feature is turned off and unmute device when feature is turned on
-        boolean currentMuteStatus =
-                mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC);
-        if (currentMuteStatus == newSystemAudioMode) {
-            mService.getAudioManager()
-                    .adjustStreamVolume(
-                            AudioManager.STREAM_MUSIC,
-                            newSystemAudioMode
-                                    ? AudioManager.ADJUST_UNMUTE
-                                    : AudioManager.ADJUST_MUTE,
-                            0);
-        }
+        // TODO(b/80297700): Mute device when TV terminates the system audio control
         updateAudioManagerForSystemAudio(newSystemAudioMode);
         synchronized (mLock) {
             if (mSystemAudioActivated != newSystemAudioMode) {
diff --git a/services/core/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java b/services/core/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
index a3949a4..596a4c0 100644
--- a/services/core/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
+++ b/services/core/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
@@ -16,8 +16,6 @@
 
 package com.android.server.job.controllers.idle;
 
-import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -35,20 +33,27 @@
     private static final boolean DEBUG = JobSchedulerService.DEBUG
             || Log.isLoggable(TAG, Log.DEBUG);
 
-    public static final String ACTION_FORCE_IDLE = "com.android.server.ACTION_FORCE_IDLE";
-    public static final String ACTION_UNFORCE_IDLE = "com.android.server.ACTION_UNFORCE_IDLE";
+    public static final String ACTION_GARAGE_MODE_ON =
+            "com.android.server.jobscheduler.GARAGE_MODE_ON";
+    public static final String ACTION_GARAGE_MODE_OFF =
+            "com.android.server.jobscheduler.GARAGE_MODE_OFF";
+
+    public static final String ACTION_FORCE_IDLE = "com.android.server.jobscheduler.FORCE_IDLE";
+    public static final String ACTION_UNFORCE_IDLE = "com.android.server.jobscheduler.UNFORCE_IDLE";
 
     // After construction, mutations of idle/screen-on state will only happen
     // on the main looper thread, either in onReceive() or in an alarm callback.
     private boolean mIdle;
-    private boolean mScreenOn;
+    private boolean mGarageModeOn;
+    private boolean mForced;
     private IdlenessListener mIdleListener;
 
     public CarIdlenessTracker() {
         // At boot we presume that the user has just "interacted" with the
         // device in some meaningful way.
         mIdle = false;
-        mScreenOn = true;
+        mGarageModeOn = false;
+        mForced = false;
     }
 
     @Override
@@ -62,9 +67,9 @@
 
         IntentFilter filter = new IntentFilter();
 
-        // Screen state
-        filter.addAction(Intent.ACTION_SCREEN_ON);
-        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        // State of GarageMode
+        filter.addAction(ACTION_GARAGE_MODE_ON);
+        filter.addAction(ACTION_GARAGE_MODE_OFF);
 
         // Debugging/instrumentation
         filter.addAction(ACTION_FORCE_IDLE);
@@ -77,7 +82,7 @@
     @Override
     public void dump(PrintWriter pw) {
         pw.print("  mIdle: "); pw.println(mIdle);
-        pw.print("  mScreenOn: "); pw.println(mScreenOn);
+        pw.print("  mGarageModeOn: "); pw.println(mGarageModeOn);
     }
 
     @Override
@@ -88,47 +93,58 @@
         // Check for forced actions
         if (action.equals(ACTION_FORCE_IDLE)) {
             logIfDebug("Forcing idle...");
-            enterIdleState(true);
+            setForceIdleState(true);
         } else if (action.equals(ACTION_UNFORCE_IDLE)) {
             logIfDebug("Unforcing idle...");
-            exitIdleState(true);
-        } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
-            logIfDebug("Going idle...");
-            mScreenOn = false;
-            enterIdleState(false);
-        } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
-            logIfDebug("exiting idle...");
-            mScreenOn = true;
-            exitIdleState(true);
+            setForceIdleState(false);
+        } else if (action.equals(ACTION_GARAGE_MODE_ON)) {
+            logIfDebug("GarageMode is on...");
+            mGarageModeOn = true;
+            updateIdlenessState();
+        } else if (action.equals(ACTION_GARAGE_MODE_OFF)) {
+            logIfDebug("GarageMode is off...");
+            mGarageModeOn = false;
+            updateIdlenessState();
         } else if (action.equals(ActivityManagerService.ACTION_TRIGGER_IDLE)) {
-            if (!mScreenOn) {
+            if (!mGarageModeOn) {
                 logIfDebug("Idle trigger fired...");
-                enterIdleState(false);
+                triggerIdlenessOnce();
             } else {
                 logIfDebug("TRIGGER_IDLE received but not changing state; idle="
-                        + mIdle + " screen=" + mScreenOn);
+                        + mIdle + " screen=" + mGarageModeOn);
             }
         }
     }
 
-    private void enterIdleState(boolean forced) {
-        if (!forced && mIdle) {
-            // Already idle and don't need to trigger callbacks since not forced
-            logIfDebug("Device is already considered idle");
-            return;
-        }
-        mIdle = true;
-        mIdleListener.reportNewIdleState(mIdle);
+    private void setForceIdleState(boolean forced) {
+        mForced = forced;
+        updateIdlenessState();
     }
 
-    private void exitIdleState(boolean forced) {
-        if (!forced && !mIdle) {
-            // Already out of idle and don't need to trigger callbacks since not forced
-            logIfDebug("Device is already considered not idle");
-            return;
+    private void updateIdlenessState() {
+        final boolean newState = (mForced || mGarageModeOn);
+        if (mIdle != newState) {
+            // State of idleness changed. Notifying idleness controller
+            logIfDebug("Device idleness changed. New idle=" + newState);
+            mIdle = newState;
+            mIdleListener.reportNewIdleState(mIdle);
+        } else {
+            // Nothing changed, device idleness is in the same state as new state
+            logIfDebug("Device idleness is the same. Current idle=" + newState);
         }
-        mIdle = false;
-        mIdleListener.reportNewIdleState(mIdle);
+    }
+
+    private void triggerIdlenessOnce() {
+        // This is simply triggering idleness once until some constraint will switch it back off
+        if (mIdle) {
+            // Already in idle state. Nothing to do
+            logIfDebug("Device is already idle");
+        } else {
+            // Going idle once
+            logIfDebug("Device is going idle once");
+            mIdle = true;
+            mIdleListener.reportNewIdleState(mIdle);
+        }
     }
 
     private void logIfDebug(String msg) {
diff --git a/services/core/java/com/android/server/location/ContextHubClientManager.java b/services/core/java/com/android/server/location/ContextHubClientManager.java
index 74930c8..4243f02 100644
--- a/services/core/java/com/android/server/location/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/ContextHubClientManager.java
@@ -45,7 +45,7 @@
     /*
      * Local flag to enable debug logging.
      */
-    private static final boolean DEBUG_LOG_ENABLED = true;
+    private static final boolean DEBUG_LOG_ENABLED = false;
 
     /*
      * The context of the service.
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index dc95d41..27509de 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -77,6 +77,11 @@
 
     private static final int OS_APP_INSTANCE = -1;
 
+    /*
+     * Local flag to enable debug logging.
+     */
+    private static final boolean DEBUG_LOG_ENABLED = false;
+
     private final Context mContext;
 
     private final Map<Integer, ContextHubInfo> mContextHubIdToInfoMap;
@@ -779,12 +784,16 @@
 
         int msgVersion = 0;
         int callbacksCount = mCallbacksList.beginBroadcast();
-        Log.d(TAG, "Sending message " + msgType + " version " + msgVersion + " from hubHandle " +
-                contextHubHandle + ", appInstance " + appInstance + ", callBackCount "
-                + callbacksCount);
+        if (DEBUG_LOG_ENABLED) {
+            Log.v(TAG, "Sending message " + msgType + " version " + msgVersion + " from hubHandle "
+                    + contextHubHandle + ", appInstance " + appInstance + ", callBackCount "
+                    + callbacksCount);
+        }
 
         if (callbacksCount < 1) {
-            Log.v(TAG, "No message callbacks registered.");
+            if (DEBUG_LOG_ENABLED) {
+                Log.v(TAG, "No message callbacks registered.");
+            }
             return 0;
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d0789b7..de53427 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4031,6 +4031,7 @@
                     + " notification=" + notification);
         }
         checkCallerIsSystemOrSameApp(pkg);
+        checkRestrictedCategories(notification);
 
         final int userId = ActivityManager.handleIncomingUser(callingPid,
                 callingUid, incomingUserId, true, false, "enqueueNotification", pkg);
@@ -5272,6 +5273,7 @@
             ArrayList<Integer> userSentimentBefore = new ArrayList<>(N);
             ArrayList<Integer> suppressVisuallyBefore = new ArrayList<>(N);
             ArrayList<ArrayList<Notification.Action>> smartActionsBefore = new ArrayList<>(N);
+            ArrayList<ArrayList<CharSequence>> smartRepliesBefore = new ArrayList<>(N);
             for (int i = 0; i < N; i++) {
                 final NotificationRecord r = mNotificationList.get(i);
                 orderBefore.add(r.getKey());
@@ -5284,6 +5286,7 @@
                 userSentimentBefore.add(r.getUserSentiment());
                 suppressVisuallyBefore.add(r.getSuppressedVisualEffects());
                 smartActionsBefore.add(r.getSmartActions());
+                smartRepliesBefore.add(r.getSmartReplies());
                 mRankingHelper.extractSignals(r);
             }
             mRankingHelper.sort(mNotificationList);
@@ -5299,7 +5302,8 @@
                         || !Objects.equals(userSentimentBefore.get(i), r.getUserSentiment())
                         || !Objects.equals(suppressVisuallyBefore.get(i),
                         r.getSuppressedVisualEffects())
-                        || !Objects.equals(smartActionsBefore.get(i), r.getSmartActions())) {
+                        || !Objects.equals(smartActionsBefore.get(i), r.getSmartActions())
+                        || !Objects.equals(smartRepliesBefore.get(i), r.getSmartReplies())) {
                     mHandler.scheduleSendRankingUpdate();
                     return;
                 }
@@ -6197,6 +6201,26 @@
         checkCallerIsSameApp(pkg);
     }
 
+    /**
+     * Check if the notification is of a category type that is restricted to system use only,
+     * if so throw SecurityException
+     */
+    private void checkRestrictedCategories(final Notification notification) {
+        try {
+            if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) {
+                return;
+            }
+        } catch (RemoteException re) {
+            if (DBG) Log.e(TAG, "Unable to confirm if it's safe to skip category "
+                    + "restrictions check thus the check will be done anyway");
+        }
+        if (Notification.CATEGORY_CAR_EMERGENCY.equals(notification.category)
+                || Notification.CATEGORY_CAR_WARNING.equals(notification.category)
+                || Notification.CATEGORY_CAR_INFORMATION.equals(notification.category)) {
+                    checkCallerIsSystem();
+        }
+    }
+
     private boolean isCallerInstantApp(String pkg) {
         // System is always allowed to act for ephemeral apps.
         if (isCallerSystemOrPhone()) {
@@ -6276,6 +6300,7 @@
         Bundle userSentiment = new Bundle();
         Bundle hidden = new Bundle();
         Bundle smartActions = new Bundle();
+        Bundle smartReplies = new Bundle();
         for (int i = 0; i < N; i++) {
             NotificationRecord record = mNotificationList.get(i);
             if (!isVisibleToListener(record.sbn, info)) {
@@ -6304,6 +6329,7 @@
             userSentiment.putInt(key, record.getUserSentiment());
             hidden.putBoolean(key, record.isHidden());
             smartActions.putParcelableArrayList(key, record.getSmartActions());
+            smartReplies.putCharSequenceArrayList(key, record.getSmartReplies());
         }
         final int M = keys.size();
         String[] keysAr = keys.toArray(new String[M]);
@@ -6315,7 +6341,7 @@
         return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
                 suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
                 channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden,
-                smartActions);
+                smartActions, smartReplies);
     }
 
     boolean hasCompanionDevice(ManagedServiceInfo info) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index f32b338..469828b 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -162,6 +162,7 @@
     private String mGroupLogTag;
     private String mChannelIdLogTag;
     private ArrayList<Notification.Action> mSmartActions;
+    private ArrayList<CharSequence> mSmartReplies;
 
     private final List<Adjustment> mAdjustments;
     private final NotificationStats mStats;
@@ -637,6 +638,9 @@
                 if (signals.containsKey(Adjustment.KEY_SMART_ACTIONS)) {
                     setSmartActions(signals.getParcelableArrayList(Adjustment.KEY_SMART_ACTIONS));
                 }
+                if (signals.containsKey(Adjustment.KEY_SMART_REPLIES)) {
+                    setSmartReplies(signals.getCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES));
+                }
             }
         }
     }
@@ -1064,6 +1068,14 @@
         return mSmartActions;
     }
 
+    public void setSmartReplies(ArrayList<CharSequence> smartReplies) {
+        mSmartReplies = smartReplies;
+    }
+
+    public ArrayList<CharSequence> getSmartReplies() {
+        return mSmartReplies;
+    }
+
     /**
      * @return all {@link Uri} that should have permission granted to whoever
      *         will be rendering it. This list has already been vetted to only
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e46c03e..a8b92a6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -288,6 +288,8 @@
 import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
 import com.android.server.wm.AppTransition;
 import com.android.server.wm.DisplayFrames;
+import com.android.server.wm.DisplayPolicy;
+import com.android.server.wm.DisplayRotation;
 import com.android.server.wm.WindowFrames;
 import com.android.server.wm.WindowManagerInternal;
 import com.android.server.wm.WindowManagerInternal.AppTransitionListener;
@@ -500,8 +502,6 @@
     WindowState mStatusBar = null;
     private final int[] mStatusBarHeightForRotation = new int[4];
     WindowState mNavigationBar = null;
-    boolean mHasNavigationBar = false;
-    boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
     @NavigationBarPosition
     int mNavigationBarPosition = NAV_BAR_BOTTOM;
     int[] mNavigationBarHeightForRotationDefault = new int[4];
@@ -556,8 +556,6 @@
     volatile boolean mRecentsVisible;
     volatile boolean mNavBarVirtualKeyHapticFeedbackEnabled = true;
     volatile boolean mPictureInPictureVisible;
-    // Written by vr manager thread, only read in this class.
-    volatile private boolean mPersistentVrModeEnabled;
     volatile private boolean mDismissImeOnBackKeyPressed;
 
     // Used to hold the last user key used to wake the device.  This helps us prevent up events
@@ -567,40 +565,18 @@
     int mRecentAppsHeldModifiers;
     boolean mLanguageSwitchKeyPressed;
 
-    int mLidState = LID_ABSENT;
     int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
     boolean mHaveBuiltInKeyboard;
 
     boolean mSystemReady;
     boolean mSystemBooted;
-    boolean mHdmiPlugged;
     HdmiControl mHdmiControl;
     IUiModeManager mUiModeManager;
     int mUiMode;
-    int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
-    int mLidOpenRotation;
-    int mCarDockRotation;
-    int mDeskDockRotation;
-    int mUndockedHdmiRotation;
-    int mDemoHdmiRotation;
-    boolean mDemoHdmiRotationLock;
-    int mDemoRotation;
-    boolean mDemoRotationLock;
 
     boolean mWakeGestureEnabledSetting;
     MyWakeGestureListener mWakeGestureListener;
 
-    // Default display does not rotate, apps that require non-default orientation will have to
-    // have the orientation emulated.
-    private boolean mForceDefaultOrientation = false;
-
-    int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
-    int mUserRotation = Surface.ROTATION_0;
-
-    boolean mSupportAutoRotation;
-    int mAllowAllRotations = -1;
-    boolean mCarDockEnablesAccelerometer;
-    boolean mDeskDockEnablesAccelerometer;
     int mLidKeyboardAccessibility;
     int mLidNavigationAccessibility;
     boolean mLidControlsScreenLock;
@@ -613,14 +589,6 @@
     int mLongPressOnBackBehavior;
     int mShortPressOnSleepBehavior;
     int mShortPressOnWindowBehavior;
-    volatile boolean mAwake;
-    boolean mScreenOnEarly;
-    boolean mScreenOnFully;
-    ScreenOnListener mScreenOnListener;
-    boolean mKeyguardDrawComplete;
-    boolean mWindowManagerDrawComplete;
-    boolean mOrientationSensorEnabled = false;
-    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mHasSoftInput = false;
     boolean mTranslucentDecorEnabled = true;
     boolean mUseTvRouting;
@@ -729,18 +697,14 @@
     // Behavior of Back button while in-call and screen on
     int mIncallBackBehavior;
 
-    // Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION)
-    int mShowRotationSuggestions;
-
     // Whether system navigation keys are enabled
     boolean mSystemNavigationKeysEnabled;
 
-    Display mDisplay;
-
-    int mLandscapeRotation = 0;  // default landscape rotation
-    int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
-    int mPortraitRotation = 0;   // default portrait rotation
-    int mUpsideDownRotation = 0; // "other" portrait rotation
+    // TODO(b/111361251): Remove default when the dependencies are multi-display ready.
+    Display mDefaultDisplay;
+    DisplayRotation mDefaultDisplayRotation;
+    DisplayPolicy mDefaultDisplayPolicy;
+    WindowOrientationListener mDefaultOrientationListener;
 
     // What we do when the user long presses on home
     private int mLongPressOnHomeBehavior;
@@ -963,7 +927,7 @@
     private UEventObserver mHDMIObserver = new UEventObserver() {
         @Override
         public void onUEvent(UEventObserver.UEvent event) {
-            setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
+            mDefaultDisplayPolicy.setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
         }
     };
 
@@ -988,12 +952,6 @@
                     Settings.Secure.WAKE_GESTURE_ENABLED), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.ACCELEROMETER_ROTATION), false, this,
-                    UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.USER_ROTATION), false, this,
-                    UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.System.getUriFor(
                     Settings.System.SCREEN_OFF_TIMEOUT), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
@@ -1006,9 +964,6 @@
                     Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS), false, this,
-                    UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.VOLUME_HUSH_GESTURE), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.Global.getUriFor(
@@ -1043,53 +998,11 @@
         }
     }
 
-    class MyOrientationListener extends WindowOrientationListener {
-
-        private SparseArray<Runnable> mRunnableCache;
-
-        MyOrientationListener(Context context, Handler handler) {
-            super(context, handler);
-            mRunnableCache = new SparseArray<>(5);
-        }
-
-        private class UpdateRunnable implements Runnable {
-            private final int mRotation;
-            UpdateRunnable(int rotation) {
-                mRotation = rotation;
-            }
-
-            @Override
-            public void run() {
-                // send interaction hint to improve redraw performance
-                mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
-                if (isRotationChoicePossible(mCurrentAppOrientation)) {
-                    final boolean isValid = isValidRotationChoice(mCurrentAppOrientation,
-                            mRotation);
-                    sendProposedRotationChangeToStatusBarInternal(mRotation, isValid);
-                } else {
-                    updateRotation(false);
-                }
-            }
-        }
-
-        @Override
-        public void onProposedRotationChanged(int rotation) {
-            if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
-            Runnable r = mRunnableCache.get(rotation, null);
-            if (r == null){
-                r = new UpdateRunnable(rotation);
-                mRunnableCache.put(rotation, r);
-            }
-            mHandler.post(r);
-        }
-    }
-    MyOrientationListener mOrientationListener;
-
     final IPersistentVrStateCallbacks mPersistentVrModeListener =
             new IPersistentVrStateCallbacks.Stub() {
         @Override
         public void onPersistentVrStateChanged(boolean enabled) {
-            mPersistentVrModeEnabled = enabled;
+            mDefaultDisplayPolicy.setPersistentVrModeEnabled(enabled);
         }
     };
 
@@ -1171,100 +1084,6 @@
         }
     }
 
-    /*
-     * We always let the sensor be switched on by default except when
-     * the user has explicitly disabled sensor based rotation or when the
-     * screen is switched off.
-     */
-    boolean needSensorRunningLp() {
-        if (mSupportAutoRotation) {
-            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
-                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
-                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
-                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
-                // If the application has explicitly requested to follow the
-                // orientation, then we need to turn the sensor on.
-                return true;
-            }
-        }
-        if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
-                (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
-                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
-                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
-            // enable accelerometer if we are docked in a dock that enables accelerometer
-            // orientation management,
-            return true;
-        }
-        if (mUserRotationMode == USER_ROTATION_LOCKED) {
-            // If the setting for using the sensor by default is enabled, then
-            // we will always leave it on.  Note that the user could go to
-            // a window that forces an orientation that does not use the
-            // sensor and in theory we could turn it off... however, when next
-            // turning it on we won't have a good value for the current
-            // orientation for a little bit, which can cause orientation
-            // changes to lag, so we'd like to keep it always on.  (It will
-            // still be turned off when the screen is off.)
-
-            // When locked we can provide rotation suggestions users can approve to change the
-            // current screen rotation. To do this the sensor needs to be running.
-            return mSupportAutoRotation &&
-                    mShowRotationSuggestions == Settings.Secure.SHOW_ROTATION_SUGGESTIONS_ENABLED;
-        }
-        return mSupportAutoRotation;
-    }
-
-    /*
-     * Various use cases for invoking this function
-     * screen turning off, should always disable listeners if already enabled
-     * screen turned on and current app has sensor based orientation, enable listeners
-     * if not already enabled
-     * screen turned on and current app does not have sensor orientation, disable listeners if
-     * already enabled
-     * screen turning on and current app has sensor based orientation, enable listeners if needed
-     * screen turning on and current app has nosensor based orientation, do nothing
-     */
-    void updateOrientationListenerLp() {
-        if (!mOrientationListener.canDetectOrientation()) {
-            // If sensor is turned off or nonexistent for some reason
-            return;
-        }
-        // Could have been invoked due to screen turning on or off or
-        // change of the currently visible window's orientation.
-        if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
-                + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
-                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
-                + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
-                + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
-
-        boolean disable = true;
-        // Note: We postpone the rotating of the screen until the keyguard as well as the
-        // window manager have reported a draw complete or the keyguard is going away in dismiss
-        // mode.
-        if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete))) {
-            if (needSensorRunningLp()) {
-                disable = false;
-                //enable listener if not already enabled
-                if (!mOrientationSensorEnabled) {
-                    // Don't clear the current sensor orientation if the keyguard is going away in
-                    // dismiss mode. This allows window manager to use the last sensor reading to
-                    // determine the orientation vs. falling back to the last known orientation if
-                    // the sensor reading was cleared which can cause it to relaunch the app that
-                    // will show in the wrong orientation first before correcting leading to app
-                    // launch delays.
-                    mOrientationListener.enable(true /* clearCurrentRotation */);
-                    if(localLOGV) Slog.v(TAG, "Enabling listeners");
-                    mOrientationSensorEnabled = true;
-                }
-            }
-        }
-        //check if sensors need to be disabled
-        if (disable && mOrientationSensorEnabled) {
-            mOrientationListener.disable();
-            if(localLOGV) Slog.v(TAG, "Disabling listeners");
-            mOrientationSensorEnabled = false;
-        }
-    }
-
     private void interceptBackKeyDown() {
         MetricsLogger.count(mContext, "key_back_down", 1);
         // Reset back key state for long press
@@ -1490,7 +1309,7 @@
     }
 
     private void powerPress(long eventTime, boolean interactive, int count) {
-        if (mScreenOnEarly && !mScreenOnFully) {
+        if (mDefaultDisplayPolicy.isScreenOnEarly() && !mDefaultDisplayPolicy.isScreenOnFully()) {
             Slog.i(TAG, "Suppressed redundant power key press while "
                     + "already in the process of turning the screen on.");
             return;
@@ -1990,6 +1809,14 @@
         return mContext.getResources().getConfiguration().isScreenRound();
     }
 
+    @Override
+    public void setDefaultDisplay(DisplayContentInfo displayContentInfo) {
+        mDefaultDisplay = displayContentInfo.getDisplay();
+        mDefaultDisplayRotation = displayContentInfo.getDisplayRotation();
+        mDefaultDisplayPolicy = mDefaultDisplayRotation.getDisplayPolicy();
+        mDefaultOrientationListener = mDefaultDisplayRotation.getOrientationListener();
+    }
+
     /** {@inheritDoc} */
     @Override
     public void init(Context context, IWindowManager windowManager,
@@ -2046,10 +1873,6 @@
 
         mHandler = new PolicyHandler();
         mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
-        mOrientationListener = new MyOrientationListener(mContext, mHandler);
-        try {
-            mOrientationListener.setCurrentRotation(windowManager.getDefaultDisplayRotation());
-        } catch (RemoteException ex) { }
         mSettingsObserver = new SettingsObserver(mHandler);
         mSettingsObserver.observe();
         mShortcutManager = new ShortcutManager(context);
@@ -2080,20 +1903,6 @@
         mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                 "PhoneWindowManager.mPowerKeyWakeLock");
         mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
-        mSupportAutoRotation = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_supportAutoRotation);
-        mLidOpenRotation = readRotation(
-                com.android.internal.R.integer.config_lidOpenRotation);
-        mCarDockRotation = readRotation(
-                com.android.internal.R.integer.config_carDockRotation);
-        mDeskDockRotation = readRotation(
-                com.android.internal.R.integer.config_deskDockRotation);
-        mUndockedHdmiRotation = readRotation(
-                com.android.internal.R.integer.config_undockedHdmiRotation);
-        mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
-        mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
         mLidKeyboardAccessibility = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lidKeyboardAccessibility);
         mLidNavigationAccessibility = mContext.getResources().getInteger(
@@ -2167,8 +1976,8 @@
         Intent intent = context.registerReceiver(mDockReceiver, filter);
         if (intent != null) {
             // Retrieve current sticky dock event broadcast.
-            mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
-                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
+            mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+                    Intent.EXTRA_DOCK_STATE_UNDOCKED));
         }
 
         // register for dream-related broadcasts
@@ -2222,11 +2031,11 @@
                     }
                     @Override
                     public void onDown() {
-                        mOrientationListener.onTouchStart();
+                        mDefaultOrientationListener.onTouchStart();
                     }
                     @Override
                     public void onUpOrCancel() {
-                        mOrientationListener.onTouchEnd();
+                        mDefaultOrientationListener.onTouchEnd();
                     }
                     @Override
                     public void onMouseHoverAtTop() {
@@ -2333,110 +2142,12 @@
                 com.android.internal.R.integer.config_navBarOpacityMode);
     }
 
-    @Override
-    public void setInitialDisplaySize(Display display, int width, int height, int density) {
-        // This method might be called before the policy has been fully initialized
-        // or for other displays we don't care about.
-        // TODO(multi-display): Define policy for secondary displays.
-        if (mContext == null || display.getDisplayId() != DEFAULT_DISPLAY) {
-            return;
-        }
-        mDisplay = display;
-
-        final Resources res = mContext.getResources();
-        int shortSize, longSize;
-        if (width > height) {
-            shortSize = height;
-            longSize = width;
-            mLandscapeRotation = Surface.ROTATION_0;
-            mSeascapeRotation = Surface.ROTATION_180;
-            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
-                mPortraitRotation = Surface.ROTATION_90;
-                mUpsideDownRotation = Surface.ROTATION_270;
-            } else {
-                mPortraitRotation = Surface.ROTATION_270;
-                mUpsideDownRotation = Surface.ROTATION_90;
-            }
-        } else {
-            shortSize = width;
-            longSize = height;
-            mPortraitRotation = Surface.ROTATION_0;
-            mUpsideDownRotation = Surface.ROTATION_180;
-            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
-                mLandscapeRotation = Surface.ROTATION_270;
-                mSeascapeRotation = Surface.ROTATION_90;
-            } else {
-                mLandscapeRotation = Surface.ROTATION_90;
-                mSeascapeRotation = Surface.ROTATION_270;
-            }
-        }
-
-        // SystemUI (status bar) layout policy
-        int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
-        int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
-
-        // Allow the navigation bar to move on non-square small devices (phones).
-        mNavigationBarCanMove = width != height && shortSizeDp < 600;
-
-        mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
-
-        // Allow a system property to override this. Used by the emulator.
-        // See also hasNavigationBar().
-        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
-        if ("1".equals(navBarOverride)) {
-            mHasNavigationBar = false;
-        } else if ("0".equals(navBarOverride)) {
-            mHasNavigationBar = true;
-        }
-
-        // For demo purposes, allow the rotation of the HDMI display to be controlled.
-        // By default, HDMI locks rotation to landscape.
-        if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
-            mDemoHdmiRotation = mPortraitRotation;
-        } else {
-            mDemoHdmiRotation = mLandscapeRotation;
-        }
-        mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
-
-        // For demo purposes, allow the rotation of the remote display to be controlled.
-        // By default, remote display locks rotation to landscape.
-        if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
-            mDemoRotation = mPortraitRotation;
-        } else {
-            mDemoRotation = mLandscapeRotation;
-        }
-        mDemoRotationLock = SystemProperties.getBoolean(
-                "persist.demo.rotationlock", false);
-
-        // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
-        // http://developer.android.com/guide/practices/screens_support.html#range
-        // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
-        // so if the orientation is forced, we need to respect that no matter what.
-        final boolean isCar = mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_AUTOMOTIVE);
-        // For TV, it's usually 960dp x 540dp, ignore the size limitation.
-        // so if the orientation is forced, we need to respect that no matter what.
-        final boolean isTv = mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_LEANBACK);
-        mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
-                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
-                // For debug purposes the next line turns this feature off with:
-                // $ adb shell setprop config.override_forced_orient true
-                // $ adb shell wm size reset
-                !"true".equals(SystemProperties.get("config.override_forced_orient"));
-    }
-
     /**
      * @return whether the navigation bar can be hidden, e.g. the device has a
      *         navigation bar and touch exploration is not enabled
      */
     private boolean canHideNavigationBar() {
-        return mHasNavigationBar;
-    }
-
-    @Override
-    public boolean isDefaultOrientationForced() {
-        return mForceDefaultOrientation;
+        return mDefaultDisplayPolicy.hasNavigationBar();
     }
 
     public void updateSettings() {
@@ -2465,15 +2176,6 @@
                     .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
                 mRingerToggleChord = Settings.Secure.VOLUME_HUSH_OFF;
             }
-            // Configure rotation suggestions.
-            int showRotationSuggestions = Settings.Secure.getIntForUser(resolver,
-                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
-                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS_DEFAULT,
-                    UserHandle.USER_CURRENT);
-            if (mShowRotationSuggestions != showRotationSuggestions) {
-                mShowRotationSuggestions = showRotationSuggestions;
-                updateOrientationListenerLp(); // Enable, disable the orientation listener
-            }
 
             // Configure wake gesture.
             boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
@@ -2484,24 +2186,6 @@
                 updateWakeGestureListenerLp();
             }
 
-            // Configure rotation lock.
-            int userRotation = Settings.System.getIntForUser(resolver,
-                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
-                    UserHandle.USER_CURRENT);
-            if (mUserRotation != userRotation) {
-                mUserRotation = userRotation;
-                updateRotation = true;
-            }
-            int userRotationMode = Settings.System.getIntForUser(resolver,
-                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
-                            WindowManagerPolicy.USER_ROTATION_FREE :
-                                    WindowManagerPolicy.USER_ROTATION_LOCKED;
-            if (mUserRotationMode != userRotationMode) {
-                mUserRotationMode = userRotationMode;
-                updateRotation = true;
-                updateOrientationListenerLp();
-            }
-
             if (mSystemReady) {
                 int pointerLocation = Settings.System.getIntForUser(resolver,
                         Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT);
@@ -2542,8 +2226,8 @@
     }
 
     private boolean shouldEnableWakeGestureLp() {
-        return mWakeGestureEnabledSetting && !mAwake
-                && (!mLidControlsSleep || mLidState != LID_CLOSED)
+        return mWakeGestureEnabledSetting && !mDefaultDisplayPolicy.isAwake()
+                && (!mLidControlsSleep || mDefaultDisplayPolicy.getLidState() != LID_CLOSED)
                 && mWakeGestureListener.isSupported();
     }
 
@@ -2583,24 +2267,6 @@
         }
     }
 
-    private int readRotation(int resID) {
-        try {
-            int rotation = mContext.getResources().getInteger(resID);
-            switch (rotation) {
-                case 0:
-                    return Surface.ROTATION_0;
-                case 90:
-                    return Surface.ROTATION_90;
-                case 180:
-                    return Surface.ROTATION_180;
-                case 270:
-                    return Surface.ROTATION_270;
-            }
-        } catch (Resources.NotFoundException e) {
-            // fall through
-        }
-        return -1;
-    }
 
     /** {@inheritDoc} */
     @Override
@@ -2829,7 +2495,7 @@
     }
 
     void readLidState() {
-        mLidState = mWindowManagerFuncs.getLidState();
+        mDefaultDisplayPolicy.setLidState(mWindowManagerFuncs.getLidState());
     }
 
     private void readCameraLensCoverState() {
@@ -2837,11 +2503,12 @@
     }
 
     private boolean isHidden(int accessibilityMode) {
+        final int lidState = mDefaultDisplayPolicy.getLidState();
         switch (accessibilityMode) {
             case 1:
-                return mLidState == LID_CLOSED;
+                return lidState == LID_CLOSED;
             case 2:
-                return mLidState == LID_OPEN;
+                return lidState == LID_OPEN;
             default:
                 return false;
         }
@@ -2873,53 +2540,62 @@
     }
 
     @Override
-    public void onOverlayChangedLw() {
-        onConfigurationChanged();
+    public void onOverlayChangedLw(DisplayContentInfo displayContentInfo) {
+        onConfigurationChanged(displayContentInfo);
     }
 
     @Override
-    public void onConfigurationChanged() {
+    public void onConfigurationChanged(DisplayContentInfo displayContentInfo) {
+        final DisplayRotation displayRotation = displayContentInfo.getDisplayRotation();
         // TODO(multi-display): Define policy for secondary displays.
-        Context uiContext = getSystemUiContext();
-        final Resources res = uiContext.getResources();
+        if (!displayRotation.isDefaultDisplay) {
+            return;
+        }
 
-        mStatusBarHeightForRotation[mPortraitRotation] =
-                mStatusBarHeightForRotation[mUpsideDownRotation] = res.getDimensionPixelSize(
+        final Context uiContext = getSystemUiContext();
+        final Resources res = uiContext.getResources();
+        final int portraitRotation = displayRotation.getPortraitRotation();
+        final int upsideDownRotation = displayRotation.getUpsideDownRotation();
+        final int landscapeRotation = displayRotation.getLandscapeRotation();
+        final int seascapeRotation = displayRotation.getSeascapeRotation();
+
+        mStatusBarHeightForRotation[portraitRotation] =
+                mStatusBarHeightForRotation[upsideDownRotation] = res.getDimensionPixelSize(
                                 com.android.internal.R.dimen.status_bar_height_portrait);
-        mStatusBarHeightForRotation[mLandscapeRotation] =
-                mStatusBarHeightForRotation[mSeascapeRotation] = res.getDimensionPixelSize(
+        mStatusBarHeightForRotation[landscapeRotation] =
+                mStatusBarHeightForRotation[seascapeRotation] = res.getDimensionPixelSize(
                         com.android.internal.R.dimen.status_bar_height_landscape);
 
         // Height of the navigation bar when presented horizontally at bottom
-        mNavigationBarHeightForRotationDefault[mPortraitRotation] =
-        mNavigationBarHeightForRotationDefault[mUpsideDownRotation] =
+        mNavigationBarHeightForRotationDefault[portraitRotation] =
+        mNavigationBarHeightForRotationDefault[upsideDownRotation] =
                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
-        mNavigationBarHeightForRotationDefault[mLandscapeRotation] =
-        mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize(
+        mNavigationBarHeightForRotationDefault[landscapeRotation] =
+        mNavigationBarHeightForRotationDefault[seascapeRotation] = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.navigation_bar_height_landscape);
 
         // Width of the navigation bar when presented vertically along one side
-        mNavigationBarWidthForRotationDefault[mPortraitRotation] =
-        mNavigationBarWidthForRotationDefault[mUpsideDownRotation] =
-        mNavigationBarWidthForRotationDefault[mLandscapeRotation] =
-        mNavigationBarWidthForRotationDefault[mSeascapeRotation] =
+        mNavigationBarWidthForRotationDefault[portraitRotation] =
+        mNavigationBarWidthForRotationDefault[upsideDownRotation] =
+        mNavigationBarWidthForRotationDefault[landscapeRotation] =
+        mNavigationBarWidthForRotationDefault[seascapeRotation] =
                 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
 
         if (ALTERNATE_CAR_MODE_NAV_SIZE) {
             // Height of the navigation bar when presented horizontally at bottom
-            mNavigationBarHeightForRotationInCarMode[mPortraitRotation] =
-            mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] =
+            mNavigationBarHeightForRotationInCarMode[portraitRotation] =
+            mNavigationBarHeightForRotationInCarMode[upsideDownRotation] =
                     res.getDimensionPixelSize(
                             com.android.internal.R.dimen.navigation_bar_height_car_mode);
-            mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] =
-            mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize(
+            mNavigationBarHeightForRotationInCarMode[landscapeRotation] =
+            mNavigationBarHeightForRotationInCarMode[seascapeRotation] = res.getDimensionPixelSize(
                     com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode);
 
             // Width of the navigation bar when presented vertically along one side
-            mNavigationBarWidthForRotationInCarMode[mPortraitRotation] =
-            mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] =
-            mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] =
-            mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] =
+            mNavigationBarWidthForRotationInCarMode[portraitRotation] =
+            mNavigationBarWidthForRotationInCarMode[upsideDownRotation] =
+            mNavigationBarWidthForRotationInCarMode[landscapeRotation] =
+            mNavigationBarWidthForRotationInCarMode[seascapeRotation] =
                     res.getDimensionPixelSize(
                             com.android.internal.R.dimen.navigation_bar_width_car_mode);
         }
@@ -2948,10 +2624,10 @@
             int displayId, DisplayCutout displayCutout) {
         int width = fullWidth;
         // TODO(multi-display): Support navigation bar on secondary displays.
-        if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
+        if (displayId == DEFAULT_DISPLAY && mDefaultDisplayPolicy.hasNavigationBar()) {
             // For a basic navigation bar, when we are in landscape mode we place
             // the navigation bar to the side.
-            if (mNavigationBarCanMove && fullWidth > fullHeight) {
+            if (mDefaultDisplayPolicy.navigationBarCanMove() && fullWidth > fullHeight) {
                 width -= getNavigationBarWidth(rotation, uiMode);
             }
         }
@@ -2974,10 +2650,10 @@
             int displayId, DisplayCutout displayCutout) {
         int height = fullHeight;
         // TODO(multi-display): Support navigation bar on secondary displays.
-        if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
+        if (displayId == DEFAULT_DISPLAY && mDefaultDisplayPolicy.hasNavigationBar()) {
             // For a basic navigation bar, when we are in portrait mode we place
             // the navigation bar to the bottom.
-            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
+            if (!mDefaultDisplayPolicy.navigationBarCanMove() || fullWidth < fullHeight) {
                 height -= getNavigationBarHeight(rotation, uiMode);
             }
         }
@@ -3065,8 +2741,8 @@
         // In that case, we want to continue hiding the IME until the windows have completed
         // drawing. This way, we know that the IME can be safely shown since the other windows are
         // now shown.
-        final boolean hideIme =
-                win.isInputMethodWindow() && (mAodShowing || !mWindowManagerDrawComplete);
+        final boolean hideIme = win.isInputMethodWindow()
+                && (mAodShowing || !mDefaultDisplayPolicy.isWindowManagerDrawComplete());
         return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
                 || hideDockDivider || hideIme;
     }
@@ -3444,7 +3120,7 @@
     @Override
     public void selectRotationAnimationLw(int anim[]) {
         // If the screen is off or non-interactive, force a jumpcut.
-        final boolean forceJumpcut = !mScreenOnFully || !okToAnimate();
+        final boolean forceJumpcut = !mDefaultDisplayPolicy.isScreenOnFully() || !okToAnimate();
         if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
                 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
                 + (mTopFullscreenOpaqueWindowState == null ?
@@ -3851,7 +3527,7 @@
             // If the device is in VR mode and keys are "internal" (e.g. on the side of the
             // device), then drop the volume keys and don't forward it to the application/dispatch
             // the audio event.
-            if (mPersistentVrModeEnabled) {
+            if (mDefaultDisplayPolicy.isPersistentVrModeEnabled()) {
                 final InputDevice d = event.getDevice();
                 if (d != null && !d.isExternal()) {
                     return -1;
@@ -4941,7 +4617,7 @@
 
     @NavigationBarPosition
     private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
-        if (mNavigationBarCanMove && displayWidth > displayHeight) {
+        if (mDefaultDisplayPolicy.navigationBarCanMove() && displayWidth > displayHeight) {
             if (displayRotation == Surface.ROTATION_270) {
                 return NAV_BAR_LEFT;
             } else {
@@ -5075,7 +4751,7 @@
         mWindowFrames.setParentFrameWasClippedByDisplayCutout(false);
         mWindowFrames.setDisplayCutout(displayFrames.mDisplayCutout);
 
-        final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
+        final boolean hasNavBar = (isDefaultDisplay && mDefaultDisplayPolicy.hasNavigationBar()
                 && mNavigationBar != null && mNavigationBar.isVisibleLw());
 
         final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
@@ -5884,11 +5560,11 @@
     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
         // lid changed state
         final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
-        if (newLidState == mLidState) {
+        if (newLidState == mDefaultDisplayPolicy.getLidState()) {
             return;
         }
 
-        mLidState = newLidState;
+        mDefaultDisplayPolicy.setLidState(newLidState);
         applyLidSwitchState();
         updateRotation(true);
 
@@ -5923,17 +5599,6 @@
         mCameraLensCoverState = lensCoverState;
     }
 
-    void setHdmiPlugged(boolean plugged) {
-        if (mHdmiPlugged != plugged) {
-            mHdmiPlugged = plugged;
-            updateRotation(true, true);
-            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
-            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-        }
-    }
-
     void initializeHdmiState() {
         final int oldMask = StrictMode.allowThreadDiskReadsMask();
         try {
@@ -5973,8 +5638,7 @@
         }
         // This dance forces the code in setHdmiPlugged to run.
         // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
-        mHdmiPlugged = !plugged;
-        setHdmiPlugged(!mHdmiPlugged);
+        mDefaultDisplayPolicy.setHdmiPlugged(plugged, true /* force */);
     }
 
 
@@ -6414,16 +6078,6 @@
     }
 
     /**
-     * Notify the StatusBar that system rotation suggestion has changed.
-     */
-    private void sendProposedRotationChangeToStatusBarInternal(int rotation, boolean isValid) {
-        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
-        if (statusBar != null) {
-            statusBar.onProposedRotationChanged(rotation, isValid);
-        }
-    }
-
-    /**
      * Returns true if the key can have global actions attached to it.
      * We reserve all power management keys for the system since they require
      * very careful handling.
@@ -6452,7 +6106,7 @@
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_DOWN:
             case KeyEvent.KEYCODE_VOLUME_MUTE:
-                return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED;
+                return mDefaultDisplayPolicy.getDockMode() != Intent.EXTRA_DOCK_STATE_UNDOCKED;
 
             // ignore media and camera keys
             case KeyEvent.KEYCODE_MUTE:
@@ -6500,7 +6154,8 @@
     }
 
     private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
-        final boolean displayOff = (mDisplay == null || mDisplay.getState() == STATE_OFF);
+        final boolean displayOff = (mDefaultDisplay == null
+                || mDefaultDisplay.getState() == STATE_OFF);
 
         if (displayOff && !mHasFeatureWatch) {
             return false;
@@ -6650,8 +6305,8 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
-                mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
-                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
+                mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+                        Intent.EXTRA_DOCK_STATE_UNDOCKED));
             } else {
                 try {
                     IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
@@ -6661,9 +6316,7 @@
                 }
             }
             updateRotation(true);
-            synchronized (mLock) {
-                updateOrientationListenerLp();
-            }
+            mDefaultDisplayRotation.updateOrientationListener();
         }
     };
 
@@ -6691,6 +6344,7 @@
                 // and then updates our own bookkeeping based on the now-
                 // current user.
                 mSettingsObserver.onChange(false);
+                mDefaultDisplayRotation.onUserSwitch();
 
                 // force a re-application of focused window sysui visibility.
                 // the window may never have been shown for this user
@@ -6764,15 +6418,16 @@
 
         mGoingToSleep = false;
         mRequestedOrGoingToSleep = false;
+        mDefaultDisplayPolicy.setAwake(false);
 
         // We must get this work done here because the power manager will drop
         // the wake lock and let the system suspend once this function returns.
         synchronized (mLock) {
-            mAwake = false;
             updateWakeGestureListenerLp();
-            updateOrientationListenerLp();
             updateLockScreenTimeout();
         }
+        mDefaultDisplayRotation.updateOrientationListener();
+
         if (mKeyguardDelegate != null) {
             mKeyguardDelegate.onFinishedGoingToSleep(why,
                     mCameraGestureTriggeredDuringGoingToSleep);
@@ -6786,17 +6441,17 @@
         EventLog.writeEvent(70000, 1);
         if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");
 
+        mDefaultDisplayPolicy.setAwake(true);
+
         // Since goToSleep performs these functions synchronously, we must
         // do the same here.  We cannot post this work to a handler because
         // that might cause it to become reordered with respect to what
         // may happen in a future call to goToSleep.
         synchronized (mLock) {
-            mAwake = true;
-
             updateWakeGestureListenerLp();
-            updateOrientationListenerLp();
             updateLockScreenTimeout();
         }
+        mDefaultDisplayRotation.updateOrientationListener();
 
         if (mKeyguardDelegate != null) {
             mKeyguardDelegate.onStartedWakingUp();
@@ -6833,16 +6488,14 @@
     }
 
     private void finishKeyguardDrawn() {
-        synchronized (mLock) {
-            if (!mScreenOnEarly || mKeyguardDrawComplete) {
-                return; // We are not awake yet or we have already informed of this event.
-            }
+        if (!mDefaultDisplayPolicy.finishKeyguardDrawn()) {
+            return;
+        }
 
-            mKeyguardDrawComplete = true;
+        synchronized (mLock) {
             if (mKeyguardDelegate != null) {
                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
             }
-            mWindowManagerDrawComplete = false;
         }
 
         // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
@@ -6857,18 +6510,13 @@
         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
 
         updateScreenOffSleepToken(true);
+        mDefaultDisplayPolicy.screenTurnedOff();
         synchronized (mLock) {
-            mScreenOnEarly = false;
-            mScreenOnFully = false;
-            mKeyguardDrawComplete = false;
-            mWindowManagerDrawComplete = false;
-            mScreenOnListener = null;
-            updateOrientationListenerLp();
-
             if (mKeyguardDelegate != null) {
                 mKeyguardDelegate.onScreenTurnedOff();
             }
         }
+        mDefaultDisplayRotation.updateOrientationListener();
         reportScreenStateToVrManager(false);
     }
 
@@ -6885,13 +6533,9 @@
         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
 
         updateScreenOffSleepToken(false);
-        synchronized (mLock) {
-            mScreenOnEarly = true;
-            mScreenOnFully = false;
-            mKeyguardDrawComplete = false;
-            mWindowManagerDrawComplete = false;
-            mScreenOnListener = screenOnListener;
+        mDefaultDisplayPolicy.screenTurnedOn(screenOnListener);
 
+        synchronized (mLock) {
             if (mKeyguardDelegate != null && mKeyguardDelegate.hasKeyguard()) {
                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
                 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
@@ -6934,46 +6578,29 @@
     }
 
     private void finishWindowsDrawn() {
-        synchronized (mLock) {
-            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
-                return; // Screen is not turned on or we did already handle this case earlier.
-            }
-
-            mWindowManagerDrawComplete = true;
+        if (!mDefaultDisplayPolicy.finishWindowsDrawn()) {
+            return;
         }
 
         finishScreenTurningOn();
     }
 
     private void finishScreenTurningOn() {
-        synchronized (mLock) {
-            // We have just finished drawing screen content. Since the orientation listener
-            // gets only installed when all windows are drawn, we try to install it again.
-            updateOrientationListenerLp();
+        // We have just finished drawing screen content. Since the orientation listener
+        // gets only installed when all windows are drawn, we try to install it again.
+        mDefaultDisplayRotation.updateOrientationListener();
+
+        final ScreenOnListener listener = mDefaultDisplayPolicy.getScreenOnListener();
+        if (!mDefaultDisplayPolicy.finishScreenTurningOn()) {
+            return; // Spurious or not ready yet.
         }
-        final ScreenOnListener listener;
+
         final boolean enableScreen;
+        final boolean awake = mDefaultDisplayPolicy.isAwake();
         synchronized (mLock) {
-            if (DEBUG_WAKEUP) Slog.d(TAG,
-                    "finishScreenTurningOn: mAwake=" + mAwake
-                            + ", mScreenOnEarly=" + mScreenOnEarly
-                            + ", mScreenOnFully=" + mScreenOnFully
-                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
-                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
-
-            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
-                    || (mAwake && !mKeyguardDrawComplete)) {
-                return; // spurious or not ready yet
-            }
-
-            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
-            listener = mScreenOnListener;
-            mScreenOnListener = null;
-            mScreenOnFully = true;
-
             // Remember the first time we draw the keyguard so we know when we're done with
             // the main part of booting and can enable the screen and hide boot messages.
-            if (!mKeyguardDrawnOnce && mAwake) {
+            if (!mKeyguardDrawnOnce && awake) {
                 mKeyguardDrawnOnce = true;
                 enableScreen = true;
                 if (mBootMessageNeedsHiding) {
@@ -7014,14 +6641,12 @@
 
     @Override
     public boolean isScreenOn() {
-        synchronized (mLock) {
-            return mScreenOnEarly;
-        }
+        return mDefaultDisplayPolicy.isScreenOnEarly();
     }
 
     @Override
     public boolean okToAnimate() {
-        return mAwake && !mGoingToSleep;
+        return mDefaultDisplayPolicy.isAwake() && !mGoingToSleep;
     }
 
     /** {@inheritDoc} */
@@ -7131,7 +6756,7 @@
         outInsets.setEmpty();
 
         // Only navigation bar
-        if (mHasNavigationBar) {
+        if (mDefaultDisplayPolicy.hasNavigationBar()) {
             int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);
             if (position == NAV_BAR_BOTTOM) {
                 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
@@ -7165,7 +6790,8 @@
     public boolean isDockSideAllowed(int dockSide, int originalDockSide, int displayWidth,
             int displayHeight, int displayRotation) {
         final int barPosition = navigationBarPosition(displayWidth, displayHeight, displayRotation);
-        return isDockSideAllowed(dockSide, originalDockSide, barPosition, mNavigationBarCanMove);
+        return isDockSideAllowed(dockSide, originalDockSide, barPosition,
+                mDefaultDisplayPolicy.navigationBarCanMove());
     }
 
     @VisibleForTesting
@@ -7202,293 +6828,6 @@
     }
 
     @Override
-    public int rotationForOrientationLw(int orientation, int lastRotation, boolean defaultDisplay) {
-        if (false) {
-            Slog.v(TAG, "rotationForOrientationLw(orient="
-                        + orientation + ", last=" + lastRotation
-                        + "); user=" + mUserRotation + " "
-                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
-                            ? "USER_ROTATION_LOCKED" : "")
-                        );
-        }
-
-        if (mForceDefaultOrientation) {
-            return Surface.ROTATION_0;
-        }
-
-        synchronized (mLock) {
-            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
-            if (sensorRotation < 0) {
-                sensorRotation = lastRotation;
-            }
-
-            final int preferredRotation;
-            if (!defaultDisplay) {
-                // For secondary displays we ignore things like displays sensors, docking mode and
-                // rotation lock, and always prefer a default rotation.
-                preferredRotation = Surface.ROTATION_0;
-            } else if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
-                // Ignore sensor when lid switch is open and rotation is forced.
-                preferredRotation = mLidOpenRotation;
-            } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
-                    && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
-                // Ignore sensor when in car dock unless explicitly enabled.
-                // This case can override the behavior of NOSENSOR, and can also
-                // enable 180 degree rotation while docked.
-                preferredRotation = mCarDockEnablesAccelerometer
-                        ? sensorRotation : mCarDockRotation;
-            } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
-                    || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
-                    || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
-                    && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
-                // Ignore sensor when in desk dock unless explicitly enabled.
-                // This case can override the behavior of NOSENSOR, and can also
-                // enable 180 degree rotation while docked.
-                preferredRotation = mDeskDockEnablesAccelerometer
-                        ? sensorRotation : mDeskDockRotation;
-            } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
-                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
-                // Note that the dock orientation overrides the HDMI orientation.
-                preferredRotation = mDemoHdmiRotation;
-            } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
-                    && mUndockedHdmiRotation >= 0) {
-                // Ignore sensor when plugged into HDMI and an undocked orientation has
-                // been specified in the configuration (only for legacy devices without
-                // full multi-display support).
-                // Note that the dock orientation overrides the HDMI orientation.
-                preferredRotation = mUndockedHdmiRotation;
-            } else if (mDemoRotationLock) {
-                // Ignore sensor when demo rotation lock is enabled.
-                // Note that the dock orientation and HDMI rotation lock override this.
-                preferredRotation = mDemoRotation;
-            } else if (mPersistentVrModeEnabled) {
-                // While in VR, apps always prefer a portrait rotation. This does not change
-                // any apps that explicitly set landscape, but does cause sensors be ignored,
-                // and ignored any orientation lock that the user has set (this conditional
-                // should remain above the ORIENTATION_LOCKED conditional below).
-                preferredRotation = mPortraitRotation;
-            } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
-                // Application just wants to remain locked in the last rotation.
-                preferredRotation = lastRotation;
-            } else if (!mSupportAutoRotation) {
-                // If we don't support auto-rotation then bail out here and ignore
-                // the sensor and any rotation lock settings.
-                preferredRotation = -1;
-            } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
-                            && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
-                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
-                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
-                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
-                                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
-                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
-                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
-                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
-                    || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
-                // Otherwise, use sensor only if requested by the application or enabled
-                // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
-                if (mAllowAllRotations < 0) {
-                    // Can't read this during init() because the context doesn't
-                    // have display metrics at that time so we cannot determine
-                    // tablet vs. phone then.
-                    mAllowAllRotations = mContext.getResources().getBoolean(
-                            com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
-                }
-                if (sensorRotation != Surface.ROTATION_180
-                        || mAllowAllRotations == 1
-                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
-                        || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
-                    preferredRotation = sensorRotation;
-                } else {
-                    preferredRotation = lastRotation;
-                }
-            } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
-                    && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
-                // Apply rotation lock.  Does not apply to NOSENSOR.
-                // The idea is that the user rotation expresses a weak preference for the direction
-                // of gravity and as NOSENSOR is never affected by gravity, then neither should
-                // NOSENSOR be affected by rotation lock (although it will be affected by docks).
-                preferredRotation = mUserRotation;
-            } else {
-                // No overriding preference.
-                // We will do exactly what the application asked us to do.
-                preferredRotation = -1;
-            }
-
-            switch (orientation) {
-                case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
-                    // Return portrait unless overridden.
-                    if (isAnyPortrait(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    return mPortraitRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
-                    // Return landscape unless overridden.
-                    if (isLandscapeOrSeascape(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    return mLandscapeRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
-                    // Return reverse portrait unless overridden.
-                    if (isAnyPortrait(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    return mUpsideDownRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
-                    // Return seascape unless overridden.
-                    if (isLandscapeOrSeascape(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    return mSeascapeRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
-                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
-                    // Return either landscape rotation.
-                    if (isLandscapeOrSeascape(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    if (isLandscapeOrSeascape(lastRotation)) {
-                        return lastRotation;
-                    }
-                    return mLandscapeRotation;
-
-                case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
-                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
-                    // Return either portrait rotation.
-                    if (isAnyPortrait(preferredRotation)) {
-                        return preferredRotation;
-                    }
-                    if (isAnyPortrait(lastRotation)) {
-                        return lastRotation;
-                    }
-                    return mPortraitRotation;
-
-                default:
-                    // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
-                    // just return the preferred orientation we already calculated.
-                    if (preferredRotation >= 0) {
-                        return preferredRotation;
-                    }
-                    return Surface.ROTATION_0;
-            }
-        }
-    }
-
-    @Override
-    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
-        switch (orientation) {
-            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
-            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
-            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
-                return isAnyPortrait(rotation);
-
-            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
-            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
-            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
-                return isLandscapeOrSeascape(rotation);
-
-            default:
-                return true;
-        }
-    }
-
-    @Override
-    public void setRotationLw(int rotation) {
-        mOrientationListener.setCurrentRotation(rotation);
-    }
-
-    public boolean isRotationChoicePossible(int orientation) {
-        // Rotation choice is only shown when the user is in locked mode.
-        if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
-
-        // We should only enable rotation choice if the rotation isn't forced by the lid, dock,
-        // demo, hdmi, vr, etc mode
-
-        // Determine if the rotation is currently forced
-        if (mForceDefaultOrientation) {
-            return false; // Rotation is forced to default orientation
-
-        } else if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
-            return false; // Rotation is forced mLidOpenRotation
-
-        } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && !mCarDockEnablesAccelerometer) {
-            return false; // Rotation forced to mCarDockRotation
-
-        } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
-                || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
-                || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
-                && !mDeskDockEnablesAccelerometer) {
-            return false; // Rotation forced to mDeskDockRotation
-
-        } else if (mHdmiPlugged && mDemoHdmiRotationLock) {
-            return false; // Rotation forced to mDemoHdmiRotation
-
-        } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
-                && mUndockedHdmiRotation >= 0) {
-            return false; // Rotation forced to mUndockedHdmiRotation
-
-        } else if (mDemoRotationLock) {
-            return false; // Rotation forced to mDemoRotation
-
-        } else if (mPersistentVrModeEnabled) {
-            return false; // Rotation forced to mPortraitRotation
-
-        } else if (!mSupportAutoRotation) {
-            return false;
-        }
-
-        // Ensure that some rotation choice is possible for the given orientation
-        switch (orientation) {
-            case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
-            case ActivityInfo.SCREEN_ORIENTATION_USER:
-            case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
-            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
-            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
-                // NOSENSOR description is ambiguous, in reality WM ignores user choice
-                return true;
-        }
-
-        // Rotation is forced, should be controlled by system
-        return false;
-    }
-
-    public boolean isValidRotationChoice(int orientation, final int preferredRotation) {
-        // Determine if the given app orientation is compatible with the provided rotation choice
-        switch (orientation) {
-            case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
-                // Works with any of the 4 rotations
-                return preferredRotation >= 0;
-
-            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
-                // It's possible for the user pref to be set at 180 because of FULL_USER. This would
-                // make switching to USER_PORTRAIT appear at 180. Provide choice to back to portrait
-                // but never to go to 180.
-                return preferredRotation == mPortraitRotation;
-
-            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
-                // Works landscape or seascape
-                return isLandscapeOrSeascape(preferredRotation);
-
-            case ActivityInfo.SCREEN_ORIENTATION_USER:
-            case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
-                // Works with any rotation except upside down
-                return (preferredRotation >= 0) && (preferredRotation != mUpsideDownRotation);
-        }
-
-        return false;
-    }
-
-    private boolean isLandscapeOrSeascape(int rotation) {
-        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
-    }
-
-    private boolean isAnyPortrait(int rotation) {
-        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
-    }
-
-    @Override
     public int getUserRotationMode() {
         return Settings.System.getIntForUser(mContext.getContentResolver(),
                 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ?
@@ -7560,8 +6899,8 @@
 
         readCameraLensCoverState();
         updateUiMode();
+        mDefaultDisplayRotation.updateOrientationListener();
         synchronized (mLock) {
-            updateOrientationListenerLp();
             mSystemReady = true;
             mHandler.post(new Runnable() {
                 @Override
@@ -7599,9 +6938,7 @@
 
     @Override
     public boolean canDismissBootAnimation() {
-        synchronized (mLock) {
-            return mKeyguardDrawComplete;
-        }
+        return mDefaultDisplayPolicy.isKeyguardDrawComplete();
     }
 
     ProgressDialog mBootMsgDialog = null;
@@ -7701,7 +7038,7 @@
             }
         }
 
-        if (mAwake && mNotifyUserActivity) {
+        if (mDefaultDisplayPolicy.isAwake() && mNotifyUserActivity) {
             mHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
                     USER_ACTIVITY_NOTIFICATION_DELAY);
             mNotifyUserActivity = false;
@@ -7744,7 +7081,7 @@
 
     private void updateLockScreenTimeout() {
         synchronized (mScreenLockTimeout) {
-            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
+            final boolean enable = (mAllowLockscreenWhenOn && mDefaultDisplayPolicy.isAwake() &&
                     mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId));
             if (mLockScreenTimerActive != enable) {
                 if (enable) {
@@ -7799,10 +7136,11 @@
     }
 
     private void applyLidSwitchState() {
-        if (mLidState == LID_CLOSED && mLidControlsSleep) {
+        final int lidState = mDefaultDisplayPolicy.getLidState();
+        if (lidState == LID_CLOSED && mLidControlsSleep) {
             goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
                     PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
-        } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) {
+        } else if (lidState == LID_CLOSED && mLidControlsScreenLock) {
             mWindowManagerFuncs.lockDeviceNow();
         }
 
@@ -7824,17 +7162,8 @@
 
     void updateRotation(boolean alwaysSendConfiguration) {
         try {
-            //set orientation on WindowManager
-            mWindowManager.updateRotation(alwaysSendConfiguration, false);
-        } catch (RemoteException e) {
-            // Ignore
-        }
-    }
-
-    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
-        try {
-            //set orientation on WindowManager
-            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
+            // Set orientation on WindowManager.
+            mWindowManager.updateRotation(alwaysSendConfiguration, false /* forceRelayout */);
         } catch (RemoteException e) {
             // Ignore
         }
@@ -7867,12 +7196,14 @@
             if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
                 intent = mDeskDockIntent;
             }
-        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH
-                && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
-                        || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
-                        || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) {
-            // Always launch dock home from home when watch is docked, if it exists.
-            intent = mDeskDockIntent;
+        } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH) {
+            final int dockMode = mDefaultDisplayPolicy.getDockMode();
+            if (dockMode == Intent.EXTRA_DOCK_STATE_DESK
+                    || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK
+                    || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK) {
+                // Always launch dock home from home when watch is docked, if it exists.
+                intent = mDeskDockIntent;
+            }
         } else if (mUiMode == Configuration.UI_MODE_TYPE_VR_HEADSET) {
             if (ENABLE_VR_HEADSET_HOME_CAPTURE) {
                 intent = mVrHeadsetHomeIntent;
@@ -7987,16 +7318,6 @@
         return true;
     }
 
-    @Override
-    public void setCurrentOrientationLw(int newOrientation) {
-        synchronized (mLock) {
-            if (newOrientation != mCurrentAppOrientation) {
-                mCurrentAppOrientation = newOrientation;
-                updateOrientationListenerLp();
-            }
-        }
-    }
-
     private boolean isTheaterModeEnabled() {
         return Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.THEATER_MODE_ON, 0) == 1;
@@ -8323,7 +7644,8 @@
         final long now = SystemClock.uptimeMillis();
         final boolean pendingPanic = mPendingPanicGestureUptime != 0
                 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
-        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) {
+        if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard()
+                && mDefaultDisplayPolicy.isKeyguardDrawComplete()) {
             // The user performed the panic gesture recently, we're about to hide the bars,
             // we're no longer on the Keyguard and the screen is ready. We can now request the bars.
             mPendingPanicGestureUptime = 0;
@@ -8466,7 +7788,7 @@
     // overridden by qemu.hw.mainkeys in the emulator.
     @Override
     public boolean hasNavigationBar() {
-        return mHasNavigationBar;
+        return mDefaultDisplayPolicy.hasNavigationBar();
     }
 
     @Override
@@ -8511,19 +7833,21 @@
     }
 
     @Override
-    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
+    public boolean shouldRotateSeamlessly(DisplayRotation displayRotation, int oldRotation,
+            int newRotation) {
         // For the upside down rotation we don't rotate seamlessly as the navigation
         // bar moves position.
         // Note most apps (using orientation:sensor or user as opposed to fullSensor)
         // will not enter the reverse portrait orientation, so actually the
         // orientation won't change at all.
-        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
+        if (oldRotation == displayRotation.getUpsideDownRotation()
+                || newRotation == displayRotation.getUpsideDownRotation()) {
             return false;
         }
         // If the navigation bar can't change sides, then it will
         // jump when we change orientations and we don't rotate
         // seamlessly.
-        if (!mNavigationBarCanMove) {
+        if (!displayRotation.getDisplayPolicy().navigationBarCanMove()) {
             return false;
         }
         int delta = newRotation - oldRotation;
@@ -8557,12 +7881,13 @@
     public void writeToProto(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         proto.write(LAST_SYSTEM_UI_FLAGS, mLastSystemUiFlags);
-        proto.write(ROTATION_MODE, mUserRotationMode);
-        proto.write(ROTATION, mUserRotation);
-        proto.write(ORIENTATION, mCurrentAppOrientation);
-        proto.write(SCREEN_ON_FULLY, mScreenOnFully);
-        proto.write(KEYGUARD_DRAW_COMPLETE, mKeyguardDrawComplete);
-        proto.write(WINDOW_MANAGER_DRAW_COMPLETE, mWindowManagerDrawComplete);
+        proto.write(ROTATION_MODE, mDefaultDisplayRotation.getUserRotationMode());
+        proto.write(ROTATION, mDefaultDisplayRotation.getUserRotation());
+        proto.write(ORIENTATION, mDefaultDisplayRotation.getCurrentAppOrientation());
+        proto.write(SCREEN_ON_FULLY, mDefaultDisplayPolicy.isScreenOnFully());
+        proto.write(KEYGUARD_DRAW_COMPLETE, mDefaultDisplayPolicy.isKeyguardDrawComplete());
+        proto.write(WINDOW_MANAGER_DRAW_COMPLETE,
+                mDefaultDisplayPolicy.isWindowManagerDrawComplete());
         if (mFocusedApp != null) {
             proto.write(FOCUSED_APP_TOKEN, mFocusedApp.toString());
         }
@@ -8584,8 +7909,8 @@
         proto.write(FORCE_STATUS_BAR_FROM_KEYGUARD, mForceStatusBarFromKeyguard);
         mStatusBarController.writeToProto(proto, STATUS_BAR);
         mNavigationBarController.writeToProto(proto, NAVIGATION_BAR);
-        if (mOrientationListener != null) {
-            mOrientationListener.writeToProto(proto, ORIENTATION_LISTENER);
+        if (mDefaultOrientationListener != null) {
+            mDefaultOrientationListener.writeToProto(proto, ORIENTATION_LISTENER);
         }
         if (mKeyguardDelegate != null) {
             mKeyguardDelegate.writeToProto(proto, KEYGUARD_DELEGATE);
@@ -8598,13 +7923,8 @@
         pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
                 pw.print(" mSystemReady="); pw.print(mSystemReady);
                 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
-        pw.print(prefix); pw.print("mLidState=");
-                pw.print(WindowManagerFuncs.lidStateToString(mLidState));
-                pw.print(" mLidOpenRotation=");
-                pw.println(Surface.rotationToString(mLidOpenRotation));
         pw.print(prefix); pw.print("mCameraLensCoverState=");
-                pw.print(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState));
-                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
+                pw.println(WindowManagerFuncs.cameraLensStateToString(mCameraLensCoverState));
         if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
                 || mForceClearedSystemUiFlags != 0) {
             pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
@@ -8622,27 +7942,9 @@
                 pw.println(mWakeGestureEnabledSetting);
 
         pw.print(prefix);
-                pw.print("mSupportAutoRotation="); pw.print(mSupportAutoRotation);
-                pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled);
-        pw.print(prefix); pw.print("mUiMode="); pw.print(Configuration.uiModeToString(mUiMode));
-                pw.print(" mDockMode="); pw.println(Intent.dockStateToString(mDockMode));
-        pw.print(prefix); pw.print("mEnableCarDockHomeCapture=");
-                pw.print(mEnableCarDockHomeCapture);
-                pw.print(" mCarDockRotation=");
-                pw.print(Surface.rotationToString(mCarDockRotation));
-                pw.print(" mDeskDockRotation=");
-                pw.println(Surface.rotationToString(mDeskDockRotation));
-        pw.print(prefix); pw.print("mUserRotationMode=");
-                pw.print(WindowManagerPolicy.userRotationModeToString(mUserRotationMode));
-                pw.print(" mUserRotation="); pw.print(Surface.rotationToString(mUserRotation));
-                pw.print(" mAllowAllRotations=");
-                pw.println(allowAllRotationsToString(mAllowAllRotations));
-        pw.print(prefix); pw.print("mCurrentAppOrientation=");
-                pw.println(ActivityInfo.screenOrientationToString(mCurrentAppOrientation));
-        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
-                pw.print(mCarDockEnablesAccelerometer);
-                pw.print(" mDeskDockEnablesAccelerometer=");
-                pw.println(mDeskDockEnablesAccelerometer);
+                pw.print("mUiMode=");
+                pw.print(Configuration.uiModeToString(mUiMode));
+                pw.print("mEnableCarDockHomeCapture="); pw.println(mEnableCarDockHomeCapture);
         pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
                 pw.print(mLidKeyboardAccessibility);
                 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
@@ -8692,12 +7994,6 @@
                 pw.print(" mEndcallBehavior=");
                 pw.println(endcallBehaviorToString(mEndcallBehavior));
         pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
-        pw.print(prefix);
-                pw.print("mAwake="); pw.print(mAwake);
-                pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
-                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
-        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
-                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
         pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
                 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
         pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
@@ -8752,19 +8048,6 @@
         pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
                 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
                 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
-        pw.print(prefix); pw.print("mLandscapeRotation=");
-                pw.print(Surface.rotationToString(mLandscapeRotation));
-                pw.print(" mSeascapeRotation=");
-                pw.println(Surface.rotationToString(mSeascapeRotation));
-        pw.print(prefix); pw.print("mPortraitRotation=");
-                pw.print(Surface.rotationToString(mPortraitRotation));
-                pw.print(" mUpsideDownRotation=");
-                pw.println(Surface.rotationToString(mUpsideDownRotation));
-        pw.print(prefix); pw.print("mDemoHdmiRotation=");
-                pw.print(Surface.rotationToString(mDemoHdmiRotation));
-                pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
-        pw.print(prefix); pw.print("mUndockedHdmiRotation=");
-                pw.println(Surface.rotationToString(mUndockedHdmiRotation));
         if (mHasFeatureLeanback) {
             pw.print(prefix);
             pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed);
@@ -8782,8 +8065,8 @@
         if (mWakeGestureListener != null) {
             mWakeGestureListener.dump(pw, prefix);
         }
-        if (mOrientationListener != null) {
-            mOrientationListener.dump(pw, prefix);
+        if (mDefaultOrientationListener != null) {
+            mDefaultOrientationListener.dump(pw, prefix);
         }
         if (mBurnInProtectionHelper != null) {
             mBurnInProtectionHelper.dump(prefix, pw);
@@ -8796,19 +8079,6 @@
         mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + "  ");
     }
 
-    private static String allowAllRotationsToString(int allowAll) {
-        switch (allowAll) {
-            case -1:
-                return "unknown";
-            case 0:
-                return "false";
-            case 1:
-                return "true";
-            default:
-                return Integer.toString(allowAll);
-        }
-    }
-
     private static String endcallBehaviorToString(int behavior) {
         StringBuilder sb = new StringBuilder();
         if ((behavior & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0 ) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 0060328..cc39217 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -93,6 +93,7 @@
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
 import com.android.server.wm.DisplayFrames;
+import com.android.server.wm.DisplayRotation;
 import com.android.server.wm.WindowFrames;
 import com.android.server.wm.utils.WmDisplayCutout;
 
@@ -177,7 +178,7 @@
     /**
      * Called when the resource overlays change.
      */
-    default void onOverlayChangedLw() {}
+    default void onOverlayChangedLw(DisplayContentInfo displayContentInfo) {}
 
     /**
      * Interface to the Window Manager state associated with a particular
@@ -638,6 +639,27 @@
          * The keyguard showing state has changed
          */
         void onKeyguardShowingAndNotOccludedChanged();
+
+        DisplayContentInfo getDefaultDisplayContentInfo();
+    }
+
+    /**
+     * Provides the rotation of a device.
+     *
+     * @see com.android.server.policy.WindowOrientationListener
+     */
+    public interface RotationSource {
+        int getProposedRotation();
+
+        void setCurrentRotation(int rotation);
+    }
+
+    /**
+     * Interface to get public information of a display content.
+     */
+    public interface DisplayContentInfo {
+        DisplayRotation getDisplayRotation();
+        Display getDisplay();
     }
 
     /** Window has been added to the screen. */
@@ -669,6 +691,11 @@
     public final int USER_ROTATION_LOCKED = 1;
 
     /**
+     * Set the default display content to provide basic functions for the policy.
+     */
+    public void setDefaultDisplay(DisplayContentInfo displayContentInfo);
+
+    /**
      * Perform initialization of the policy.
      *
      * @param context The system context we are running in.
@@ -677,17 +704,6 @@
             WindowManagerFuncs windowManagerFuncs);
 
     /**
-     * @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true.
-     */
-    public boolean isDefaultOrientationForced();
-
-    /**
-     * Called by window manager once it has the initial, default native
-     * display dimensions.
-     */
-    public void setInitialDisplaySize(Display display, int width, int height, int density);
-
-    /**
      * Check permissions when adding a window.
      *
      * @param attrs The window's LayoutParams.
@@ -1410,44 +1426,6 @@
     public boolean isShowingDreamLw();
 
     /**
-     * Given an orientation constant, returns the appropriate surface rotation,
-     * taking into account sensors, docking mode, rotation lock, and other factors.
-     *
-     * @param orientation An orientation constant, such as
-     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
-     * @param lastRotation The most recently used rotation.
-     * @param defaultDisplay Flag indicating whether the rotation is computed for the default
-     *                       display. Currently for all non-default displays sensors, docking mode,
-     *                       rotation lock and other factors are ignored.
-     * @return The surface rotation to use.
-     */
-    public int rotationForOrientationLw(@ActivityInfo.ScreenOrientation int orientation,
-            int lastRotation, boolean defaultDisplay);
-
-    /**
-     * Given an orientation constant and a rotation, returns true if the rotation
-     * has compatible metrics to the requested orientation.  For example, if
-     * the application requested landscape and got seascape, then the rotation
-     * has compatible metrics; if the application requested portrait and got landscape,
-     * then the rotation has incompatible metrics; if the application did not specify
-     * a preference, then anything goes.
-     *
-     * @param orientation An orientation constant, such as
-     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
-     * @param rotation The rotation to check.
-     * @return True if the rotation is compatible with the requested orientation.
-     */
-    public boolean rotationHasCompatibleMetricsLw(@ActivityInfo.ScreenOrientation int orientation,
-            int rotation);
-
-    /**
-     * Called by the window manager when the rotation changes.
-     *
-     * @param rotation The new rotation.
-     */
-    public void setRotationLw(int rotation);
-
-    /**
      * Called when the system is mostly done booting to set whether
      * the system should go into safe mode.
      */
@@ -1487,8 +1465,6 @@
      */
     public void enableScreenAfterBoot();
 
-    public void setCurrentOrientationLw(@ActivityInfo.ScreenOrientation int newOrientation);
-
     /**
      * Call from application to perform haptic feedback on its window.
      */
@@ -1702,9 +1678,10 @@
     /**
      * Called when the configuration has changed, and it's safe to load new values from resources.
      */
-    public void onConfigurationChanged();
+    public void onConfigurationChanged(DisplayContentInfo displayContentInfo);
 
-    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation);
+    public boolean shouldRotateSeamlessly(DisplayRotation displayRotation,
+            int oldRotation, int newRotation);
 
     /**
      * Called when System UI has been started.
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index 1508c9e..d5adb5e 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -204,6 +204,10 @@
         }
     }
 
+    public Handler getHandler() {
+        return mHandler;
+    }
+
     /**
      * Sets the current rotation.
      *
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index d6ccf3b..556038f 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -328,6 +328,7 @@
                             PackageManager pm = context.getPackageManager();
                             String app = intent.getData().getSchemeSpecificPart();
                             sStatsd.informOnePackageRemoved(app, uid);
+                            StatsLog.write(StatsLog.GENERIC_ATOM, uid, 1000);
                         }
                     } else {
                         PackageManager pm = context.getPackageManager();
@@ -336,6 +337,7 @@
                         String app = intent.getData().getSchemeSpecificPart();
                         PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
                         sStatsd.informOnePackage(app, uid, pi.getLongVersionCode());
+                        StatsLog.write(StatsLog.GENERIC_ATOM, uid, 1001);
                     }
                 } catch (Exception e) {
                     Slog.w(TAG, "Failed to inform statsd of an app update", e);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 738b0ca..519881e 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -547,50 +547,50 @@
     }
 
     @Override
-    public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
+    public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
         if (mBar != null) {
             try {
-                mBar.showFingerprintDialog(bundle, receiver);
+                mBar.showBiometricDialog(bundle, receiver);
             } catch (RemoteException ex) {
             }
         }
     }
 
     @Override
-    public void onFingerprintAuthenticated() {
+    public void onBiometricAuthenticated() {
         if (mBar != null) {
             try {
-                mBar.onFingerprintAuthenticated();
+                mBar.onBiometricAuthenticated();
             } catch (RemoteException ex) {
             }
         }
     }
 
     @Override
-    public void onFingerprintHelp(String message) {
+    public void onBiometricHelp(String message) {
         if (mBar != null) {
             try {
-                mBar.onFingerprintHelp(message);
+                mBar.onBiometricHelp(message);
             } catch (RemoteException ex) {
             }
         }
     }
 
     @Override
-    public void onFingerprintError(String error) {
+    public void onBiometricError(String error) {
         if (mBar != null) {
             try {
-                mBar.onFingerprintError(error);
+                mBar.onBiometricError(error);
             } catch (RemoteException ex) {
             }
         }
     }
 
     @Override
-    public void hideFingerprintDialog() {
+    public void hideBiometricDialog() {
         if (mBar != null) {
             try {
-                mBar.hideFingerprintDialog();
+                mBar.hideBiometricDialog();
             } catch (RemoteException ex) {
             }
         }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 218fcb7..d7d5cf8 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -173,7 +173,8 @@
  * IMPORTANT: No method from this class should ever be used without holding
  * WindowManagerService.mWindowMap.
  */
-class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
+class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer>
+        implements WindowManagerPolicy.DisplayContentInfo {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
 
     /** Unique identifier of this stack. */
@@ -234,6 +235,8 @@
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
     private final Display mDisplay;
     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+    private final DisplayPolicy mDisplayPolicy;
+    private DisplayRotation mDisplayRotation;
     DisplayFrames mDisplayFrames;
 
     /**
@@ -304,8 +307,11 @@
     private boolean mLayoutNeeded;
     int pendingLayoutChanges;
     int mDeferredRotationPauseCount;
+
     // TODO(multi-display): remove some of the usages.
+    @VisibleForTesting
     boolean isDefaultDisplay;
+
     /**
      * Flag indicating whether WindowManager should override info for this display in
      * DisplayManager.
@@ -762,6 +768,13 @@
         mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
         initializeDisplayBaseInfo();
+        mDisplayPolicy = new DisplayPolicy(service);
+        mDisplayRotation = new DisplayRotation(service, this);
+        if (isDefaultDisplay) {
+            // The policy may be invoked right after here, so it requires the necessary default
+            // fields of this display content.
+            mService.mPolicy.setDefaultDisplay(this);
+        }
         mDividerControllerLocked = new DockedStackDividerController(service, this);
         mPinnedStackControllerLocked = new PinnedStackController(service, this);
 
@@ -801,7 +814,9 @@
         // {@link DisplayContent} ready for use.
         mDisplayReady = true;
 
-        mInputMonitor = new InputMonitor(service, mDisplayId);
+        // TODO(b/112081256): Use independent InputMonitor.
+        mInputMonitor = isDefaultDisplay ? new InputMonitor(service, mDisplayId)
+                : mService.getDefaultDisplayContentLocked().mInputMonitor;
     }
 
     boolean isReady() {
@@ -905,7 +920,8 @@
         appToken.onRemovedFromDisplay();
     }
 
-    Display getDisplay() {
+    @Override
+    public Display getDisplay() {
         return mDisplay;
     }
 
@@ -917,6 +933,20 @@
         return mDisplayMetrics;
     }
 
+    DisplayPolicy getDisplayPolicy() {
+        return mDisplayPolicy;
+    }
+
+    @Override
+    public DisplayRotation getDisplayRotation() {
+        return mDisplayRotation;
+    }
+
+    @VisibleForTesting
+    void setDisplayRotation(DisplayRotation displayRotation) {
+        mDisplayRotation = displayRotation;
+    }
+
     int getRotation() {
         return mRotation;
     }
@@ -924,6 +954,7 @@
     @VisibleForTesting
     void setRotation(int newRotation) {
         mRotation = newRotation;
+        mDisplayRotation.setRotation(newRotation);
     }
 
     int getLastOrientation() {
@@ -969,14 +1000,45 @@
 
         mDeferredRotationPauseCount--;
         if (mDeferredRotationPauseCount == 0) {
-            final boolean changed = updateRotationUnchecked();
-            if (changed) {
-                mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
-            }
+            updateRotationAndSendNewConfigIfNeeded();
         }
     }
 
     /**
+     * If this is true we have updated our desired orientation, but not yet changed the real
+     * orientation our applied our screen rotation animation. For example, because a previous
+     * screen rotation was in progress.
+     *
+     * @return {@code true} if the there is an ongoing rotation change.
+     */
+    boolean rotationNeedsUpdate() {
+        final int lastOrientation = getLastOrientation();
+        final int oldRotation = getRotation();
+        final boolean oldAltOrientation = getAltOrientation();
+
+        final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
+        final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
+                lastOrientation, rotation);
+        if (oldRotation == rotation && oldAltOrientation == altOrientation) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Update rotation of the display and send configuration if the rotation is changed.
+     *
+     * @return {@code true} if the rotation has been changed and the new config is sent.
+     */
+    boolean updateRotationAndSendNewConfigIfNeeded() {
+        final boolean changed = updateRotationUnchecked(false /* forceUpdate */);
+        if (changed) {
+            mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
+        }
+        return changed;
+    }
+
+    /**
      * Update rotation of the display.
      *
      * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
@@ -1034,13 +1096,12 @@
         final int oldRotation = mRotation;
         final int lastOrientation = mLastOrientation;
         final boolean oldAltOrientation = mAltOrientation;
-        final int rotation = mService.mPolicy.rotationForOrientationLw(lastOrientation, oldRotation,
-                isDefaultDisplay);
+        final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id="
                 + mDisplayId + " based on lastOrientation=" + lastOrientation
                 + " and oldRotation=" + oldRotation);
-        boolean mayRotateSeamlessly = mService.mPolicy.shouldRotateSeamlessly(oldRotation,
-                rotation);
+        boolean mayRotateSeamlessly = mService.mPolicy.shouldRotateSeamlessly(mDisplayRotation,
+                oldRotation, rotation);
 
         if (mayRotateSeamlessly) {
             final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated);
@@ -1071,7 +1132,7 @@
         //       an orientation that has different metrics than it expected.
         //       eg. Portrait instead of Landscape.
 
-        final boolean altOrientation = !mService.mPolicy.rotationHasCompatibleMetricsLw(
+        final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
                 lastOrientation, rotation);
 
         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
@@ -1093,11 +1154,8 @@
             mService.mWaitingForConfig = true;
         }
 
-        mRotation = rotation;
+        setRotation(rotation);
         mAltOrientation = altOrientation;
-        if (isDefaultDisplay) {
-            mService.mPolicy.setRotationLw(rotation);
-        }
 
         mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
         mService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
@@ -1191,8 +1249,23 @@
     }
 
     void configureDisplayPolicy() {
-        mService.mPolicy.setInitialDisplaySize(getDisplay(),
-                mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity);
+        final int width = mBaseDisplayWidth;
+        final int height = mBaseDisplayHeight;
+        final int shortSize;
+        final int longSize;
+        if (width > height) {
+            shortSize = height;
+            longSize = width;
+        } else {
+            shortSize = width;
+            longSize = height;
+        }
+
+        final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
+        final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
+
+        mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
+        mDisplayPolicy.configure(width, height, shortSizeDp);
 
         mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
@@ -2367,6 +2440,10 @@
         pw.println();
         mDisplayFrames.dump(prefix, pw);
         pw.println();
+        mDisplayPolicy.dump(prefix, pw);
+        pw.println();
+        mDisplayRotation.dump(prefix, pw);
+        pw.println();
         mInputMonitor.dump(pw, "  ");
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
new file mode 100644
index 0000000..9151ddf
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -0,0 +1,260 @@
+/*
+ * 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.wm;
+
+import static android.view.WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED;
+import static android.view.WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.content.Intent;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
+import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
+
+import java.io.PrintWriter;
+
+/**
+ * The policy that provides the basic behaviors and states of a display to show UI.
+ */
+public class DisplayPolicy {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayPolicy" : TAG_WM;
+
+    private final WindowManagerService mService;
+    private final Object mLock;
+
+    private final boolean mCarDockEnablesAccelerometer;
+    private final boolean mDeskDockEnablesAccelerometer;
+
+    private volatile int mLidState = LID_ABSENT;
+    private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+    private volatile boolean mHdmiPlugged;
+
+    private volatile boolean mHasNavigationBar;
+    // Can the navigation bar ever move to the side?
+    private volatile boolean mNavigationBarCanMove;
+
+    // Written by vr manager thread, only read in this class.
+    private volatile boolean mPersistentVrModeEnabled;
+
+    private volatile boolean mAwake;
+    private volatile boolean mScreenOnEarly;
+    private volatile boolean mScreenOnFully;
+    private volatile ScreenOnListener mScreenOnListener;
+
+    private volatile boolean mKeyguardDrawComplete;
+    private volatile boolean mWindowManagerDrawComplete;
+
+    DisplayPolicy(WindowManagerService service) {
+        mService = service;
+        mLock = service.getWindowManagerLock();
+        mCarDockEnablesAccelerometer = service.mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
+        mDeskDockEnablesAccelerometer = service.mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
+    }
+
+    void configure(int width, int height, int shortSizeDp) {
+        // Allow the navigation bar to move on non-square small devices (phones).
+        mNavigationBarCanMove = width != height && shortSizeDp < 600;
+
+        mHasNavigationBar = mService.mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_showNavigationBar);
+
+        // Allow a system property to override this. Used by the emulator.
+        // See also hasNavigationBar().
+        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
+        if ("1".equals(navBarOverride)) {
+            mHasNavigationBar = false;
+        } else if ("0".equals(navBarOverride)) {
+            mHasNavigationBar = true;
+        }
+    }
+
+    public void setHdmiPlugged(boolean plugged) {
+        setHdmiPlugged(plugged, false /* force */);
+    }
+
+    public void setHdmiPlugged(boolean plugged, boolean force) {
+        if (force || mHdmiPlugged != plugged) {
+            mHdmiPlugged = plugged;
+            mService.updateRotation(true /* alwaysSendConfiguration */, true /* forceRelayout */);
+            final Intent intent = new Intent(ACTION_HDMI_PLUGGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
+            mService.mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+        }
+    }
+
+    boolean isHdmiPlugged() {
+        return mHdmiPlugged;
+    }
+
+    boolean isCarDockEnablesAccelerometer() {
+        return mCarDockEnablesAccelerometer;
+    }
+
+    boolean isDeskDockEnablesAccelerometer() {
+        return mDeskDockEnablesAccelerometer;
+    }
+
+    public void setPersistentVrModeEnabled(boolean persistentVrModeEnabled) {
+        mPersistentVrModeEnabled = persistentVrModeEnabled;
+    }
+
+    public boolean isPersistentVrModeEnabled() {
+        return mPersistentVrModeEnabled;
+    }
+
+    public void setDockMode(int dockMode) {
+        mDockMode = dockMode;
+    }
+
+    public int getDockMode() {
+        return mDockMode;
+    }
+
+    public boolean hasNavigationBar() {
+        return mHasNavigationBar;
+    }
+
+    public boolean navigationBarCanMove() {
+        return mNavigationBarCanMove;
+    }
+
+    public void setLidState(int lidState) {
+        mLidState = lidState;
+    }
+
+    public int getLidState() {
+        return mLidState;
+    }
+
+    public void setAwake(boolean awake) {
+        mAwake = awake;
+    }
+
+    public boolean isAwake() {
+        return mAwake;
+    }
+
+    public boolean isScreenOnEarly() {
+        return mScreenOnEarly;
+    }
+
+    public boolean isScreenOnFully() {
+        return mScreenOnFully;
+    }
+
+    public boolean isKeyguardDrawComplete() {
+        return mKeyguardDrawComplete;
+    }
+
+    public boolean isWindowManagerDrawComplete() {
+        return mWindowManagerDrawComplete;
+    }
+
+    public ScreenOnListener getScreenOnListener() {
+        return mScreenOnListener;
+    }
+
+    public void screenTurnedOn(ScreenOnListener screenOnListener) {
+        synchronized (mLock) {
+            mScreenOnEarly = true;
+            mScreenOnFully = false;
+            mKeyguardDrawComplete = false;
+            mWindowManagerDrawComplete = false;
+            mScreenOnListener = screenOnListener;
+        }
+    }
+
+    public void screenTurnedOff() {
+        synchronized (mLock) {
+            mScreenOnEarly = false;
+            mScreenOnFully = false;
+            mKeyguardDrawComplete = false;
+            mWindowManagerDrawComplete = false;
+            mScreenOnListener = null;
+        }
+    }
+
+    /** Return false if we are not awake yet or we have already informed of this event. */
+    public boolean finishKeyguardDrawn() {
+        synchronized (mLock) {
+            if (!mScreenOnEarly || mKeyguardDrawComplete) {
+                return false;
+            }
+
+            mKeyguardDrawComplete = true;
+            mWindowManagerDrawComplete = false;
+        }
+        return true;
+    }
+
+    /** Return false if screen is not turned on or we did already handle this case earlier. */
+    public boolean finishWindowsDrawn() {
+        synchronized (mLock) {
+            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
+                return false;
+            }
+
+            mWindowManagerDrawComplete = true;
+        }
+        return true;
+    }
+
+    /** Return false if it is not ready to turn on. */
+    public boolean finishScreenTurningOn() {
+        synchronized (mLock) {
+            if (DEBUG_SCREEN_ON) Slog.d(TAG,
+                    "finishScreenTurningOn: mAwake=" + mAwake
+                            + ", mScreenOnEarly=" + mScreenOnEarly
+                            + ", mScreenOnFully=" + mScreenOnFully
+                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
+                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+
+            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
+                    || (mAwake && !mKeyguardDrawComplete)) {
+                return false;
+            }
+
+            if (DEBUG_SCREEN_ON) Slog.i(TAG, "Finished screen turning on...");
+            mScreenOnListener = null;
+            mScreenOnFully = true;
+        }
+        return true;
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        pw.println(prefix + "DisplayPolicy");
+        pw.print(prefix + "  mCarDockEnablesAccelerometer=" + mCarDockEnablesAccelerometer);
+        pw.println(" mDeskDockEnablesAccelerometer=" + mDeskDockEnablesAccelerometer);
+        pw.print(prefix + "  mDockMode=" + Intent.dockStateToString(mDockMode));
+        pw.println(" mLidState=" + WindowManagerFuncs.lidStateToString(mLidState));
+        pw.print(prefix + "  mAwake=" + mAwake);
+        pw.print(" mScreenOnEarly=" + mScreenOnEarly);
+        pw.println(" mScreenOnFully=" + mScreenOnFully);
+        pw.print(prefix + "  mKeyguardDrawComplete=" + mKeyguardDrawComplete);
+        pw.println(" mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+        pw.println(prefix + "  mHdmiPlugged=" + mHdmiPlugged);
+    }
+}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
new file mode 100644
index 0000000..685c444
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -0,0 +1,881 @@
+/*
+ * 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.wm;
+
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.hardware.power.V1_0.PowerHint;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Surface;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
+import com.android.server.UiThread;
+import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.policy.WindowOrientationListener;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
+import java.io.PrintWriter;
+
+/**
+ * Defines the mapping between orientation and rotation of a display.
+ * Non-public methods are assumed to run inside WM lock.
+ */
+public class DisplayRotation {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayRotation" : TAG_WM;
+
+    private final WindowManagerService mService;
+    private final DisplayPolicy mDisplayPolicy;
+    private final Context mContext;
+    private final Object mLock;
+
+    public final boolean isDefaultDisplay;
+    private final boolean mSupportAutoRotation;
+    private final int mLidOpenRotation;
+    private final int mCarDockRotation;
+    private final int mDeskDockRotation;
+    private final int mUndockedHdmiRotation;
+
+    private OrientationListener mOrientationListener;
+    private StatusBarManagerInternal mStatusBarManagerInternal;
+    private SettingsObserver mSettingsObserver;
+
+    // Default display does not rotate, apps that require non-default orientation will have to
+    // have the orientation emulated.
+    private boolean mForceDefaultOrientation;
+
+    private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+    @VisibleForTesting
+    int mLandscapeRotation;  // default landscape
+    @VisibleForTesting
+    int mSeascapeRotation;   // "other" landscape, 180 degrees from mLandscapeRotation
+    @VisibleForTesting
+    int mPortraitRotation;   // default portrait
+    @VisibleForTesting
+    int mUpsideDownRotation; // "other" portrait
+
+    // Behavior of rotation suggestions. (See Settings.Secure.SHOW_ROTATION_SUGGESTION)
+    private int mShowRotationSuggestions;
+
+    private int mAllowAllRotations = -1;
+    private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
+    private int mUserRotation = Surface.ROTATION_0;
+
+    private int mDemoHdmiRotation;
+    private int mDemoRotation;
+    private boolean mDemoHdmiRotationLock;
+    private boolean mDemoRotationLock;
+
+    DisplayRotation(WindowManagerService service, DisplayContent displayContent) {
+        this(service, displayContent, displayContent.getDisplayPolicy(),
+                service.mContext, service.getWindowManagerLock());
+    }
+
+    @VisibleForTesting
+    DisplayRotation(WindowManagerService service, DisplayContent displayContent,
+            DisplayPolicy displayPolicy, Context context, Object lock) {
+        mService = service;
+        mDisplayPolicy = displayPolicy;
+        mContext = context;
+        mLock = lock;
+        isDefaultDisplay = displayContent.isDefaultDisplay;
+
+        mSupportAutoRotation = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_supportAutoRotation);
+        mLidOpenRotation = readRotation(
+                com.android.internal.R.integer.config_lidOpenRotation);
+        mCarDockRotation = readRotation(
+                com.android.internal.R.integer.config_carDockRotation);
+        mDeskDockRotation = readRotation(
+                com.android.internal.R.integer.config_deskDockRotation);
+        mUndockedHdmiRotation = readRotation(
+                com.android.internal.R.integer.config_undockedHdmiRotation);
+
+        if (isDefaultDisplay) {
+            final Handler uiHandler = UiThread.getHandler();
+            mOrientationListener = new OrientationListener(mContext, uiHandler);
+            mOrientationListener.setCurrentRotation(displayContent.getRotation());
+            mSettingsObserver = new SettingsObserver(uiHandler);
+            mSettingsObserver.observe();
+        }
+    }
+
+    private int readRotation(int resID) {
+        try {
+            final int rotation = mContext.getResources().getInteger(resID);
+            switch (rotation) {
+                case 0:
+                    return Surface.ROTATION_0;
+                case 90:
+                    return Surface.ROTATION_90;
+                case 180:
+                    return Surface.ROTATION_180;
+                case 270:
+                    return Surface.ROTATION_270;
+            }
+        } catch (Resources.NotFoundException e) {
+            // fall through
+        }
+        return -1;
+    }
+
+    void configure(int width, int height, int shortSizeDp, int longSizeDp) {
+        final Resources res = mContext.getResources();
+        if (width > height) {
+            mLandscapeRotation = Surface.ROTATION_0;
+            mSeascapeRotation = Surface.ROTATION_180;
+            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
+                mPortraitRotation = Surface.ROTATION_90;
+                mUpsideDownRotation = Surface.ROTATION_270;
+            } else {
+                mPortraitRotation = Surface.ROTATION_270;
+                mUpsideDownRotation = Surface.ROTATION_90;
+            }
+        } else {
+            mPortraitRotation = Surface.ROTATION_0;
+            mUpsideDownRotation = Surface.ROTATION_180;
+            if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) {
+                mLandscapeRotation = Surface.ROTATION_270;
+                mSeascapeRotation = Surface.ROTATION_90;
+            } else {
+                mLandscapeRotation = Surface.ROTATION_90;
+                mSeascapeRotation = Surface.ROTATION_270;
+            }
+        }
+
+        // For demo purposes, allow the rotation of the HDMI display to be controlled.
+        // By default, HDMI locks rotation to landscape.
+        if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
+            mDemoHdmiRotation = mPortraitRotation;
+        } else {
+            mDemoHdmiRotation = mLandscapeRotation;
+        }
+        mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
+
+        // For demo purposes, allow the rotation of the remote display to be controlled.
+        // By default, remote display locks rotation to landscape.
+        if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
+            mDemoRotation = mPortraitRotation;
+        } else {
+            mDemoRotation = mLandscapeRotation;
+        }
+        mDemoRotationLock = SystemProperties.getBoolean("persist.demo.rotationlock", false);
+
+        // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
+        // http://developer.android.com/guide/practices/screens_support.html#range
+        // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
+        // so if the orientation is forced, we need to respect that no matter what.
+        final boolean isCar = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_AUTOMOTIVE);
+        // For TV, it's usually 960dp x 540dp, ignore the size limitation.
+        // so if the orientation is forced, we need to respect that no matter what.
+        final boolean isTv = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_LEANBACK);
+        mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
+                res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
+                // For debug purposes the next line turns this feature off with:
+                // $ adb shell setprop config.override_forced_orient true
+                // $ adb shell wm size reset
+                !"true".equals(SystemProperties.get("config.override_forced_orient"));
+    }
+
+    void setRotation(int rotation) {
+        if (mOrientationListener != null) {
+            mOrientationListener.setCurrentRotation(rotation);
+        }
+    }
+
+    void setCurrentOrientation(int newOrientation) {
+        if (newOrientation != mCurrentAppOrientation) {
+            mCurrentAppOrientation = newOrientation;
+            if (isDefaultDisplay) {
+                updateOrientationListenerLw();
+            }
+        }
+    }
+
+    /** @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true. */
+    boolean isDefaultOrientationForced() {
+        return mForceDefaultOrientation;
+    }
+
+    public int getLandscapeRotation() {
+        return mLandscapeRotation;
+    }
+
+    public int getSeascapeRotation() {
+        return mSeascapeRotation;
+    }
+
+    public int getPortraitRotation() {
+        return mPortraitRotation;
+    }
+
+    public int getUpsideDownRotation() {
+        return mUpsideDownRotation;
+    }
+
+    public int getCurrentAppOrientation() {
+        return mCurrentAppOrientation;
+    }
+
+    public DisplayPolicy getDisplayPolicy() {
+        return mDisplayPolicy;
+    }
+
+    public WindowOrientationListener getOrientationListener() {
+        return mOrientationListener;
+    }
+
+    public int getUserRotation() {
+        return mUserRotation;
+    }
+
+    public int getUserRotationMode() {
+        return mUserRotationMode;
+    }
+
+    public void updateOrientationListener() {
+        synchronized (mLock) {
+            updateOrientationListenerLw();
+        }
+    }
+
+    /**
+     * Various use cases for invoking this function:
+     * <li>Screen turning off, should always disable listeners if already enabled.</li>
+     * <li>Screen turned on and current app has sensor based orientation, enable listeners
+     *     if not already enabled.</li>
+     * <li>Screen turned on and current app does not have sensor orientation, disable listeners
+     *     if already enabled.</li>
+     * <li>Screen turning on and current app has sensor based orientation, enable listeners
+     *     if needed.</li>
+     * <li>screen turning on and current app has nosensor based orientation, do nothing.</li>
+     */
+    private void updateOrientationListenerLw() {
+        if (mOrientationListener == null || !mOrientationListener.canDetectOrientation()) {
+            // If sensor is turned off or nonexistent for some reason.
+            return;
+        }
+
+        final boolean screenOnEarly = mDisplayPolicy.isScreenOnEarly();
+        final boolean awake = mDisplayPolicy.isAwake();
+        final boolean keyguardDrawComplete = mDisplayPolicy.isKeyguardDrawComplete();
+        final boolean windowManagerDrawComplete = mDisplayPolicy.isWindowManagerDrawComplete();
+
+        // Could have been invoked due to screen turning on or off or
+        // change of the currently visible window's orientation.
+        if (DEBUG_ORIENTATION) Slog.v(TAG, "screenOnEarly=" + screenOnEarly
+                + ", awake=" + awake + ", currentAppOrientation=" + mCurrentAppOrientation
+                + ", orientationSensorEnabled=" + mOrientationListener.mEnabled
+                + ", keyguardDrawComplete=" + keyguardDrawComplete
+                + ", windowManagerDrawComplete=" + windowManagerDrawComplete);
+
+        boolean disable = true;
+        // Note: We postpone the rotating of the screen until the keyguard as well as the
+        // window manager have reported a draw complete or the keyguard is going away in dismiss
+        // mode.
+        if (screenOnEarly && awake && ((keyguardDrawComplete && windowManagerDrawComplete))) {
+            if (needSensorRunning()) {
+                disable = false;
+                // Enable listener if not already enabled.
+                if (!mOrientationListener.mEnabled) {
+                    // Don't clear the current sensor orientation if the keyguard is going away in
+                    // dismiss mode. This allows window manager to use the last sensor reading to
+                    // determine the orientation vs. falling back to the last known orientation if
+                    // the sensor reading was cleared which can cause it to relaunch the app that
+                    // will show in the wrong orientation first before correcting leading to app
+                    // launch delays.
+                    mOrientationListener.enable(true /* clearCurrentRotation */);
+                }
+            }
+        }
+        // Check if sensors need to be disabled.
+        if (disable && mOrientationListener.mEnabled) {
+            mOrientationListener.disable();
+        }
+    }
+
+    /**
+     * We always let the sensor be switched on by default except when
+     * the user has explicitly disabled sensor based rotation or when the
+     * screen is switched off.
+     */
+    private boolean needSensorRunning() {
+        if (mSupportAutoRotation) {
+            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
+                // If the application has explicitly requested to follow the
+                // orientation, then we need to turn the sensor on.
+                return true;
+            }
+        }
+
+        final int dockMode = mDisplayPolicy.getDockMode();
+        if ((mDisplayPolicy.isCarDockEnablesAccelerometer()
+                && dockMode == Intent.EXTRA_DOCK_STATE_CAR)
+                || (mDisplayPolicy.isDeskDockEnablesAccelerometer()
+                        && (dockMode == Intent.EXTRA_DOCK_STATE_DESK
+                                || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+                                || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
+            // Enable accelerometer if we are docked in a dock that enables accelerometer
+            // orientation management.
+            return true;
+        }
+
+        if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
+            // If the setting for using the sensor by default is enabled, then
+            // we will always leave it on.  Note that the user could go to
+            // a window that forces an orientation that does not use the
+            // sensor and in theory we could turn it off... however, when next
+            // turning it on we won't have a good value for the current
+            // orientation for a little bit, which can cause orientation
+            // changes to lag, so we'd like to keep it always on.  (It will
+            // still be turned off when the screen is off.)
+
+            // When locked we can provide rotation suggestions users can approve to change the
+            // current screen rotation. To do this the sensor needs to be running.
+            return mSupportAutoRotation &&
+                    mShowRotationSuggestions == Settings.Secure.SHOW_ROTATION_SUGGESTIONS_ENABLED;
+        }
+        return mSupportAutoRotation;
+    }
+
+    /**
+     * Given an orientation constant, returns the appropriate surface rotation,
+     * taking into account sensors, docking mode, rotation lock, and other factors.
+     *
+     * @param orientation An orientation constant, such as
+     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
+     * @param lastRotation The most recently used rotation.
+     * @param defaultDisplay Flag indicating whether the rotation is computed for the default
+     *                       display. Currently for all non-default displays sensors, docking mode,
+     *                       rotation lock and other factors are ignored.
+     * @return The surface rotation to use.
+     */
+    int rotationForOrientation(int orientation, int lastRotation) {
+        if (DEBUG_ORIENTATION) {
+            Slog.v(TAG, "rotationForOrientation(orient="
+                        + orientation + ", last=" + lastRotation
+                        + "); user=" + mUserRotation + " "
+                        + (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
+                            ? "USER_ROTATION_LOCKED" : "")
+                        );
+        }
+
+        if (mForceDefaultOrientation) {
+            return Surface.ROTATION_0;
+        }
+
+        int sensorRotation = mOrientationListener != null
+                ? mOrientationListener.getProposedRotation() // may be -1
+                : -1;
+        if (sensorRotation < 0) {
+            sensorRotation = lastRotation;
+        }
+
+        final int lidState = mDisplayPolicy.getLidState();
+        final int dockMode = mDisplayPolicy.getDockMode();
+        final boolean hdmiPlugged = mDisplayPolicy.isHdmiPlugged();
+        final boolean carDockEnablesAccelerometer =
+                mDisplayPolicy.isCarDockEnablesAccelerometer();
+        final boolean deskDockEnablesAccelerometer =
+                mDisplayPolicy.isDeskDockEnablesAccelerometer();
+
+        final int preferredRotation;
+        if (!isDefaultDisplay) {
+            // For secondary displays we ignore things like displays sensors, docking mode and
+            // rotation lock, and always prefer a default rotation.
+            preferredRotation = Surface.ROTATION_0;
+        } else if (lidState == LID_OPEN && mLidOpenRotation >= 0) {
+            // Ignore sensor when lid switch is open and rotation is forced.
+            preferredRotation = mLidOpenRotation;
+        } else if (dockMode == Intent.EXTRA_DOCK_STATE_CAR
+                && (carDockEnablesAccelerometer || mCarDockRotation >= 0)) {
+            // Ignore sensor when in car dock unless explicitly enabled.
+            // This case can override the behavior of NOSENSOR, and can also
+            // enable 180 degree rotation while docked.
+            preferredRotation = carDockEnablesAccelerometer ? sensorRotation : mCarDockRotation;
+        } else if ((dockMode == Intent.EXTRA_DOCK_STATE_DESK
+                || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+                || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
+                && (deskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
+            // Ignore sensor when in desk dock unless explicitly enabled.
+            // This case can override the behavior of NOSENSOR, and can also
+            // enable 180 degree rotation while docked.
+            preferredRotation = deskDockEnablesAccelerometer ? sensorRotation : mDeskDockRotation;
+        } else if (hdmiPlugged && mDemoHdmiRotationLock) {
+            // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.
+            // Note that the dock orientation overrides the HDMI orientation.
+            preferredRotation = mDemoHdmiRotation;
+        } else if (hdmiPlugged && dockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
+                && mUndockedHdmiRotation >= 0) {
+            // Ignore sensor when plugged into HDMI and an undocked orientation has
+            // been specified in the configuration (only for legacy devices without
+            // full multi-display support).
+            // Note that the dock orientation overrides the HDMI orientation.
+            preferredRotation = mUndockedHdmiRotation;
+        } else if (mDemoRotationLock) {
+            // Ignore sensor when demo rotation lock is enabled.
+            // Note that the dock orientation and HDMI rotation lock override this.
+            preferredRotation = mDemoRotation;
+        } else if (mDisplayPolicy.isPersistentVrModeEnabled()) {
+            // While in VR, apps always prefer a portrait rotation. This does not change
+            // any apps that explicitly set landscape, but does cause sensors be ignored,
+            // and ignored any orientation lock that the user has set (this conditional
+            // should remain above the ORIENTATION_LOCKED conditional below).
+            preferredRotation = mPortraitRotation;
+        } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
+            // Application just wants to remain locked in the last rotation.
+            preferredRotation = lastRotation;
+        } else if (!mSupportAutoRotation) {
+            // If we don't support auto-rotation then bail out here and ignore
+            // the sensor and any rotation lock settings.
+            preferredRotation = -1;
+        } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
+                        && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
+                                || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+                                || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
+                                || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
+                                || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER))
+                || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
+                || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+                || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
+                || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
+            // Otherwise, use sensor only if requested by the application or enabled
+            // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
+            if (mAllowAllRotations < 0) {
+                // Can't read this during init() because the context doesn't
+                // have display metrics at that time so we cannot determine
+                // tablet vs. phone then.
+                mAllowAllRotations = mContext.getResources().getBoolean(
+                        com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
+            }
+            if (sensorRotation != Surface.ROTATION_180
+                    || mAllowAllRotations == 1
+                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+                    || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
+                preferredRotation = sensorRotation;
+            } else {
+                preferredRotation = lastRotation;
+            }
+        } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
+                && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+            // Apply rotation lock.  Does not apply to NOSENSOR.
+            // The idea is that the user rotation expresses a weak preference for the direction
+            // of gravity and as NOSENSOR is never affected by gravity, then neither should
+            // NOSENSOR be affected by rotation lock (although it will be affected by docks).
+            preferredRotation = mUserRotation;
+        } else {
+            // No overriding preference.
+            // We will do exactly what the application asked us to do.
+            preferredRotation = -1;
+        }
+
+        switch (orientation) {
+            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
+                // Return portrait unless overridden.
+                if (isAnyPortrait(preferredRotation)) {
+                    return preferredRotation;
+                }
+                return mPortraitRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
+                // Return landscape unless overridden.
+                if (isLandscapeOrSeascape(preferredRotation)) {
+                    return preferredRotation;
+                }
+                return mLandscapeRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+                // Return reverse portrait unless overridden.
+                if (isAnyPortrait(preferredRotation)) {
+                    return preferredRotation;
+                }
+                return mUpsideDownRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+                // Return seascape unless overridden.
+                if (isLandscapeOrSeascape(preferredRotation)) {
+                    return preferredRotation;
+                }
+                return mSeascapeRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+                // Return either landscape rotation.
+                if (isLandscapeOrSeascape(preferredRotation)) {
+                    return preferredRotation;
+                }
+                if (isLandscapeOrSeascape(lastRotation)) {
+                    return lastRotation;
+                }
+                return mLandscapeRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+                // Return either portrait rotation.
+                if (isAnyPortrait(preferredRotation)) {
+                    return preferredRotation;
+                }
+                if (isAnyPortrait(lastRotation)) {
+                    return lastRotation;
+                }
+                return mPortraitRotation;
+
+            default:
+                // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
+                // just return the preferred orientation we already calculated.
+                if (preferredRotation >= 0) {
+                    return preferredRotation;
+                }
+                return Surface.ROTATION_0;
+        }
+    }
+
+    private boolean isLandscapeOrSeascape(int rotation) {
+        return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
+    }
+
+    private boolean isAnyPortrait(int rotation) {
+        return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
+    }
+
+    /**
+     * Given an orientation constant and a rotation, returns true if the rotation
+     * has compatible metrics to the requested orientation.  For example, if
+     * the application requested landscape and got seascape, then the rotation
+     * has compatible metrics; if the application requested portrait and got landscape,
+     * then the rotation has incompatible metrics; if the application did not specify
+     * a preference, then anything goes.
+     *
+     * @param orientation An orientation constant, such as
+     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
+     * @param rotation The rotation to check.
+     * @return True if the rotation is compatible with the requested orientation.
+     */
+    boolean rotationHasCompatibleMetrics(int orientation, int rotation) {
+        switch (orientation) {
+            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
+            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+                return isAnyPortrait(rotation);
+
+            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
+            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+                return isLandscapeOrSeascape(rotation);
+
+            default:
+                return true;
+        }
+    }
+
+    private boolean isValidRotationChoice(final int preferredRotation) {
+        // Determine if the given app orientation is compatible with the provided rotation choice.
+        switch (mCurrentAppOrientation) {
+            case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
+                // Works with any of the 4 rotations.
+                return preferredRotation >= 0;
+
+            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+                // It's possible for the user pref to be set at 180 because of FULL_USER. This would
+                // make switching to USER_PORTRAIT appear at 180. Provide choice to back to portrait
+                // but never to go to 180.
+                return preferredRotation == mPortraitRotation;
+
+            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+                // Works landscape or seascape.
+                return isLandscapeOrSeascape(preferredRotation);
+
+            case ActivityInfo.SCREEN_ORIENTATION_USER:
+            case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
+                // Works with any rotation except upside down.
+                return (preferredRotation >= 0) && (preferredRotation != mUpsideDownRotation);
+        }
+
+        return false;
+    }
+
+    private boolean isRotationChoicePossible(int orientation) {
+        // Rotation choice is only shown when the user is in locked mode.
+        if (mUserRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) return false;
+
+        // We should only enable rotation choice if the rotation isn't forced by the lid, dock,
+        // demo, hdmi, vr, etc mode.
+
+        // Determine if the rotation is currently forced.
+        if (mForceDefaultOrientation) {
+            return false; // Rotation is forced to default orientation.
+        }
+
+        final int lidState = mDisplayPolicy.getLidState();
+        if (lidState == LID_OPEN && mLidOpenRotation >= 0) {
+            return false; // Rotation is forced mLidOpenRotation.
+        }
+
+        final int dockMode = mDisplayPolicy.getDockMode();
+        final boolean carDockEnablesAccelerometer = false;
+        if (dockMode == Intent.EXTRA_DOCK_STATE_CAR && !carDockEnablesAccelerometer) {
+            return false; // Rotation forced to mCarDockRotation.
+        }
+
+        final boolean deskDockEnablesAccelerometer =
+                mDisplayPolicy.isDeskDockEnablesAccelerometer();
+        if ((dockMode == Intent.EXTRA_DOCK_STATE_DESK
+                || dockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
+                || dockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
+                && !deskDockEnablesAccelerometer) {
+            return false; // Rotation forced to mDeskDockRotation.
+        }
+
+        final boolean hdmiPlugged = mDisplayPolicy.isHdmiPlugged();
+        if (hdmiPlugged && mDemoHdmiRotationLock) {
+            return false; // Rotation forced to mDemoHdmiRotation.
+
+        } else if (hdmiPlugged && dockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED
+                && mUndockedHdmiRotation >= 0) {
+            return false; // Rotation forced to mUndockedHdmiRotation.
+
+        } else if (mDemoRotationLock) {
+            return false; // Rotation forced to mDemoRotation.
+
+        } else if (mDisplayPolicy.isPersistentVrModeEnabled()) {
+            return false; // Rotation forced to mPortraitRotation.
+
+        } else if (!mSupportAutoRotation) {
+            return false;
+        }
+
+        // Ensure that some rotation choice is possible for the given orientation.
+        switch (orientation) {
+            case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
+            case ActivityInfo.SCREEN_ORIENTATION_USER:
+            case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
+            case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
+            case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
+                // NOSENSOR description is ambiguous, in reality WM ignores user choice.
+                return true;
+        }
+
+        // Rotation is forced, should be controlled by system.
+        return false;
+    }
+
+    /** Notify the StatusBar that system rotation suggestion has changed. */
+    private void sendProposedRotationChangeToStatusBarInternal(int rotation, boolean isValid) {
+        if (mStatusBarManagerInternal == null) {
+            mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
+        }
+        if (mStatusBarManagerInternal != null) {
+            mStatusBarManagerInternal.onProposedRotationChanged(rotation, isValid);
+        }
+    }
+
+    private static String allowAllRotationsToString(int allowAll) {
+        switch (allowAll) {
+            case -1:
+                return "unknown";
+            case 0:
+                return "false";
+            case 1:
+                return "true";
+            default:
+                return Integer.toString(allowAll);
+        }
+    }
+
+    public void onUserSwitch() {
+        if (mSettingsObserver != null) {
+            mSettingsObserver.onChange(false);
+        }
+    }
+
+    /** Return whether the rotation settings has changed. */
+    private boolean updateSettings() {
+        final ContentResolver resolver = mContext.getContentResolver();
+        boolean shouldUpdateRotation = false;
+
+        synchronized (mLock) {
+            boolean shouldUpdateOrientationListener = false;
+
+            // Configure rotation suggestions.
+            final int showRotationSuggestions = Settings.Secure.getIntForUser(resolver,
+                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
+                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS_DEFAULT,
+                    UserHandle.USER_CURRENT);
+            if (mShowRotationSuggestions != showRotationSuggestions) {
+                mShowRotationSuggestions = showRotationSuggestions;
+                shouldUpdateOrientationListener = true;
+            }
+
+            // Configure rotation lock.
+            final int userRotation = Settings.System.getIntForUser(resolver,
+                    Settings.System.USER_ROTATION, Surface.ROTATION_0,
+                    UserHandle.USER_CURRENT);
+            if (mUserRotation != userRotation) {
+                mUserRotation = userRotation;
+                shouldUpdateRotation = true;
+            }
+
+            final int userRotationMode = Settings.System.getIntForUser(resolver,
+                    Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0
+                            ? WindowManagerPolicy.USER_ROTATION_FREE
+                            : WindowManagerPolicy.USER_ROTATION_LOCKED;
+            if (mUserRotationMode != userRotationMode) {
+                mUserRotationMode = userRotationMode;
+                shouldUpdateOrientationListener = true;
+                shouldUpdateRotation = true;
+            }
+
+            if (shouldUpdateOrientationListener) {
+                updateOrientationListenerLw(); // Enable or disable the orientation listener.
+            }
+        }
+
+        return shouldUpdateRotation;
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        pw.println(prefix + "DisplayRotation");
+        pw.println(prefix + "  mCurrentAppOrientation="
+                + ActivityInfo.screenOrientationToString(mCurrentAppOrientation));
+        pw.print(prefix + "  mLandscapeRotation=" + Surface.rotationToString(mLandscapeRotation));
+        pw.println(" mSeascapeRotation=" + Surface.rotationToString(mSeascapeRotation));
+        pw.print(prefix + "  mPortraitRotation=" + Surface.rotationToString(mPortraitRotation));
+        pw.println(" mUpsideDownRotation=" + Surface.rotationToString(mUpsideDownRotation));
+
+        pw.print(prefix + "  mSupportAutoRotation=" + mSupportAutoRotation);
+        if (mOrientationListener != null) {
+            pw.print(" mOrientationSensorEnabled=" + mOrientationListener.mEnabled);
+        }
+        pw.println();
+
+        pw.print(prefix + "  mCarDockRotation=" + Surface.rotationToString(mCarDockRotation));
+        pw.println(" mDeskDockRotation=" + Surface.rotationToString(mDeskDockRotation));
+        pw.print(prefix + "  mUserRotationMode="
+                + WindowManagerPolicy.userRotationModeToString(mUserRotationMode));
+        pw.print(" mUserRotation=" + Surface.rotationToString(mUserRotation));
+        pw.println(" mAllowAllRotations=" + allowAllRotationsToString(mAllowAllRotations));
+
+        pw.print(prefix + "  mDemoHdmiRotation=" + Surface.rotationToString(mDemoHdmiRotation));
+        pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
+        pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
+        pw.println(prefix + "  mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
+    }
+
+    private class OrientationListener extends WindowOrientationListener {
+        final SparseArray<Runnable> mRunnableCache = new SparseArray<>(5);
+        boolean mEnabled;
+
+        OrientationListener(Context context, Handler handler) {
+            super(context, handler);
+        }
+
+        private class UpdateRunnable implements Runnable {
+            final int mRotation;
+
+            UpdateRunnable(int rotation) {
+                mRotation = rotation;
+            }
+
+            @Override
+            public void run() {
+                // Send interaction hint to improve redraw performance.
+                mService.mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0);
+                if (isRotationChoicePossible(mCurrentAppOrientation)) {
+                    final boolean isValid = isValidRotationChoice(mRotation);
+                    sendProposedRotationChangeToStatusBarInternal(mRotation, isValid);
+                } else {
+                    mService.updateRotation(false /* alwaysSendConfiguration */,
+                            false /* forceRelayout */);
+                }
+            }
+        }
+
+        @Override
+        public void onProposedRotationChanged(int rotation) {
+            if (DEBUG_ORIENTATION) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
+            Runnable r = mRunnableCache.get(rotation, null);
+            if (r == null) {
+                r = new UpdateRunnable(rotation);
+                mRunnableCache.put(rotation, r);
+            }
+            getHandler().post(r);
+        }
+
+        @Override
+        public void enable(boolean clearCurrentRotation) {
+            super.enable(clearCurrentRotation);
+            mEnabled = true;
+            if (DEBUG_ORIENTATION) Slog.v(TAG, "Enabling listeners");
+        }
+
+        @Override
+        public void disable() {
+            super.disable();
+            mEnabled = false;
+            if (DEBUG_ORIENTATION) Slog.v(TAG, "Disabling listeners");
+        }
+    }
+
+    private class SettingsObserver extends ContentObserver {
+        SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        void observe() {
+            final ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS), false, this,
+                    UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.ACCELEROMETER_ROTATION), false, this,
+                    UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.USER_ROTATION), false, this,
+                    UserHandle.USER_ALL);
+            updateSettings();
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            if (updateSettings()) {
+                mService.updateRotation(true /* alwaysSendConfiguration */,
+                        false /* forceRelayout */);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index d53a21b..c4beb55 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -399,7 +399,8 @@
             this.inDrag = inDrag;
             wallpaperController = mService.mRoot.mWallpaperController;
 
-            mService.mRoot.getDisplayContent(mDisplayId).forAllWindows(this,
+            // TODO(b/112081256): Use independent InputMonitor for each display.
+            mService.mRoot/*.getDisplayContent(mDisplayId)*/.forAllWindows(this,
                     true /* traverseTopToBottom */);
             if (mAddWallpaperInputConsumerHandle) {
                 // No visible wallpaper found, add the wallpaper input consumer at the end.
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 3df4eb7..ca4fa64 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -134,6 +134,9 @@
     // transaction from the global transaction.
     private final SurfaceControl.Transaction mDisplayTransaction = new SurfaceControl.Transaction();
 
+    private final Consumer<DisplayContent> mDisplayContentConfigChangesConsumer =
+            mService.mPolicy::onConfigurationChanged;
+
     private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
         if (w.mHasSurface) {
             try {
@@ -379,7 +382,7 @@
         prepareFreezingTaskBounds();
         super.onConfigurationChanged(newParentConfig);
 
-        mService.mPolicy.onConfigurationChanged();
+        forAllDisplays(mDisplayContentConfigChangesConsumer);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9b792e3..ea68e17 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2480,10 +2480,7 @@
                 dc.setLastOrientation(req);
                 //send a message to Policy indicating orientation change to take
                 //action like disabling/enabling sensors etc.,
-                // TODO(multi-display): Implement policy for secondary displays.
-                if (dc.isDefaultDisplay) {
-                    mPolicy.setCurrentOrientationLw(req);
-                }
+                dc.getDisplayRotation().setCurrentOrientation(req);
                 return dc.updateRotationUnchecked(forceUpdate);
             }
             return false;
@@ -2492,27 +2489,6 @@
         }
     }
 
-    // If this is true we have updated our desired orientation, but not yet
-    // changed the real orientation our applied our screen rotation animation.
-    // For example, because a previous screen rotation was in progress.
-    boolean rotationNeedsUpdateLocked() {
-        // TODO(multi-display): Check for updates on all displays. Need to have per-display policy
-        // to implement WindowManagerPolicy#rotationForOrientationLw() correctly.
-        final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
-        final int lastOrientation = defaultDisplayContent.getLastOrientation();
-        final int oldRotation = defaultDisplayContent.getRotation();
-        final boolean oldAltOrientation = defaultDisplayContent.getAltOrientation();
-
-        final int rotation = mPolicy.rotationForOrientationLw(lastOrientation, oldRotation,
-                true /* defaultDisplay */);
-        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
-                lastOrientation, rotation);
-        if (oldRotation == rotation && oldAltOrientation == altOrientation) {
-            return false;
-        }
-        return true;
-    }
-
     @Override
     public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) {
@@ -3841,28 +3817,31 @@
         long origId = Binder.clearCallingIdentity();
 
         try {
-            // TODO(multi-display): Update rotation for different displays separately.
-            final boolean rotationChanged;
-            final int displayId;
             synchronized (mWindowMap) {
-                final DisplayContent displayContent = getDefaultDisplayContentLocked();
-                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
-                rotationChanged = displayContent.updateRotationUnchecked();
-                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-                if (!rotationChanged || forceRelayout) {
-                    displayContent.setLayoutNeeded();
+                boolean layoutNeeded = false;
+                final int displayCount = mRoot.mChildren.size();
+                for (int i = 0; i < displayCount; ++i) {
+                    final DisplayContent displayContent = mRoot.mChildren.get(i);
+                    Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
+                    final boolean rotationChanged = displayContent.updateRotationUnchecked();
+                    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+
+                    if (!rotationChanged || forceRelayout) {
+                        displayContent.setLayoutNeeded();
+                        layoutNeeded = true;
+                    }
+                    if (rotationChanged || alwaysSendConfiguration) {
+                        mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
+                                .sendToTarget();
+                    }
+                }
+
+                if (layoutNeeded) {
                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                             "updateRotation: performSurfacePlacement");
                     mWindowPlacerLocked.performSurfacePlacement();
                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 }
-                displayId = displayContent.getDisplayId();
-            }
-
-            if (rotationChanged || alwaysSendConfiguration) {
-                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: sendNewConfiguration");
-                sendNewConfiguration(displayId);
-                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -3871,6 +3850,13 @@
     }
 
     @Override
+    public WindowManagerPolicy.DisplayContentInfo getDefaultDisplayContentInfo() {
+        synchronized (mWindowMap) {
+            return getDefaultDisplayContentLocked();
+        }
+    }
+
+    @Override
     public int getDefaultDisplayRotation() {
         synchronized (mWindowMap) {
             return getDefaultDisplayContentLocked().getRotation();
@@ -5792,7 +5778,7 @@
 
             displayContent.updateDisplayInfo();
             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
-                    mPolicy.isDefaultOrientationForced(), isSecure,
+                    displayContent.getDisplayRotation().isDefaultOrientationForced(), isSecure,
                     this);
             mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
                     screenRotationAnimation);
@@ -6082,23 +6068,26 @@
     @Override
     public void createInputConsumer(IBinder token, String name, InputChannel inputChannel) {
         synchronized (mWindowMap) {
-            mRoot.forAllDisplays(dc -> {
-                dc.getInputMonitor().createInputConsumer(token, name, inputChannel,
+            // TODO(b/112049699): Fix this for multiple displays. There is only one inputChannel
+            // here to accept the return value.
+            DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+            if (display != null) {
+                display.getInputMonitor().createInputConsumer(token, name, inputChannel,
                         Binder.getCallingPid(), Binder.getCallingUserHandle());
-            });
+            }
         }
     }
 
     @Override
     public boolean destroyInputConsumer(String name) {
         synchronized (mWindowMap) {
-            AtomicBoolean retValue = new AtomicBoolean(true);
-            mRoot.forAllDisplays(dc -> {
-                if (!dc.getInputMonitor().destroyInputConsumer(name)) {
-                    retValue.set(false);
-                }
-            });
-            return retValue.get();
+            // TODO(b/112049699): Fix this for multiple displays. For consistency with
+            // createInputConsumer above.
+            DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+            if (display != null) {
+                return display.getInputMonitor().destroyInputConsumer(name);
+            }
+            return false;
         }
     }
 
@@ -6761,8 +6750,10 @@
 
     public void onOverlayChanged() {
         synchronized (mWindowMap) {
-            mPolicy.onOverlayChangedLw();
-            getDefaultDisplayContentLocked().updateDisplayInfo();
+            mRoot.forAllDisplays(displayContent -> {
+                mPolicy.onOverlayChangedLw(displayContent);
+                displayContent.updateDisplayInfo();
+            });
             requestTraversal();
         }
     }
@@ -7090,19 +7081,24 @@
 
     @Override
     public void dontOverrideDisplayInfo(int displayId) {
-        synchronized (mWindowMap) {
-            final DisplayContent dc = getDisplayContentOrCreate(displayId);
-            if (dc == null) {
-                throw new IllegalArgumentException(
-                        "Trying to register a non existent display.");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mWindowMap) {
+                final DisplayContent dc = getDisplayContentOrCreate(displayId);
+                if (dc == null) {
+                    throw new IllegalArgumentException(
+                            "Trying to register a non existent display.");
+                }
+                // We usually set the override info in DisplayManager so that we get consistent
+                // values when displays are changing. However, we don't do this for displays that
+                // serve as containers for ActivityViews because we don't want letter-/pillar-boxing
+                // during resize.
+                dc.mShouldOverrideDisplayConfiguration = false;
+                mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId,
+                        null /* info */);
             }
-            // We usually set the override info in DisplayManager so that we get consistent
-            // values when displays are changing. However, we don't do this for displays that
-            // serve as containers for ActivityViews because we don't want letter-/pillar-boxing
-            // during resize.
-            dc.mShouldOverrideDisplayConfiguration = false;
-            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId,
-                    null /* info */);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
@@ -7141,11 +7137,7 @@
             }
             finishSeamlessRotation();
 
-            final DisplayContent displayContent = w.getDisplayContent();
-            if (displayContent.updateRotationUnchecked()) {
-                mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
-                        .sendToTarget();
-            }
+            w.getDisplayContent().updateRotationAndSendNewConfigIfNeeded();
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index aced8e4..08decdf 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -569,7 +569,7 @@
             // animation after the old one finally finishes. It's better to defer the
             // app transition.
             if (screenRotationAnimation != null && screenRotationAnimation.isAnimating() &&
-                    mService.rotationNeedsUpdateLocked()) {
+                    mService.getDefaultDisplayContentLocked().rotationNeedsUpdate()) {
                 if (DEBUG_APP_TRANSITIONS) {
                     Slog.v(TAG, "Delaying app transition for screen rotation animation to finish");
                 }
diff --git a/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
new file mode 100644
index 0000000..dd0a58d
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.Handler;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class KeyValueBackupJobTest {
+    private Context mContext;
+    private BackupManagerConstants mConstants;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = RuntimeEnvironment.application;
+        mConstants = new BackupManagerConstants(Handler.getMain(), mContext.getContentResolver());
+        mConstants.start();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mConstants.stop();
+        KeyValueBackupJob.cancel(mContext);
+    }
+
+    @Test
+    public void testIsScheduled_beforeScheduling_returnsFalse() {
+        boolean isScheduled = KeyValueBackupJob.isScheduled();
+
+        assertThat(isScheduled).isFalse();
+    }
+
+    @Test
+    public void testIsScheduled_afterScheduling_returnsTrue() {
+        KeyValueBackupJob.schedule(mContext, mConstants);
+
+        boolean isScheduled = KeyValueBackupJob.isScheduled();
+
+        assertThat(isScheduled).isTrue();
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
index 8fab197..1f6ac8d 100644
--- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
@@ -54,6 +54,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
+import static org.robolectric.shadow.api.Shadow.extract;
 
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 import static java.util.Collections.emptyList;
@@ -79,6 +80,7 @@
 import android.net.Uri;
 import android.os.DeadObjectException;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
@@ -101,6 +103,7 @@
 import com.android.server.testing.FrameworkRobolectricTestRunner;
 import com.android.server.testing.SystemLoaderClasses;
 import com.android.server.testing.SystemLoaderPackages;
+import com.android.server.testing.shadows.FrameworkShadowLooper;
 import com.android.server.testing.shadows.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
 import com.android.server.testing.shadows.ShadowEventLog;
@@ -143,10 +146,11 @@
         manifest = Config.NONE,
         sdk = 26,
         shadows = {
+            FrameworkShadowLooper.class,
             ShadowBackupDataInput.class,
             ShadowBackupDataOutput.class,
             ShadowEventLog.class,
-            ShadowQueuedWork.class
+            ShadowQueuedWork.class,
         })
 @SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
 @SystemLoaderClasses({IBackupTransport.class, IBackupAgent.class, PackageInfo.class})
@@ -171,6 +175,7 @@
     private File mDataDir;
     private Application mApplication;
     private ShadowApplication mShadowApplication;
+    private FrameworkShadowLooper mShadowMainLooper;
     private Context mContext;
 
     @Before
@@ -183,6 +188,8 @@
         mShadowApplication = shadowOf(mApplication);
         mContext = mApplication;
 
+        mShadowMainLooper = extract(Looper.getMainLooper());
+
         File cacheDir = mApplication.getCacheDir();
         // Corresponds to /data/backup
         mBaseStateDir = new File(cacheDir, "base_state");
@@ -337,7 +344,7 @@
 
         runTask(task);
 
-        assertEventLogged(EventLogTags.BACKUP_START, mTransport.transportDirName);
+        assertEventLogged(EventLogTags.BACKUP_START, mTransport.transportName);
     }
 
     @Test
@@ -1571,11 +1578,10 @@
     }
 
     private void runTask(PerformBackupTask task) {
-        Message message = mBackupHandler.obtainMessage(BackupHandler.MSG_BACKUP_RESTORE_STEP, task);
-        mBackupHandler.sendMessage(message);
-        while (mShadowBackupLooper.getScheduler().areAnyRunnable()) {
-            mShadowBackupLooper.runToEndOfTasks();
-        }
+        // Pretend we are not on the main-thread to prevent RemoteCall from complaining
+        mShadowMainLooper.setCurrentThread(false);
+        task.run();
+        mShadowMainLooper.reset();
         assertTaskPostConditions();
     }
 
@@ -1699,7 +1705,7 @@
             String transportDirName,
             boolean nonIncremental,
             PackageData... packages) {
-        ArrayList<BackupRequest> backupRequests =
+        ArrayList<BackupRequest> keyValueBackupRequests =
                 Stream.of(packages)
                         .map(packageData -> packageData.packageName)
                         .map(BackupRequest::new)
@@ -1713,7 +1719,7 @@
                         mBackupManagerService,
                         transportClient,
                         transportDirName,
-                        backupRequests,
+                        keyValueBackupRequests,
                         mOldJournal,
                         mObserver,
                         mMonitor,
diff --git a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
new file mode 100644
index 0000000..aec207d
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.backup.remote;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import java.util.concurrent.CompletableFuture;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class FutureBackupCallbackTest {
+    @Test
+    public void testOperationComplete_completesFuture() throws Exception {
+        CompletableFuture<RemoteResult> future = new CompletableFuture<>();
+        FutureBackupCallback callback = new FutureBackupCallback(future);
+
+        callback.operationComplete(7);
+
+        assertThat(future.get()).isEqualTo(RemoteResult.successful(7));
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
new file mode 100644
index 0000000..55db616
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
@@ -0,0 +1,244 @@
+/*
+ * 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.backup.remote;
+
+import static com.android.server.backup.testing.TestUtils.runToEndOfTasks;
+import static com.android.server.backup.testing.TestUtils.uncheck;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.IBackupCallback;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.backup.testing.TestUtils.ThrowingRunnable;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class RemoteCallTest {
+    /** A {@link RemoteCallable} that calls the callback immediately. */
+    private final RemoteCallable<IBackupCallback> IMMEDIATE_CALLABLE =
+            callback -> callback.operationComplete(0);
+
+    @Mock private RemoteCallable<IBackupCallback> mCallable;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testCall_whenCancelledAndImmediateCallableAndTimeOut0_returnsCancel()
+            throws Exception {
+        RemoteCall remoteCall = new RemoteCall(true, IMMEDIATE_CALLABLE, 0);
+
+        RemoteResult result = runInWorkerThread(remoteCall::call);
+
+        assertThat(result).isEqualTo(RemoteResult.FAILED_CANCELLED);
+    }
+
+    @Test
+    public void testCall_whenCancelledAndImmediateCallableAndTimeOut0_doesNotCallCallable()
+            throws Exception {
+        RemoteCall remoteCall = new RemoteCall(true, IMMEDIATE_CALLABLE, 0);
+
+        runInWorkerThread(remoteCall::call);
+
+        verify(mCallable, never()).call(any());
+    }
+
+    @Test
+    public void testCall_whenImmediateCallableAndTimeOut0AndCancelIsCalledBeforeCall_returnsCancel()
+            throws Exception {
+        RemoteCall remoteCall = new RemoteCall(IMMEDIATE_CALLABLE, 0);
+        remoteCall.cancel();
+
+        RemoteResult result = runInWorkerThread(remoteCall::call);
+
+        assertThat(result).isEqualTo(RemoteResult.FAILED_CANCELLED);
+    }
+
+    @Test
+    public void
+            testCall_whenImmediateCallableAndTimeOut0AndCancelIsCalledBeforeCall_doesNotCallCallable()
+                    throws Exception {
+        RemoteCall remoteCall = new RemoteCall(IMMEDIATE_CALLABLE, 0);
+        remoteCall.cancel();
+
+        runInWorkerThread(remoteCall::call);
+
+        verify(mCallable, never()).call(any());
+    }
+
+    @Test
+    public void testCall_whenImmediateCallableAndTimeOut0_returnsTimeOut() throws Exception {
+        RemoteCall remoteCall = new RemoteCall(IMMEDIATE_CALLABLE, 0);
+
+        RemoteResult result = runInWorkerThread(remoteCall::call);
+
+        assertThat(result).isEqualTo(RemoteResult.FAILED_TIMED_OUT);
+    }
+
+    @Test
+    public void testCall_whenTimeOut0_doesNotCallCallable() throws Exception {
+        RemoteCall remoteCall = new RemoteCall(mCallable, 0);
+
+        runInWorkerThread(remoteCall::call);
+
+        verify(mCallable, never()).call(any());
+    }
+
+    @Test
+    public void testCall_whenTimesOutBeforeCallbackIsCalled_returnsTimeOut() throws Exception {
+        ConditionVariable scheduled = new ConditionVariable(false);
+        RemoteCall remoteCall =
+                new RemoteCall(
+                        callback -> {
+                            postDelayed(
+                                    Handler.getMain(), () -> callback.operationComplete(0), 1000);
+                            scheduled.open();
+                        },
+                        500);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        // Method runToEndOfTasks() will execute what was posted to the main handler, which is the
+        // completion of the callback and the time-out (that was scheduled by RemoteCall). But to be
+        // able to execute everything we have to ensure that runToEndOfTasks() is called *after*
+        // everything has been scheduled, that's why we use the condition variable scheduled, that
+        // is set to true (i.e. opened) when everything is scheduled, allowing us to run the tasks.
+        scheduled.block();
+        runToEndOfTasks(Looper.getMainLooper());
+        assertThat(result.get()).isEqualTo(RemoteResult.FAILED_TIMED_OUT);
+    }
+
+    @Test
+    public void testCall_whenTimesOutBeforeCancelIsCalled_returnsTimeOut() throws Exception {
+        ConditionVariable scheduled = new ConditionVariable(false);
+        RemoteCall remoteCall = new RemoteCall(callback -> scheduled.open(), 500);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        scheduled.block();
+        runToEndOfTasks(Looper.getMainLooper());
+        remoteCall.cancel();
+        assertThat(result.get()).isEqualTo(RemoteResult.FAILED_TIMED_OUT);
+    }
+
+    @Test
+    public void testCall_whenCallbackIsCalledBeforeTimeOut_returnsSuccess() throws Exception {
+        ConditionVariable scheduled = new ConditionVariable(false);
+        RemoteCall remoteCall =
+                new RemoteCall(
+                        callback -> {
+                            postDelayed(
+                                    Handler.getMain(), () -> callback.operationComplete(3), 500);
+                            scheduled.open();
+                        },
+                        1000);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        scheduled.block();
+        runToEndOfTasks(Looper.getMainLooper());
+        assertThat(result.get()).isEqualTo(RemoteResult.successful(3));
+    }
+
+    @Test
+    public void testCall_whenCallbackIsCalledBeforeCancel_returnsSuccess() throws Exception {
+        CompletableFuture<IBackupCallback> callbackFuture = new CompletableFuture<>();
+        RemoteCall remoteCall = new RemoteCall(callbackFuture::complete, 1000);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        // callbackFuture.get() will return when callable is executed (i.e. inside
+        // remoteCall.call()), at which point we can complete it.
+        IBackupCallback callback = callbackFuture.get();
+        callback.operationComplete(3);
+        remoteCall.cancel();
+        assertThat(result.get()).isEqualTo(RemoteResult.successful(3));
+    }
+
+    @Test
+    public void testCall_whenCancelIsCalledBeforeCallbackButAfterCall_returnsCancel()
+            throws Exception {
+        CompletableFuture<IBackupCallback> callbackFuture = new CompletableFuture<>();
+        RemoteCall remoteCall = new RemoteCall(callbackFuture::complete, 1000);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        IBackupCallback callback = callbackFuture.get();
+        remoteCall.cancel();
+        callback.operationComplete(3);
+        assertThat(result.get()).isEqualTo(RemoteResult.FAILED_CANCELLED);
+    }
+
+    @Test
+    public void testCall_whenCancelIsCalledBeforeTimeOutButAfterCall_returnsCancel()
+            throws Exception {
+        ConditionVariable scheduled = new ConditionVariable(false);
+        RemoteCall remoteCall = new RemoteCall(callback -> scheduled.open(), 1000);
+
+        Future<RemoteResult> result = runInWorkerThreadAsync(remoteCall::call);
+
+        scheduled.block();
+        remoteCall.cancel();
+        runToEndOfTasks(Looper.getMainLooper());
+        assertThat(result.get()).isEqualTo(RemoteResult.FAILED_CANCELLED);
+    }
+
+    private static <T> Future<T> runInWorkerThreadAsync(Callable<T> supplier) {
+        CompletableFuture<T> future = new CompletableFuture<>();
+        new Thread(() -> future.complete(uncheck(supplier)), "test-worker-thread").start();
+        return future;
+    }
+
+    private static <T> T runInWorkerThread(Callable<T> supplier) throws Exception {
+        return runInWorkerThreadAsync(supplier).get();
+    }
+
+    /** Unchecked version of {@link Handler#postDelayed(Runnable, long)}. */
+    private static void postDelayed(Handler handler, ThrowingRunnable runnable, long delayMillis) {
+        handler.postDelayed(() -> uncheck(runnable), delayMillis);
+    }
+
+    /** Unchecked version of {@link Handler#post(Runnable)}. */
+    private static void post(Handler handler, ThrowingRunnable runnable) {
+        handler.post(() -> uncheck(runnable));
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
new file mode 100644
index 0000000..f1c4f27
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.backup.remote;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.expectThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class RemoteResultTest {
+    @Test
+    public void testSucceeded_whenSuccessfulResult_returnsTrue() {
+        RemoteResult result = RemoteResult.successful(3);
+
+        boolean succeeded = result.succeeded();
+
+        assertThat(succeeded).isTrue();
+    }
+
+    @Test
+    public void testSucceeded_whenFailedResults_returnsFalse() {
+        boolean timeOutSucceeded = RemoteResult.FAILED_TIMED_OUT.succeeded();
+        boolean cancelledSucceeded = RemoteResult.FAILED_CANCELLED.succeeded();
+        boolean threadInterruptedSucceeded = RemoteResult.FAILED_THREAD_INTERRUPTED.succeeded();
+
+        assertThat(timeOutSucceeded).isFalse();
+        assertThat(cancelledSucceeded).isFalse();
+        assertThat(threadInterruptedSucceeded).isFalse();
+    }
+
+    @Test
+    public void testGet_whenSuccessfulResult_returnsValue() {
+        RemoteResult result = RemoteResult.successful(7);
+
+        long value = result.get();
+
+        assertThat(value).isEqualTo(7);
+    }
+
+    @Test
+    public void testGet_whenFailedResult_throws() {
+        RemoteResult result = RemoteResult.FAILED_TIMED_OUT;
+
+        expectThrows(IllegalStateException.class, result::get);
+    }
+
+    @Test
+    public void testToString() {
+        assertThat(RemoteResult.successful(3).toString()).isEqualTo("RemoteResult{3}");
+        assertThat(RemoteResult.FAILED_TIMED_OUT.toString())
+                .isEqualTo("RemoteResult{FAILED_TIMED_OUT}");
+        assertThat(RemoteResult.FAILED_CANCELLED.toString())
+                .isEqualTo("RemoteResult{FAILED_CANCELLED}");
+        assertThat(RemoteResult.FAILED_THREAD_INTERRUPTED.toString())
+                .isEqualTo("RemoteResult{FAILED_THREAD_INTERRUPTED}");
+    }
+
+    @Test
+    public void testEquals() {
+        assertThat(RemoteResult.successful(3).equals(RemoteResult.successful(3))).isTrue();
+        assertThat(RemoteResult.successful(3).equals(RemoteResult.successful(7))).isFalse();
+        assertThat(RemoteResult.successful(-1).equals(RemoteResult.successful(1))).isFalse();
+        assertThat(RemoteResult.successful(Long.MAX_VALUE).equals(RemoteResult.successful(-1)))
+                .isFalse();
+        assertThat(RemoteResult.successful(3).equals(RemoteResult.FAILED_TIMED_OUT)).isFalse();
+        assertThat(RemoteResult.successful(3).equals("3")).isFalse();
+        assertThat(RemoteResult.successful(3).equals(null)).isFalse();
+        assertThat(RemoteResult.FAILED_TIMED_OUT.equals(RemoteResult.FAILED_TIMED_OUT)).isTrue();
+        assertThat(RemoteResult.FAILED_TIMED_OUT.equals(RemoteResult.FAILED_CANCELLED)).isFalse();
+    }
+
+    /** @see Object#hashCode() */
+    @Test
+    public void testHashCode() {
+        RemoteResult result3 = RemoteResult.successful(3);
+        assertThat(result3.hashCode()).isEqualTo(result3.hashCode());
+        assertThat(result3.hashCode()).isEqualTo(RemoteResult.successful(3).hashCode());
+        assertThat(RemoteResult.FAILED_TIMED_OUT.hashCode())
+                .isEqualTo(RemoteResult.FAILED_TIMED_OUT.hashCode());
+        assertThat(RemoteResult.FAILED_CANCELLED.hashCode())
+                .isEqualTo(RemoteResult.FAILED_CANCELLED.hashCode());
+        assertThat(RemoteResult.FAILED_THREAD_INTERRUPTED.hashCode())
+                .isEqualTo(RemoteResult.FAILED_THREAD_INTERRUPTED.hashCode());
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
new file mode 100644
index 0000000..e0d3c0c
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.backup.remote;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.IBackupManager;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class ServiceBackupCallbackTest {
+    @Test
+    public void testOperationComplete_callsBackupManagerOpComplete() throws Exception {
+        IBackupManager backupManager = mock(IBackupManager.class);
+        ServiceBackupCallback callback = new ServiceBackupCallback(backupManager, 0x68e);
+
+        callback.operationComplete(7);
+
+        verify(backupManager).opComplete(0x68e, 7);
+    }
+}
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 23d4ba4..084f27f 100644
--- a/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.server.backup.testing;
 
+import static com.android.server.backup.testing.TestUtils.runToEndOfTasks;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -46,8 +48,6 @@
 import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.shadows.ShadowBinder;
 import org.robolectric.shadows.ShadowLog;
-import org.robolectric.shadows.ShadowLooper;
-import org.robolectric.shadows.ShadowSystemClock;
 
 import java.io.File;
 import java.lang.Thread.UncaughtExceptionHandler;
@@ -79,14 +79,7 @@
                         baseStateDir,
                         dataDir,
                         transportManager);
-        ShadowLooper shadowBackupLooper = shadowOf(backupThread.getLooper());
-        shadowBackupLooper.runToEndOfTasks();
-        // Handler instances have their own clock, so advancing looper (with runToEndOfTasks())
-        // above does NOT advance the handlers' clock, hence whenever a handler post messages with
-        // specific time to the looper the time of those messages will be before the looper's time.
-        // To fix this we advance SystemClock as well since that is from where the handlers read
-        // time.
-        ShadowSystemClock.setCurrentTimeMillis(shadowBackupLooper.getScheduler().getCurrentTime());
+        runToEndOfTasks(backupThread.getLooper());
         return backupManagerService;
     }
 
diff --git a/services/robotests/src/com/android/server/backup/testing/TestUtils.java b/services/robotests/src/com/android/server/backup/testing/TestUtils.java
index b657dd0..134cfd8 100644
--- a/services/robotests/src/com/android/server/backup/testing/TestUtils.java
+++ b/services/robotests/src/com/android/server/backup/testing/TestUtils.java
@@ -18,15 +18,33 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.robolectric.Shadows.shadowOf;
+
+import android.os.Looper;
+
 import com.android.server.testing.shadows.ShadowEventLog;
 
 import org.robolectric.shadows.ShadowLog;
+import org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowSystemClock;
 
 import java.util.Arrays;
 import java.util.concurrent.Callable;
 import java.util.function.Predicate;
 
 public class TestUtils {
+    /** Version of {@link ShadowLooper#runToEndOfTasks()} that also advances the system clock. */
+    public static void runToEndOfTasks(Looper looper) {
+        ShadowLooper shadowLooper = shadowOf(looper);
+        shadowLooper.runToEndOfTasks();
+        // Handler instances have their own clock, so advancing looper (with runToEndOfTasks())
+        // above does NOT advance the handlers' clock, hence whenever a handler post messages with
+        // specific time to the looper the time of those messages will be before the looper's time.
+        // To fix this we advance SystemClock as well since that is from where the handlers read
+        // time.
+        ShadowSystemClock.setCurrentTimeMillis(shadowLooper.getScheduler().getCurrentTime());
+    }
+
     /** Reset logcat with {@link ShadowLog#reset()} before the test case. */
     public static void assertLogcatAtMost(String tag, int level) {
         assertThat(ShadowLog.getLogsForTag(tag).stream().allMatch(logItem -> logItem.type <= level))
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index 5e7a2522..0dc5130 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -33,6 +33,7 @@
 import java.util.Collections;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.Ignore;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
@@ -163,6 +164,7 @@
         assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
     }
 
+    @Ignore("b/80297700")
     @Test
     public void handleSetSystemAudioMode_setOn_orignalOff() {
         mMusicMute = true;
@@ -190,6 +192,7 @@
         assertThat(mMusicMute).isFalse();
     }
 
+    @Ignore("b/80297700")
     @Test
     public void handleSystemAudioModeRequest_turnOffByTv() {
         assertThat(mMusicMute).isFalse();
@@ -215,6 +218,7 @@
         assertThat(mMusicMute).isTrue();
     }
 
+    @Ignore("b/80297700")
     @Test
     public void onStandbyAudioSystem_currentSystemAudioControlOn() {
         // Set system audio control on first
@@ -298,6 +302,7 @@
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(message);
     }
 
+    @Ignore("b/80297700")
     @Test
     public void terminateSystemAudioMode_systemAudioModeOn() {
         mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(true);
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
index 1d37802..ef87f9d 100644
--- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
@@ -55,6 +55,7 @@
 
 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
 import com.android.server.wm.DisplayFrames;
+import com.android.server.wm.WindowTestUtils.TestDisplayContent;
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import org.junit.Before;
@@ -123,7 +124,6 @@
         mNavigationBar.attrs.gravity = Gravity.BOTTOM;
 
         mPolicy.addWindow(mNavigationBar);
-        mPolicy.mHasNavigationBar = true;
         mPolicy.mLastSystemUiFlags |= View.NAVIGATION_BAR_TRANSPARENT;
     }
 
@@ -245,12 +245,10 @@
                 policy[0].mAccessibilityManager = new AccessibilityManager(context,
                         mock(IAccessibilityManager.class), UserHandle.USER_CURRENT);
                 policy[0].mSystemGestures = mock(SystemGesturesPointerEventListener.class);
-                policy[0].mNavigationBarCanMove = true;
-                policy[0].mPortraitRotation = ROTATION_0;
-                policy[0].mLandscapeRotation = ROTATION_90;
-                policy[0].mUpsideDownRotation = ROTATION_180;
-                policy[0].mSeascapeRotation = ROTATION_270;
-                policy[0].onConfigurationChanged();
+
+                final TestDisplayContent displayContent = TestDisplayContent.create(context);
+                policy[0].setDefaultDisplay(displayContent);
+                policy[0].onConfigurationChanged(displayContent);
             });
             return policy[0];
         }
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index f6599dc..e8d8022 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -42,6 +42,10 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
 /**
  * Tests for the {@link AppWindowToken} class.
  *
@@ -162,6 +166,9 @@
         sWm.mDisplayReady = true;
         sWm.mDisplayEnabled = true;
 
+        final DisplayRotation spiedRotation = spy(mDisplayContent.getDisplayRotation());
+        mDisplayContent.setDisplayRotation(spiedRotation);
+
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
         attrs.setTitle("AppWindow");
@@ -169,20 +176,21 @@
         mToken.addWindow(appWindow);
 
         // Set initial orientation and update.
-        performRotation(Surface.ROTATION_90);
+        performRotation(spiedRotation, Surface.ROTATION_90);
         appWindow.resizeReported = false;
 
         // Update the rotation to perform 180 degree rotation and check that resize was reported.
-        performRotation(Surface.ROTATION_270);
+        performRotation(spiedRotation, Surface.ROTATION_270);
         assertTrue(appWindow.resizeReported);
+
         appWindow.removeImmediately();
     }
 
-    private void performRotation(int rotationToReport) {
-        ((TestWindowManagerPolicy) sWm.mPolicy).rotationToReport = rotationToReport;
+    private void performRotation(DisplayRotation spiedRotation, int rotationToReport) {
+        doReturn(rotationToReport).when(spiedRotation).rotationForOrientation(anyInt(), anyInt());
         sWm.updateRotation(false, false);
-        // Simulate animator finishing orientation change
-        sWm.mRoot.mOrientationChangeComplete = true;
+        // Prevent the next rotation from being deferred by animation.
+        sWm.mAnimator.setScreenRotationAnimationLocked(mDisplayContent.getDisplayId(), null);
         sWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
index a2ccee4..bfc99c8 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
@@ -255,16 +255,32 @@
      * Asserts the top inset of {@param activity} is equal to {@param expected} waiting as needed.
      */
     private void assertTopInsetEquals(Activity activity, int expected) throws Exception {
-        waitFor(() -> getInsets(activity).getSystemWindowInsetTop() == expected);
+        waitForTopInsetEqual(activity, expected);
         assertEquals(expected, getInsets(activity).getSystemWindowInsetTop());
     }
 
+    private void waitForTopInsetEqual(Activity activity, int expected) {
+        waitFor(() -> getInsets(activity).getSystemWindowInsetTop() == expected);
+    }
+
     /**
      * Asserts the inset at {@param side} of {@param activity} is equal to {@param expected}
      * waiting as needed.
      */
     private void assertInsetGreaterOrEqual(Activity activity, int side, int expected)
             throws Exception {
+        waitForInsetGreaterOrEqual(activity, side, expected);
+
+        final WindowInsets insets = getInsets(activity);
+        switch (side) {
+            case TOP: assertGreaterOrEqual(insets.getSystemWindowInsetTop(), expected); break;
+            case BOTTOM: assertGreaterOrEqual(insets.getSystemWindowInsetBottom(), expected); break;
+            case LEFT: assertGreaterOrEqual(insets.getSystemWindowInsetLeft(), expected); break;
+            case RIGHT: assertGreaterOrEqual(insets.getSystemWindowInsetRight(), expected); break;
+        }
+    }
+
+    private void waitForInsetGreaterOrEqual(Activity activity, int side, int expected) {
         waitFor(() -> {
             final WindowInsets insets = getInsets(activity);
             switch (side) {
@@ -275,14 +291,6 @@
                 default: return true;
             }
         });
-
-        final WindowInsets insets = getInsets(activity);
-        switch (side) {
-            case TOP: assertGreaterOrEqual(insets.getSystemWindowInsetTop(), expected); break;
-            case BOTTOM: assertGreaterOrEqual(insets.getSystemWindowInsetBottom(), expected); break;
-            case LEFT: assertGreaterOrEqual(insets.getSystemWindowInsetLeft(), expected); break;
-            case RIGHT: assertGreaterOrEqual(insets.getSystemWindowInsetRight(), expected); break;
-        }
     }
 
     /** Asserts that the first entry is greater than or equal to the second entry. */
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index e4f181b..735e284 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -31,7 +31,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.proto.ProtoOutputStream;
-import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.IWindow;
 import android.view.IWindowManager;
@@ -73,14 +72,7 @@
 
     }
 
-    @Override
-    public boolean isDefaultOrientationForced() {
-        return false;
-    }
-
-    @Override
-    public void setInitialDisplaySize(Display display, int width, int height, int density) {
-
+    public void setDefaultDisplay(DisplayContentInfo displayContentInfo) {
     }
 
     @Override
@@ -389,22 +381,6 @@
     public void onKeyguardOccludedChangedLw(boolean occluded) {
     }
 
-    @Override
-    public int rotationForOrientationLw(int orientation, int lastRotation, boolean defaultDisplay) {
-        return rotationToReport;
-    }
-
-    @Override
-    public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
-        return true;
-    }
-
-    @Override
-    public void setRotationLw(int rotation) {
-
-    }
-
-    @Override
     public void setSafeMode(boolean safeMode) {
 
     }
@@ -440,11 +416,6 @@
     }
 
     @Override
-    public void setCurrentOrientationLw(int newOrientation) {
-
-    }
-
-    @Override
     public boolean performHapticFeedbackLw(WindowState win, int effectId,
             boolean always) {
         return false;
@@ -562,12 +533,13 @@
     }
 
     @Override
-    public void onConfigurationChanged() {
+    public void onConfigurationChanged(DisplayContentInfo displayContentInfo) {
 
     }
 
     @Override
-    public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
+    public boolean shouldRotateSeamlessly(DisplayRotation displayRotation, int oldRotation,
+            int newRotation) {
         return false;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 4864332..431d1a7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -121,13 +121,52 @@
         mStubStack = new TaskStack(sWm, 0, null);
     }
 
-    public void assertRect(Rect rect, int left, int top, int right, int bottom) {
+    // Do not use this function directly in the tests below. Instead, use more explicit function
+    // such as assertFlame().
+    private void assertRect(Rect rect, int left, int top, int right, int bottom) {
         assertEquals(left, rect.left);
         assertEquals(top, rect.top);
         assertEquals(right, rect.right);
         assertEquals(bottom, rect.bottom);
     }
 
+    private void assertContentInset(WindowState w, int left, int top, int right, int bottom) {
+        assertRect(w.mContentInsets, left, top, right, bottom);
+    }
+
+    private void assertVisibleInset(WindowState w, int left, int top, int right, int bottom) {
+        assertRect(w.mVisibleInsets, left, top, right, bottom);
+    }
+
+    private void assertStableInset(WindowState w, int left, int top, int right, int bottom) {
+        assertRect(w.mStableInsets, left, top, right, bottom);
+    }
+
+    private void assertFrame(WindowState w, int left, int top, int right, int bottom) {
+        assertRect(w.getFrameLw(), left, top, right, bottom);
+    }
+
+    private void assertContentFrame(WindowState w, Rect expectedRect) {
+        assertRect(w.getContentFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
+                expectedRect.bottom);
+    }
+
+    private void assertVisibleFrame(WindowState w, Rect expectedRect) {
+        assertRect(w.getVisibleFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
+                expectedRect.bottom);
+    }
+
+    private void assertStableFrame(WindowState w, Rect expectedRect) {
+        assertRect(w.getStableFrameLw(), expectedRect.left, expectedRect.top, expectedRect.right,
+                expectedRect.bottom);
+    }
+
+    private void assertPolicyCrop(WindowStateWithTask w, int left, int top, int right, int bottom) {
+        Rect policyCrop = new Rect();
+        w.calculatePolicyCrop(policyCrop);
+        assertRect(policyCrop, left, top, right, bottom);
+    }
+
     @Test
     public void testLayoutInFullscreenTaskInsets() throws Exception {
         Task task = new TaskWithBounds(null); // fullscreen task doesn't use bounds for computeFrame
@@ -163,14 +202,13 @@
         // and stable frames work the same way.
         final WindowFrames windowFrames = new WindowFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(),0, 0, 1000, 1000);
-        assertRect(w.mContentInsets, 0, topContentInset, 0, bottomContentInset);
-        assertRect(w.mVisibleInsets, 0, topVisibleInset, 0, bottomVisibleInset);
-        assertRect(w.mStableInsets, leftStableInset, 0, rightStableInset, 0);
-        // The frames remain as passed in shrunk to the window frame
-        assertTrue(cf.equals(w.getContentFrameLw()));
-        assertTrue(vf.equals(w.getVisibleFrameLw()));
-        assertTrue(sf.equals(w.getStableFrameLw()));
+        assertFrame(w, 0, 0, 1000, 1000);
+        assertContentInset(w, 0, topContentInset, 0, bottomContentInset);
+        assertVisibleInset(w, 0, topVisibleInset, 0, bottomVisibleInset);
+        assertStableInset(w, leftStableInset, 0, rightStableInset, 0);
+        assertContentFrame(w, cf);
+        assertVisibleFrame(w, vf);
+        assertStableFrame(w, sf);
         // On the other hand getFrame() doesn't extend past cf we won't get any insets
         w.mAttrs.x = 100;
         w.mAttrs.y = 100;
@@ -178,12 +216,12 @@
         w.mRequestedWidth = 100;
         w.mRequestedHeight = 100;
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), 100, 100, 200, 200);
-        assertRect(w.mContentInsets, 0, 0, 0, 0);
+        assertFrame(w, 100, 100, 200, 200);
+        assertContentInset(w, 0, 0, 0, 0);
         // In this case the frames are shrunk to the window frame.
-        assertTrue(w.getFrameLw().equals(w.getContentFrameLw()));
-        assertTrue(w.getFrameLw().equals(w.getVisibleFrameLw()));
-        assertTrue(w.getFrameLw().equals(w.getStableFrameLw()));
+        assertContentFrame(w, w.getFrameLw());
+        assertVisibleFrame(w, w.getFrameLw());
+        assertStableFrame(w, w.getFrameLw());
     }
 
     @Test
@@ -200,7 +238,7 @@
         // so we expect it to fill the entire available frame.
         final WindowFrames windowFrames = new WindowFrames(pf, pf, pf, pf, pf, pf, pf, pf);
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), 0, 0, 1000, 1000);
+        assertFrame(w, 0, 0, 1000, 1000);
 
         // It can select various widths and heights within the bounds.
         // Strangely the window attribute width is ignored for normal windows
@@ -210,14 +248,14 @@
         w.computeFrameLw(windowFrames);
         // Explicit width and height without requested width/height
         // gets us nothing.
-        assertRect(w.getFrameLw(), 0, 0, 0, 0);
+        assertFrame(w, 0, 0, 0, 0);
 
         w.mRequestedWidth = 300;
         w.mRequestedHeight = 300;
         w.computeFrameLw(windowFrames);
         // With requestedWidth/Height we can freely choose our size within the
         // parent bounds.
-        assertRect(w.getFrameLw(), 0, 0, 300, 300);
+        assertFrame(w, 0, 0, 300, 300);
 
         // With FLAG_SCALED though, requestedWidth/height is used to control
         // the unscaled surface size, and mAttrs.width/height becomes the
@@ -228,14 +266,14 @@
         w.mAttrs.width = 100;
         w.mAttrs.height = 100;
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), 0, 0, 100, 100);
+        assertFrame(w, 0, 0, 100, 100);
         w.mAttrs.flags = 0;
 
         // But sizes too large will be clipped to the containing frame
         w.mRequestedWidth = 1200;
         w.mRequestedHeight = 1200;
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), 0, 0, 1000, 1000);
+        assertFrame(w, 0, 0, 1000, 1000);
 
         // Before they are clipped though windows will be shifted
         w.mAttrs.x = 300;
@@ -243,7 +281,7 @@
         w.mRequestedWidth = 1000;
         w.mRequestedHeight = 1000;
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), 0, 0, 1000, 1000);
+        assertFrame(w, 0, 0, 1000, 1000);
 
         // If there is room to move around in the parent frame the window will be shifted according
         // to gravity.
@@ -253,16 +291,16 @@
         w.mRequestedHeight = 300;
         w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), 700, 0, 1000, 300);
+         assertFrame(w, 700, 0, 1000, 300);
         w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), 700, 700, 1000, 1000);
+        assertFrame(w, 700, 700, 1000, 1000);
         // Window specified  x and y are interpreted as offsets in the opposite
         // direction of gravity
         w.mAttrs.x = 100;
         w.mAttrs.y = 100;
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), 600, 600, 900, 900);
+        assertFrame(w, 600, 600, 900, 900);
     }
 
     @Test
@@ -286,24 +324,23 @@
         w.computeFrameLw(windowFrames);
         // For non fullscreen tasks the containing frame is based off the
         // task bounds not the parent frame.
-        assertRect(w.getFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
-        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
-        assertRect(w.mContentInsets, 0, 0, 0, 0);
+        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
+        assertContentFrame(w, taskBounds);
+        assertContentInset(w, 0, 0, 0, 0);
 
         pf.set(0, 0, logicalWidth, logicalHeight);
         // We still produce insets against the containing frame the same way.
         final int cfRight = logicalWidth / 2;
         final int cfBottom = logicalHeight / 2;
         final Rect cf = new Rect(0, 0, cfRight, cfBottom);
-
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
+        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
         int contentInsetRight = taskRight - cfRight;
         int contentInsetBottom = taskBottom - cfBottom;
-        assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
-        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
-                taskBottom - contentInsetBottom);
+        assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
+        assertContentFrame(w, new Rect(taskLeft, taskTop, taskRight - contentInsetRight,
+                taskBottom - contentInsetBottom));
 
         pf.set(0, 0, logicalWidth, logicalHeight);
         // However if we set temp inset bounds, the insets will be computed
@@ -314,15 +351,14 @@
         final int insetRight = insetLeft + (taskRight - taskLeft);
         final int insetBottom = insetTop + (taskBottom - taskTop);
         task.mInsetBounds.set(insetLeft, insetTop, insetRight, insetBottom);
-
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw(windowFrames);
-        assertRect(w.getFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
+        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
         contentInsetRight = insetRight - cfRight;
         contentInsetBottom = insetBottom - cfBottom;
-        assertRect(w.mContentInsets, 0, 0, contentInsetRight, contentInsetBottom);
-        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight - contentInsetRight,
-                taskBottom - contentInsetBottom);
+        assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
+        assertContentFrame(w, new Rect(taskLeft, taskTop, taskRight - contentInsetRight,
+                taskBottom - contentInsetBottom));
     }
 
     @Test
@@ -344,20 +380,16 @@
         final Rect vf = cf;
         final Rect sf = vf;
         // We use a decor content frame with insets to produce cropping.
-        Rect dcf = cf;
-
-        final Rect policyCrop = new Rect();
+        Rect dcf = new Rect(cf);
 
         final WindowFrames windowFrames = new WindowFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
         w.computeFrameLw(windowFrames);
-        w.calculatePolicyCrop(policyCrop);
-        assertRect(policyCrop, 0, cf.top, logicalWidth, cf.bottom);
+        assertPolicyCrop(w, 0, cf.top, logicalWidth, cf.bottom);
 
         windowFrames.mDecorFrame.setEmpty();
         // Likewise with no decor frame we would get no crop
         w.computeFrameLw(windowFrames);
-        w.calculatePolicyCrop(policyCrop);
-        assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);
+        assertPolicyCrop(w, 0, 0, logicalWidth, logicalHeight);
 
         // Now we set up a window which doesn't fill the entire decor frame.
         // Normally it would be cropped to it's frame but in the case of docked resizing
@@ -372,16 +404,14 @@
         w.mRequestedHeight = logicalHeight / 2;
         w.computeFrameLw(windowFrames);
 
-        w.calculatePolicyCrop(policyCrop);
         // Normally the crop is shrunk from the decor frame
         // to the computed window frame.
-        assertRect(policyCrop, 0, 0, logicalWidth / 2, logicalHeight / 2);
+        assertPolicyCrop(w, 0, 0, logicalWidth / 2, logicalHeight / 2);
 
         w.mDockedResizingForTest = true;
-        w.calculatePolicyCrop(policyCrop);
         // But if we are docked resizing it won't be, however we will still be
         // shrunk to the decor frame and the display.
-        assertRect(policyCrop, 0, 0,
+        assertPolicyCrop(w, 0, 0,
                 Math.min(pf.width(), displayInfo.logicalWidth),
                 Math.min(pf.height(), displayInfo.logicalHeight));
     }
@@ -409,9 +439,9 @@
         w.computeFrameLw(windowFrames);
         // For non fullscreen tasks the containing frame is based off the
         // task bounds not the parent frame.
-        assertRect(w.getFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
-        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
-        assertRect(w.mContentInsets, 0, 0, 0, 0);
+        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
+        assertContentFrame(w, taskBounds);
+        assertContentInset(w, 0, 0, 0, 0);
 
         // Now simulate switch to fullscreen for letterboxed app.
         final int xInset = logicalWidth / 10;
@@ -422,12 +452,11 @@
         w.mAppToken.onOverrideConfigurationChanged(config);
         pf.set(0, 0, logicalWidth, logicalHeight);
         task.mFullscreenForTest = true;
-
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw(windowFrames);
-        assertEquals(cf, w.getFrameLw());
-        assertEquals(cf, w.getContentFrameLw());
-        assertRect(w.mContentInsets, 0, 0, 0, 0);
+        assertFrame(w, cf.left, cf.top, cf.right, cf.bottom);
+        assertContentFrame(w, cf);
+        assertContentInset(w, 0, 0, 0, 0);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index a48a3b9..a1b1640 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -22,8 +22,10 @@
 import android.graphics.Rect;
 import android.os.Binder;
 import android.os.IBinder;
+import android.view.Display;
 import android.view.IApplicationToken;
 import android.view.IWindow;
+import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 import android.view.WindowManager;
@@ -60,6 +62,37 @@
         return service;
     }
 
+    /** An extension of {@link DisplayContent} to gain package scoped access. */
+    public static class TestDisplayContent extends DisplayContent {
+
+        private TestDisplayContent(Display display, WindowManagerService service,
+                WallpaperController wallpaperController, DisplayWindowController controller) {
+            super(display, service, wallpaperController, controller);
+        }
+
+        /** Create a mocked default {@link DisplayContent}. */
+        public static TestDisplayContent create(Context context) {
+            final TestDisplayContent displayContent = mock(TestDisplayContent.class);
+            displayContent.isDefaultDisplay = true;
+
+            final DisplayPolicy displayPolicy = mock(DisplayPolicy.class);
+            when(displayPolicy.navigationBarCanMove()).thenReturn(true);
+            when(displayPolicy.hasNavigationBar()).thenReturn(true);
+
+            final DisplayRotation displayRotation = new DisplayRotation(
+                    mock(WindowManagerService.class), displayContent, displayPolicy,
+                    context, new Object());
+            displayRotation.mPortraitRotation = Surface.ROTATION_0;
+            displayRotation.mLandscapeRotation = Surface.ROTATION_90;
+            displayRotation.mUpsideDownRotation = Surface.ROTATION_180;
+            displayRotation.mSeascapeRotation = Surface.ROTATION_270;
+
+            when(displayContent.getDisplayRotation()).thenReturn(displayRotation);
+
+            return displayContent;
+        }
+    }
+
     /**
      * Creates a mock instance of {@link StackWindowController}.
      */
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index 742ad65..f255d49 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -95,6 +95,7 @@
             assertEquals(getUserSentiment(i), ranking.getUserSentiment());
             assertEquals(getHidden(i), ranking.isSuspended());
             assertActionsEqual(getSmartActions(key, i), ranking.getSmartActions());
+            assertEquals(getSmartReplies(key, i), ranking.getSmartReplies());
         }
     }
 
@@ -112,6 +113,7 @@
         Bundle userSentiment = new Bundle();
         Bundle mHidden = new Bundle();
         Bundle smartActions = new Bundle();
+        Bundle smartReplies = new Bundle();
 
         for (int i = 0; i < mKeys.length; i++) {
             String key = mKeys[i];
@@ -130,12 +132,13 @@
             userSentiment.putInt(key, getUserSentiment(i));
             mHidden.putBoolean(key, getHidden(i));
             smartActions.putParcelableArrayList(key, getSmartActions(key, i));
+            smartReplies.putCharSequenceArrayList(key, getSmartReplies(key, i));
         }
         NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
                 interceptedKeys.toArray(new String[0]), visibilityOverrides,
                 suppressedVisualEffects, importance, explanation, overrideGroupKeys,
                 channels, overridePeople, snoozeCriteria, showBadge, userSentiment, mHidden,
-                smartActions);
+                smartActions, smartReplies);
         return update;
     }
 
@@ -216,6 +219,14 @@
         return actions;
     }
 
+    private ArrayList<CharSequence> getSmartReplies(String key, int index) {
+        ArrayList<CharSequence> choices = new ArrayList<>();
+        for (int i = 0; i < index; i++) {
+            choices.add("choice_" + key + "_" + i);
+        }
+        return choices;
+    }
+
     private void assertActionsEqual(
             List<Notification.Action> expecteds, List<Notification.Action> actuals) {
         assertEquals(expecteds.size(), actuals.size());
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 66285c3..0cbb1aa 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -111,6 +111,7 @@
 import android.text.Html;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
+import android.util.Log;
 
 import com.android.internal.R;
 import com.android.internal.statusbar.NotificationVisibility;
@@ -199,6 +200,7 @@
     // Use a Testable subclass so we can simulate calls from the system without failing.
     private static class TestableNotificationManagerService extends NotificationManagerService {
         int countSystemChecks = 0;
+        boolean isSystemUid = true;
 
         public TestableNotificationManagerService(Context context) {
             super(context);
@@ -207,13 +209,13 @@
         @Override
         protected boolean isCallingUidSystem() {
             countSystemChecks++;
-            return true;
+            return isSystemUid;
         }
 
         @Override
         protected boolean isCallerSystemOrPhone() {
             countSystemChecks++;
-            return true;
+            return isSystemUid;
         }
 
         @Override
@@ -651,6 +653,79 @@
         assertNull(mService.getNotificationRecord(sbn.getKey()));
     }
 
+    /**
+     * Confirm the system user on automotive devices can use car categories
+     */
+    @Test
+    public void testEnqueuedRestrictedNotifications_asSystem() throws Exception {
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
+                .thenReturn(true);
+        List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
+                Notification.CATEGORY_CAR_WARNING,
+                Notification.CATEGORY_CAR_INFORMATION);
+        int id = 0;
+        for (String category: categories) {
+            final StatusBarNotification sbn =
+                    generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
+            sbn.getNotification().category = category;
+            mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+                    sbn.getId(), sbn.getNotification(), sbn.getUserId());
+        }
+        waitForIdle();
+        assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
+    }
+
+
+    /**
+     * Confirm restricted notification categories only apply to automotive.
+     */
+    @Test
+    public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception {
+        mService.isSystemUid = false;
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
+                .thenReturn(false);
+        List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
+                Notification.CATEGORY_CAR_WARNING,
+                Notification.CATEGORY_CAR_INFORMATION);
+        int id = 0;
+        for (String category: categories) {
+            final StatusBarNotification sbn =
+                    generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn;
+            sbn.getNotification().category = category;
+            mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+                    sbn.getId(), sbn.getNotification(), sbn.getUserId());
+        }
+        waitForIdle();
+        assertEquals(categories.size(), mBinderService.getActiveNotifications(PKG).length);
+    }
+
+    /**
+     * Confirm if a non-system user tries to use the car categories on a automotive device that
+     * they will get a security exception
+     */
+    @Test
+    public void testEnqueuedRestrictedNotifications_badUser() throws Exception {
+        mService.isSystemUid = false;
+        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0))
+                .thenReturn(true);
+        List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY,
+                Notification.CATEGORY_CAR_WARNING,
+                Notification.CATEGORY_CAR_INFORMATION);
+        for (String category: categories) {
+            final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
+            sbn.getNotification().category = category;
+            try {
+                mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+                        sbn.getId(), sbn.getNotification(), sbn.getUserId());
+                fail("Calls from non system apps should not allow use of restricted categories");
+            } catch (SecurityException e) {
+                // pass
+            }
+        }
+        waitForIdle();
+        assertEquals(0, mBinderService.getActiveNotifications(PKG).length);
+    }
+
     @Test
     public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 22958d4..62fc9c4 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -843,6 +843,7 @@
         public void onRemoteRttRequest(Connection c) {}
         /** @hide */
         public void onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle) {}
+        public void onConnectionTimeReset(Connection c) {}
     }
 
     /**
@@ -2372,6 +2373,16 @@
     }
 
     /**
+     * @hide
+     * Resets the cdma connection time.
+     */
+    public final void resetConnectionTime() {
+        for (Listener l : mListeners) {
+            l.onConnectionTimeReset(this);
+        }
+    }
+
+    /**
      * Returns the connections or conferences with which this connection can be conferenced.
      */
     public final List<Conferenceable> getConferenceables() {
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 2291090..61adcdd 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -1474,6 +1474,13 @@
                 mAdapter.onPhoneAccountChanged(id, pHandle);
             }
         }
+
+        public void onConnectionTimeReset(Connection c) {
+            String id = mIdByConnection.get(c);
+            if (id != null) {
+                mAdapter.resetConnectionTime(id);
+            }
+        }
     };
 
     /** {@inheritDoc} */
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 0d319bb..520e7ed 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -255,6 +255,18 @@
     }
 
     /**
+        * Resets the cdma connection time.
+        */
+    void resetConnectionTime(String callId) {
+        for (IConnectionServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.resetConnectionTime(callId, Log.getExternalSession());
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    /**
      * Indicates that the call no longer exists. Can be used with either a call or a conference
      * call.
      *
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 3e1bf77..78d65e6 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -610,6 +610,11 @@
         public void onConnectionServiceFocusReleased(Session.Info sessionInfo) {
             mHandler.obtainMessage(MSG_CONNECTION_SERVICE_FOCUS_RELEASED).sendToTarget();
         }
+
+        @Override
+        public void resetConnectionTime(String callId, Session.Info sessionInfo) {
+            // Do nothing
+        }
     };
 
     public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index bb4b483..9821dcb 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -466,6 +466,11 @@
                 Log.w(this, "onRemoteRttRequest called on a remote conference");
             }
         }
+
+        @Override
+        public void resetConnectionTime(String callId, Session.Info sessionInfo) {
+            // Do nothing
+        }
     };
 
     private final ConnectionServiceAdapterServant mServant =
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index be474bd..0157a58 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -121,4 +121,6 @@
     in Session.Info sessionInfo);
 
     void onConnectionServiceFocusReleased(in Session.Info sessionInfo);
+
+    void resetConnectionTime(String callIdi, in Session.Info sessionInfo);
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9e23c5c..b2eb5e0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1553,7 +1553,8 @@
             ITelephony telephony = getITelephony();
             if (telephony == null)
                 return null;
-            return telephony.getNeighboringCellInfo(mContext.getOpPackageName());
+            return telephony.getNeighboringCellInfo(mContext.getOpPackageName(),
+                    mContext.getApplicationInfo().targetSdkVersion);
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
diff --git a/telephony/java/com/android/ims/internal/uce/common/CapInfo.java b/telephony/java/com/android/ims/internal/uce/common/CapInfo.java
index 56969a8..a9847ba 100644
--- a/telephony/java/com/android/ims/internal/uce/common/CapInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/common/CapInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.common;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -73,6 +74,7 @@
     /**
      * Constructor for the CapInfo class.
      */
+    @UnsupportedAppUsage
     public CapInfo() {
     };
 
@@ -80,6 +82,7 @@
     /**
      * Checks whether IM is supported.
      */
+    @UnsupportedAppUsage
     public boolean isImSupported() {
         return mImSupported;
     }
@@ -87,6 +90,7 @@
     /**
      * Sets IM as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setImSupported(boolean imSupported) {
         this.mImSupported = imSupported;
     }
@@ -94,6 +98,7 @@
     /**
      * Checks whether FT Thumbnail is supported.
      */
+    @UnsupportedAppUsage
     public boolean isFtThumbSupported() {
         return mFtThumbSupported;
     }
@@ -101,6 +106,7 @@
     /**
      * Sets FT thumbnail as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setFtThumbSupported(boolean ftThumbSupported) {
         this.mFtThumbSupported = ftThumbSupported;
     }
@@ -110,6 +116,7 @@
     /**
      * Checks whether FT Store and Forward is supported
      */
+    @UnsupportedAppUsage
     public boolean isFtSnFSupported() {
         return  mFtSnFSupported;
     }
@@ -117,6 +124,7 @@
     /**
      * Sets FT Store and Forward as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setFtSnFSupported(boolean  ftSnFSupported) {
         this.mFtSnFSupported =  ftSnFSupported;
     }
@@ -124,6 +132,7 @@
    /**
     * Checks whether File transfer HTTP is supported.
     */
+   @UnsupportedAppUsage
    public boolean isFtHttpSupported() {
        return  mFtHttpSupported;
    }
@@ -131,6 +140,7 @@
    /**
     * Sets File transfer HTTP as supported or not supported.
     */
+   @UnsupportedAppUsage
    public void setFtHttpSupported(boolean  ftHttpSupported) {
        this.mFtHttpSupported =  ftHttpSupported;
    }
@@ -138,6 +148,7 @@
     /**
      * Checks whether FT is supported.
      */
+    @UnsupportedAppUsage
     public boolean isFtSupported() {
         return mFtSupported;
     }
@@ -145,6 +156,7 @@
     /**
      * Sets FT as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setFtSupported(boolean ftSupported) {
         this.mFtSupported = ftSupported;
     }
@@ -152,6 +164,7 @@
     /**
      * Checks whether IS is supported.
      */
+    @UnsupportedAppUsage
     public boolean isIsSupported() {
         return mIsSupported;
     }
@@ -159,6 +172,7 @@
     /**
      * Sets IS as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setIsSupported(boolean isSupported) {
         this.mIsSupported = isSupported;
     }
@@ -166,6 +180,7 @@
     /**
      * Checks whether video sharing is supported during a CS call.
      */
+    @UnsupportedAppUsage
     public boolean isVsDuringCSSupported() {
         return mVsDuringCSSupported;
     }
@@ -174,6 +189,7 @@
      *  Sets video sharing as supported or not supported during a CS
      *  call.
      */
+    @UnsupportedAppUsage
     public void setVsDuringCSSupported(boolean vsDuringCSSupported) {
         this.mVsDuringCSSupported = vsDuringCSSupported;
     }
@@ -182,6 +198,7 @@
      *  Checks whether video sharing outside a voice call is
      *   supported.
      */
+    @UnsupportedAppUsage
     public boolean isVsSupported() {
         return mVsSupported;
     }
@@ -189,6 +206,7 @@
     /**
      * Sets video sharing as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setVsSupported(boolean vsSupported) {
         this.mVsSupported = vsSupported;
     }
@@ -196,6 +214,7 @@
     /**
      * Checks whether social presence is supported.
      */
+    @UnsupportedAppUsage
     public boolean isSpSupported() {
         return mSpSupported;
     }
@@ -203,6 +222,7 @@
     /**
      * Sets social presence as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setSpSupported(boolean spSupported) {
         this.mSpSupported = spSupported;
     }
@@ -211,6 +231,7 @@
      * Checks whether capability discovery via presence is
      * supported.
      */
+    @UnsupportedAppUsage
     public boolean isCdViaPresenceSupported() {
         return mCdViaPresenceSupported;
     }
@@ -219,6 +240,7 @@
      * Sets capability discovery via presence as supported or not
      * supported.
      */
+    @UnsupportedAppUsage
     public void setCdViaPresenceSupported(boolean cdViaPresenceSupported) {
         this.mCdViaPresenceSupported = cdViaPresenceSupported;
     }
@@ -226,6 +248,7 @@
     /**
      * Checks whether IP voice call is supported.
      */
+    @UnsupportedAppUsage
     public boolean isIpVoiceSupported() {
         return mIpVoiceSupported;
     }
@@ -233,6 +256,7 @@
     /**
      * Sets IP voice call as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setIpVoiceSupported(boolean ipVoiceSupported) {
         this.mIpVoiceSupported = ipVoiceSupported;
     }
@@ -240,6 +264,7 @@
     /**
      * Checks whether IP video call is supported.
      */
+    @UnsupportedAppUsage
     public boolean isIpVideoSupported() {
         return mIpVideoSupported;
     }
@@ -247,6 +272,7 @@
     /**
      * Sets IP video call as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setIpVideoSupported(boolean ipVideoSupported) {
         this.mIpVideoSupported = ipVideoSupported;
     }
@@ -255,6 +281,7 @@
     * Checks whether Geo location Pull using File Transfer is
     * supported.
     */
+   @UnsupportedAppUsage
    public boolean isGeoPullFtSupported() {
        return mGeoPullFtSupported;
    }
@@ -263,6 +290,7 @@
     * Sets Geo location Pull using File Transfer as supported or
     * not supported.
     */
+   @UnsupportedAppUsage
    public void setGeoPullFtSupported(boolean geoPullFtSupported) {
        this.mGeoPullFtSupported = geoPullFtSupported;
    }
@@ -270,6 +298,7 @@
     /**
      * Checks whether Geo Pull is supported.
      */
+    @UnsupportedAppUsage
     public boolean isGeoPullSupported() {
         return mGeoPullSupported;
     }
@@ -277,6 +306,7 @@
     /**
      * Sets Geo Pull as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setGeoPullSupported(boolean geoPullSupported) {
         this.mGeoPullSupported = geoPullSupported;
     }
@@ -284,6 +314,7 @@
     /**
      * Checks whether Geo Push is supported.
      */
+    @UnsupportedAppUsage
     public boolean isGeoPushSupported() {
         return mGeoPushSupported;
     }
@@ -291,6 +322,7 @@
     /**
      * Sets Geo Push as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setGeoPushSupported(boolean geoPushSupported) {
         this.mGeoPushSupported = geoPushSupported;
     }
@@ -298,6 +330,7 @@
     /**
      * Checks whether short messaging is supported.
      */
+    @UnsupportedAppUsage
     public boolean isSmSupported() {
         return mSmSupported;
     }
@@ -305,6 +338,7 @@
     /**
      * Sets short messaging as supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setSmSupported(boolean smSupported) {
         this.mSmSupported = smSupported;
     }
@@ -312,18 +346,22 @@
     /**
      * Checks whether store/forward and group chat are supported.
      */
+    @UnsupportedAppUsage
     public boolean isFullSnFGroupChatSupported() {
         return mFullSnFGroupChatSupported;
     }
 
+    @UnsupportedAppUsage
     public boolean isRcsIpVoiceCallSupported() {
         return mRcsIpVoiceCallSupported;
     }
 
+    @UnsupportedAppUsage
     public boolean isRcsIpVideoCallSupported() {
         return mRcsIpVideoCallSupported;
     }
 
+    @UnsupportedAppUsage
     public boolean isRcsIpVideoOnlyCallSupported() {
         return mRcsIpVideoOnlyCallSupported;
     }
@@ -331,16 +369,20 @@
     /**
      * Sets store/forward and group chat supported or not supported.
      */
+    @UnsupportedAppUsage
     public void setFullSnFGroupChatSupported(boolean fullSnFGroupChatSupported) {
         this.mFullSnFGroupChatSupported = fullSnFGroupChatSupported;
     }
 
+    @UnsupportedAppUsage
     public void setRcsIpVoiceCallSupported(boolean rcsIpVoiceCallSupported) {
         this.mRcsIpVoiceCallSupported = rcsIpVoiceCallSupported;
     }
+    @UnsupportedAppUsage
     public void setRcsIpVideoCallSupported(boolean rcsIpVideoCallSupported) {
         this.mRcsIpVideoCallSupported = rcsIpVideoCallSupported;
     }
+    @UnsupportedAppUsage
     public void setRcsIpVideoOnlyCallSupported(boolean rcsIpVideoOnlyCallSupported) {
         this.mRcsIpVideoOnlyCallSupported = rcsIpVideoOnlyCallSupported;
     }
@@ -351,17 +393,20 @@
     }
 
     /** Sets the list of supported extensions. */
+    @UnsupportedAppUsage
     public void setExts(String[] exts) {
         this.mExts = exts;
     }
 
 
     /** Gets the time stamp for when to query again. */
+    @UnsupportedAppUsage
     public long getCapTimestamp() {
         return mCapTimestamp;
     }
 
     /** Sets the time stamp for when to query again. */
+    @UnsupportedAppUsage
     public void setCapTimestamp(long capTimestamp) {
         this.mCapTimestamp = capTimestamp;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/common/StatusCode.java b/telephony/java/com/android/ims/internal/uce/common/StatusCode.java
index ad9b669..3921cfb 100644
--- a/telephony/java/com/android/ims/internal/uce/common/StatusCode.java
+++ b/telephony/java/com/android/ims/internal/uce/common/StatusCode.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.common;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -71,12 +72,14 @@
      * Constructor for the StatusCode class.
      * @hide
      */
+    @UnsupportedAppUsage
     public StatusCode() {}
 
     /**
      *  Gets the status code.
      *  @hide
      */
+    @UnsupportedAppUsage
     public int getStatusCode() {
         return mStatusCode;
     }
@@ -85,6 +88,7 @@
      *  Sets the status code.
      *  @hide
      */
+    @UnsupportedAppUsage
     public void setStatusCode(int nStatusCode) {
         this.mStatusCode = nStatusCode;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/common/UceLong.java b/telephony/java/com/android/ims/internal/uce/common/UceLong.java
index fd07fe8..7207899 100644
--- a/telephony/java/com/android/ims/internal/uce/common/UceLong.java
+++ b/telephony/java/com/android/ims/internal/uce/common/UceLong.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.common;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -32,6 +33,7 @@
      * Constructor for the UceLong class.
      * @hide
      */
+    @UnsupportedAppUsage
     public UceLong() {
     };
 
@@ -39,6 +41,7 @@
      * Gets the long value.
      * @hide
      */
+    @UnsupportedAppUsage
     public long getUceLong() {
         return mUceLong;
     }
@@ -47,6 +50,7 @@
      * Sets the long value.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUceLong(long uceLong) {
         this.mUceLong = uceLong;
     }
@@ -54,6 +58,7 @@
     /** Get the client ID as integer value.
      *  @hide
      */
+    @UnsupportedAppUsage
     public int getClientId() {
         return mClientId;
     }
@@ -62,6 +67,7 @@
      * Set the client ID as integer value.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setClientId(int nClientId) {
         this.mClientId = nClientId;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java b/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
index c570f49..bcb9f2d 100644
--- a/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
@@ -15,6 +15,7 @@
  */
 package com.android.ims.internal.uce.options;
 
+import android.annotation.UnsupportedAppUsage;
 import com.android.ims.internal.uce.common.CapInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -30,10 +31,12 @@
         return new OptionsCapInfo();
     }
 
+    @UnsupportedAppUsage
     public String getSdp() {
         return mSdp;
     }
 
+    @UnsupportedAppUsage
     public void setSdp(String sdp) {
         this.mSdp = sdp;
     }
@@ -41,16 +44,19 @@
     /**
      * Constructor for the OptionsCapInfo class.
      */
+    @UnsupportedAppUsage
     public OptionsCapInfo() {
         mCapInfo = new CapInfo();
     };
 
+    @UnsupportedAppUsage
     public CapInfo getCapInfo() {
         return mCapInfo;
     }
     /**
      * Sets the CapInfo
      */
+    @UnsupportedAppUsage
     public void setCapInfo(CapInfo capInfo) {
         this.mCapInfo = capInfo;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java b/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java
index 35f769c..14c64ac 100644
--- a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java
+++ b/telephony/java/com/android/ims/internal/uce/options/OptionsCmdId.java
@@ -17,6 +17,7 @@
 package com.android.ims.internal.uce.options;
 
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -55,6 +56,7 @@
      * Sets the command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(int nCmdId) {
         this.mCmdId = nCmdId;
     }
@@ -63,6 +65,7 @@
      * Constructor for the OptionsCDCmdId class.
      * @hide
      */
+    @UnsupportedAppUsage
     public OptionsCmdId(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java b/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
index dab191c..4af3e6e 100644
--- a/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
+++ b/telephony/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
@@ -19,6 +19,7 @@
 import com.android.ims.internal.uce.common.StatusCode;
 import com.android.ims.internal.uce.common.CapInfo;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -41,6 +42,7 @@
      * Sets the command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(OptionsCmdId cmdId) {
         this.mCmdId = cmdId;
     }
@@ -56,6 +58,7 @@
     /**
        Sets the user data.
        @hide  */
+    @UnsupportedAppUsage
     public void setUserData(int userData) {
         this.mUserData = userData;
     }
@@ -72,6 +75,7 @@
      * Sets the status code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setStatus(StatusCode status) {
         this.mStatus = status;
     }
@@ -80,6 +84,7 @@
      * Constructor for the OptionsCmdStatus class.
      * @hide
      */
+    @UnsupportedAppUsage
     public OptionsCmdStatus() {
         mStatus = new StatusCode();
         mCapInfo = new CapInfo();
@@ -96,6 +101,7 @@
      * Sets the CapInfo
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCapInfo(CapInfo capInfo) {
         this.mCapInfo = capInfo;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java b/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
index 0b9dd21..c5f333d 100644
--- a/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
+++ b/telephony/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.options;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -41,6 +42,7 @@
      * Sets the Options command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(OptionsCmdId cmdId) {
         this.mCmdId = cmdId;
     }
@@ -57,6 +59,7 @@
      * Sets the request ID
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRequestId(int requestId) {
         this.mRequestId = requestId;
     }
@@ -73,6 +76,7 @@
      * Sets the SIP response code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSipResponseCode(int sipResponseCode) {
         this.mSipResponseCode = sipResponseCode;
     }
@@ -89,6 +93,7 @@
      * Sets the SIP response code reason phrase.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setReasonPhrase(String reasonPhrase) {
         this.mReasonPhrase = reasonPhrase;
     }
@@ -105,6 +110,7 @@
      * Sets the SIP retryAfter sec value
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRetryAfter(int retryAfter) {
         this.mRetryAfter = retryAfter;
     }
@@ -113,6 +119,7 @@
      * Constructor for the OptionsSipResponse class.
      * @hide
      */
+    @UnsupportedAppUsage
     public OptionsSipResponse() {
         mCmdId = new OptionsCmdId();
     };
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java
index 60fc226..745df5b 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresCapInfo.java
@@ -18,6 +18,7 @@
 
 import com.android.ims.internal.uce.common.CapInfo;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -26,12 +27,14 @@
 public class PresCapInfo implements Parcelable {
 
     private CapInfo mCapInfo;
+    @UnsupportedAppUsage
     private String mContactUri = "";
 
     /**
      * Gets the UCE capability information.
      * @hide
      */
+    @UnsupportedAppUsage
     public CapInfo getCapInfo() {
         return mCapInfo;
     }
@@ -48,6 +51,7 @@
      *  Gets the contact URI.
      *  @hide
      */
+    @UnsupportedAppUsage
     public String getContactUri() {
         return mContactUri;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java b/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java
index 395f3e8..41020ec 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresCmdId.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -57,6 +58,7 @@
      * Sets the command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(int nCmdId) {
         this.mCmdId = nCmdId;
     }
@@ -66,6 +68,7 @@
     * Constructor for the PresCmdId class.
     * @hide
     */
+    @UnsupportedAppUsage
     public PresCmdId(){};
 
 
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java b/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
index a5b498b..ff8069c 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
@@ -18,6 +18,7 @@
 
 import com.android.ims.internal.uce.common.StatusCode;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -42,6 +43,7 @@
      * Sets the command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(PresCmdId cmdId) {
         this.mCmdId = cmdId;
     }
@@ -58,6 +60,7 @@
      * Sets the user data.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUserData(int userData) {
         this.mUserData = userData;
     }
@@ -73,6 +76,7 @@
      * Sets the status code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setStatus(StatusCode status) {
         this.mStatus = status;
     }
@@ -89,6 +93,7 @@
      * Sets the request ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRequestId(int requestId) {
         this.mRequestId = requestId;
     }
@@ -97,6 +102,7 @@
      * Constructor for the PresCmdStatus class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresCmdStatus() {
         mStatus = new StatusCode();
     };
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java b/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
index 3e8531a..87193e3 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -65,6 +66,7 @@
      * Sets the publish trigger type.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPublishTrigeerType(int nPublishTriggerType) {
         this.mPublishTriggerType = nPublishTriggerType;
     }
@@ -74,6 +76,7 @@
      * Constructor for the PresPublishTriggerType class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresPublishTriggerType(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java
index a073a23..237c999 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresResInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -38,6 +39,7 @@
      * Sets the Presence service resource instance information.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setInstanceInfo(PresResInstanceInfo instanceInfo) {
         this.mInstanceInfo = instanceInfo;
     }
@@ -54,6 +56,7 @@
      * Sets the resource URI.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setResUri(String resUri) {
         this.mResUri = resUri;
     }
@@ -70,6 +73,7 @@
      * Sets the display name.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setDisplayName(String displayName) {
         this.mDisplayName = displayName;
     }
@@ -79,6 +83,7 @@
     * Constructor for the PresResInstanceInfo class.
     * @hide
     */
+    @UnsupportedAppUsage
     public PresResInfo() {
         mInstanceInfo = new PresResInstanceInfo();
     };
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
index 430cff1..29699ea 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import java.util.Arrays;
@@ -59,6 +60,7 @@
      * Sets the resource instance state.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setResInstanceState(int nResInstanceState) {
         this.mResInstanceState = nResInstanceState;
     }
@@ -75,6 +77,7 @@
      * Sets the resource ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setResId(String resourceId) {
         this.mId = resourceId;
     }
@@ -93,6 +96,7 @@
      * code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setReason(String reason) {
         this.mReason = reason;
     }
@@ -109,6 +113,7 @@
      * Sets the entity URI.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPresentityUri(String presentityUri) {
         this.mPresentityUri = presentityUri;
     }
@@ -125,6 +130,7 @@
      * Sets the tuple information.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setTupleInfo(PresTupleInfo[] tupleInfo) {
         this.mTupleInfoArray = new PresTupleInfo[tupleInfo.length];
         this.mTupleInfoArray = tupleInfo;
@@ -135,6 +141,7 @@
     * Constructor for the PresResInstanceInfo class.
     * @hide
     */
+    @UnsupportedAppUsage
     public PresResInstanceInfo(){
 
     };
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
index 987dd77..ab46e4b 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -60,6 +61,7 @@
      * Sets the URI.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setUri(String uri) {
         this.mUri = uri;
     }
@@ -76,6 +78,7 @@
      * Sets the version.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setVersion(int version) {
         this.mVersion = version;
     }
@@ -92,6 +95,7 @@
      * Sets the RLMI state.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setFullState(boolean fullState) {
         this.mFullState = fullState;
     }
@@ -108,6 +112,7 @@
      * Sets the RLMI list name.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setListName(String listName) {
         this.mListName = listName;
     }
@@ -124,6 +129,7 @@
      * Sets the subscription request ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRequestId(int requestId) {
         this.mRequestId = requestId;
     }
@@ -140,6 +146,7 @@
      * Sets the presence subscription state.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPresSubscriptionState(PresSubscriptionState presSubscriptionState) {
         this.mPresSubscriptionState = presSubscriptionState;
     }
@@ -156,6 +163,7 @@
      * Sets the presence subscription expiration time.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSubscriptionExpireTime(int subscriptionExpireTime) {
         this.mSubscriptionExpireTime = subscriptionExpireTime;
     }
@@ -172,6 +180,7 @@
      * Sets the presence subscription terminated reason.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSubscriptionTerminatedReason(String subscriptionTerminatedReason) {
         this.mSubscriptionTerminatedReason = subscriptionTerminatedReason;
     }
@@ -180,6 +189,7 @@
      * Constructor for the PresTupleInfo class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresRlmiInfo(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
index f7b7264..83ba722 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -45,6 +46,7 @@
      * Gets the media type.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getMediaType() {
         return mMediaCap;
     }
@@ -61,6 +63,7 @@
      * Gets the service ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getServiceId() {
         return mServiceID;
     }
@@ -76,6 +79,7 @@
      * Gets the service description.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getServiceDesc() {
         return mServiceDesc;
     }
@@ -92,6 +96,7 @@
      * Gets the service version.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getServiceVer() {
         return mServiceVer;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java b/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java
index 456b443..5e42592 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresSipResponse.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -32,6 +33,7 @@
      * Gets the Presence command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresCmdId getCmdId() {
         return mCmdId;
     }
@@ -40,6 +42,7 @@
      * Sets the Presence command ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setCmdId(PresCmdId cmdId) {
         this.mCmdId = cmdId;
     }
@@ -48,6 +51,7 @@
      * Gets the request ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getRequestId() {
         return mRequestId;
     }
@@ -56,6 +60,7 @@
      * Sets the request ID.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRequestId(int requestId) {
         this.mRequestId = requestId;
     }
@@ -64,6 +69,7 @@
      * Gets the SIP response code.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getSipResponseCode() {
         return mSipResponseCode;
     }
@@ -72,6 +78,7 @@
      * Sets the SIP response code.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setSipResponseCode(int sipResponseCode) {
         this.mSipResponseCode = sipResponseCode;
     }
@@ -82,6 +89,7 @@
      * code.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getReasonPhrase() {
         return mReasonPhrase;
     }
@@ -90,6 +98,7 @@
      * Sets the SIP response code reason phrase.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setReasonPhrase(String reasonPhrase) {
         this.mReasonPhrase = reasonPhrase;
     }
@@ -98,6 +107,7 @@
      * Gets the SIP retryAfter sec value.
      * @hide
      */
+    @UnsupportedAppUsage
     public int getRetryAfter() {
         return mRetryAfter;
     }
@@ -106,6 +116,7 @@
      * Sets the SIP retryAfter sec value
      * @hide
      */
+    @UnsupportedAppUsage
     public void setRetryAfter(int retryAfter) {
         this.mRetryAfter = retryAfter;
     }
@@ -114,6 +125,7 @@
      * Constructor for the PresSipResponse class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresSipResponse(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java b/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
index 872bc23..bee928c 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -77,6 +78,7 @@
      * Constructor for the PresSubscriptionState class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresSubscriptionState() {    };
 
     /**
@@ -92,6 +94,7 @@
      * Sets the Presence subscription state.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setPresSubscriptionState(int nPresSubscriptionState) {
         this.mPresSubscriptionState = nPresSubscriptionState;
     }
diff --git a/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java b/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
index e1867c5..7a47786 100644
--- a/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
+++ b/telephony/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.ims.internal.uce.presence;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -39,6 +40,7 @@
      * Sets the feature tag.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setFeatureTag(String featureTag) {
         this.mFeatureTag = featureTag;
     }
@@ -54,6 +56,7 @@
      * Sets the contact URI.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setContactUri(String contactUri) {
         this.mContactUri = contactUri;
     }
@@ -70,6 +73,7 @@
      * Sets the timestamp.
      * @hide
      */
+    @UnsupportedAppUsage
     public void setTimestamp(String timestamp) {
         this.mTimestamp = timestamp;
     }
@@ -78,6 +82,7 @@
      * Constructor for the PresTupleInfo class.
      * @hide
      */
+    @UnsupportedAppUsage
     public PresTupleInfo(){};
 
     /** @hide */
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index d850fbc..f9c3940 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -390,7 +390,7 @@
     /**
      * Returns the neighboring cell information of the device.
      */
-    List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);
+    List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg, int targetSdk);
 
      int getCallState();
 
diff --git a/vr/java/com/google/vr/platform/DeviceInfo.java b/vr/java/com/google/vr/platform/DeviceInfo.java
index f6da66b..6a4617d 100644
--- a/vr/java/com/google/vr/platform/DeviceInfo.java
+++ b/vr/java/com/google/vr/platform/DeviceInfo.java
@@ -1,5 +1,6 @@
 package com.google.vr.platform;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.SystemProperties;
 
 /**
@@ -13,6 +14,7 @@
     /**
      * Returns true if this device boots directly in VR mode.
      */
+    @UnsupportedAppUsage
     public static boolean getVrBoot() {
         return SystemProperties.getBoolean(VR_MODE_BOOT, false);
     }
diff --git a/vr/java/com/google/vr/platform/Dvr.java b/vr/java/com/google/vr/platform/Dvr.java
index b07d634..41dcd87 100644
--- a/vr/java/com/google/vr/platform/Dvr.java
+++ b/vr/java/com/google/vr/platform/Dvr.java
@@ -1,5 +1,7 @@
 package com.google.vr.platform;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * Class to load the dvr api.
  * @hide
@@ -10,6 +12,7 @@
      *
      * @return A Long object describing the handle returned by dlopen.
      */
+    @UnsupportedAppUsage
     public static Long loadLibrary() {
         // Load a thin JNI library that runs dlopen on request.
         System.loadLibrary("dvr_loader");
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index 2ea6e79..66297fc 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -16,11 +16,12 @@
 
 package android.net.wifi.hotspot2;
 
+import android.net.wifi.WifiManager;
 import android.os.Handler;
 
 /**
  * Base class for provisioning callbacks. Should be extended by applications and set when calling
- * {@link WifiManager#startSubscriptionProvisiong(OsuProvider, ProvisioningCallback, Handler)}.
+ * {@link WifiManager#startSubscriptionProvisioning(OsuProvider, ProvisioningCallback, Handler)}.
  *
  * @hide
  */
@@ -28,84 +29,101 @@
 
     /**
      * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
      */
-    public static final int OSU_FAILURE_AP_CONNECTION      = 1;
+    public static final int OSU_FAILURE_AP_CONNECTION = 1;
 
     /**
-     * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
+     * The reason code for invalid server URL address.
      */
     public static final int OSU_FAILURE_SERVER_URL_INVALID = 2;
 
     /**
-     * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
+     * The reason code for provisioning failure due to connection failure to the server.
      */
-    public static final int OSU_FAILURE_SERVER_CONNECTION  = 3;
+    public static final int OSU_FAILURE_SERVER_CONNECTION = 3;
 
     /**
-     * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
+     * The reason code for provisioning failure due to invalid server certificate.
      */
-    public static final int OSU_FAILURE_SERVER_VALIDATION  = 4;
+    public static final int OSU_FAILURE_SERVER_VALIDATION = 4;
 
     /**
-     * The reason code for Provisioning Failure due to connection failure to OSU AP.
-     * @hide
+     * The reason code for provisioning failure due to invalid service provider.
      */
-    public static final int OSU_FAILURE_PROVIDER_VERIFICATION = 5;
+    public static final int OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION = 5;
 
     /**
-     * The reason code for Provisioning Failure when a provisioning flow is aborted.
-     * @hide
+     * The reason code for provisioning failure when a provisioning flow is aborted.
      */
     public static final int OSU_FAILURE_PROVISIONING_ABORTED = 6;
 
     /**
-     * The reason code for Provisioning Failure when a provisioning flow is aborted.
-     * @hide
+     * The reason code for provisioning failure when a provisioning flow is not possible.
      */
     public static final int OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7;
 
     /**
-     * The status code for Provisioning flow to indicate connecting to OSU AP
-     * @hide
+     * The reason code for provisioning failure due to invalid server url.
      */
-    public static final int OSU_STATUS_AP_CONNECTING       = 1;
+    public static final int OSU_FAILURE_INVALID_SERVER_URL = 8;
 
     /**
-     * The status code for Provisioning flow to indicate connected to OSU AP
-     * @hide
+     * The reason code for provisioning failure when a command received is not the expected command
+     * type.
      */
-    public static final int OSU_STATUS_AP_CONNECTED        = 2;
+    public static final int OSU_FAILURE_UNEXPECTED_COMMAND_TYPE = 9;
 
     /**
-     * The status code for Provisioning flow to indicate connecting to OSU AP
-     * @hide
+     * The reason code for provisioning failure when a SOAP message is not the expected message
+     * type.
      */
-    public static final int OSU_STATUS_SERVER_CONNECTED    = 3;
+    public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE = 10;
 
     /**
-     * The status code for Provisioning flow to indicate connecting to OSU AP
-     * @hide
+     * The reason code for provisioning failure when a SOAP message exchange fails.
      */
-    public static final int OSU_STATUS_SERVER_VALIDATED    = 4;
+    public static final int OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11;
 
     /**
-     * The status code for Provisioning flow to indicate connecting to OSU AP
-     * @hide
+     * The status code for provisioning flow to indicate connecting to OSU AP
      */
-    public static final int OSU_STATUS_PROVIDER_VERIFIED   = 5;
+    public static final int OSU_STATUS_AP_CONNECTING = 1;
+
+    /**
+     * The status code for provisioning flow to indicate the OSU AP is connected.
+     */
+    public static final int OSU_STATUS_AP_CONNECTED = 2;
+
+    /**
+     * The status code for provisioning flow to indicate the server connection is completed.
+     */
+    public static final int OSU_STATUS_SERVER_CONNECTED = 3;
+
+    /**
+     * The status code for provisioning flow to indicate the server certificate is validated.
+     */
+    public static final int OSU_STATUS_SERVER_VALIDATED = 4;
+
+    /**
+     * The status code for provisioning flow to indicate the service provider is verified.
+     */
+    public static final int OSU_STATUS_SERVICE_PROVIDER_VERIFIED = 5;
+
+    /**
+     * The status code for provisioning flow to indicate starting the SOAP exchange.
+     */
+    public static final int OSU_STATUS_INIT_SOAP_EXCHANGE = 6;
 
     /**
      * Provisioning status for OSU failure
+     *
      * @param status indicates error condition
      */
     public abstract void onProvisioningFailure(int status);
 
     /**
      * Provisioning status when OSU is in progress
+     *
      * @param status indicates status of OSU flow
      */
     public abstract void onProvisioningStatus(int status);