Merge "[QS] Disable hotspot when data saver is enabled" into pi-dev
diff --git a/api/current.txt b/api/current.txt
index 4416532..94c1d32 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13601,11 +13601,19 @@
     method public static android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source) throws java.io.IOException;
     method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
     method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source) throws java.io.IOException;
+    method public int getAllocator();
+    method public boolean getConserveMemory();
+    method public android.graphics.Rect getCrop();
+    method public boolean getDecodeAsAlphaMask();
+    method public boolean getMutable();
+    method public android.graphics.ImageDecoder.OnPartialImageListener getOnPartialImageListener();
+    method public android.graphics.PostProcessor getPostProcessor();
+    method public boolean getRequireUnpremultiplied();
     method public android.util.Size getSampledSize(int);
     method public android.graphics.ImageDecoder setAllocator(int);
-    method public android.graphics.ImageDecoder setAsAlphaMask(boolean);
     method public android.graphics.ImageDecoder setConserveMemory(boolean);
     method public android.graphics.ImageDecoder setCrop(android.graphics.Rect);
+    method public android.graphics.ImageDecoder setDecodeAsAlphaMask(boolean);
     method public android.graphics.ImageDecoder setMutable(boolean);
     method public android.graphics.ImageDecoder setOnPartialImageListener(android.graphics.ImageDecoder.OnPartialImageListener);
     method public android.graphics.ImageDecoder setPostProcessor(android.graphics.PostProcessor);
@@ -37136,6 +37144,7 @@
     field public static final java.lang.String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
     field public static final java.lang.String ACTION_CHANNEL_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_NOTIFICATION_SETTINGS";
     field public static final java.lang.String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS";
+    field public static final java.lang.String ACTION_DATA_USAGE_SETTINGS = "android.settings.DATA_USAGE_SETTINGS";
     field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
     field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
     field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
@@ -41371,10 +41380,10 @@
     method public void onStateChanged(android.telecom.Call, int);
     method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
     field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
-    field public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3; // 0x3
-    field public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2; // 0x2
-    field public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4; // 0x4
-    field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5; // 0x5
+    field public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2; // 0x2
+    field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4; // 0x4
+    field public static final int HANDOVER_FAILURE_UNKNOWN = 5; // 0x5
+    field public static final int HANDOVER_FAILURE_USER_REJECTED = 3; // 0x3
   }
 
   public static class Call.Details {
diff --git a/api/removed.txt b/api/removed.txt
index b8e2b98..a5370f4 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -152,6 +152,11 @@
     method public deprecated boolean clipRegion(android.graphics.Region);
   }
 
+  public final class ImageDecoder implements java.lang.AutoCloseable {
+    method public deprecated boolean getAsAlphaMask();
+    method public deprecated android.graphics.ImageDecoder setAsAlphaMask(boolean);
+  }
+
   public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
     ctor public LayerRasterizer();
     method public void addLayer(android.graphics.Paint, float, float);
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index af43032..64a5181 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -65,8 +65,8 @@
  * <pre class="prettyprint">
  * {@literal
  * <provider
- *     android:name="com.android.mypkg.MySliceProvider"
- *     android:authorities="com.android.mypkg" />}
+ *     android:name="com.example.mypkg.MySliceProvider"
+ *     android:authorities="com.example.mypkg" />}
  * </pre>
  * <p>
  * Slices can be identified by a Uri or by an Intent. To link an Intent with a slice, the provider
@@ -77,10 +77,10 @@
  * <pre class="prettyprint">
  * {@literal
  * <provider
- *     android:name="com.android.mypkg.MySliceProvider"
- *     android:authorities="com.android.mypkg">
+ *     android:name="com.example.mypkg.MySliceProvider"
+ *     android:authorities="com.example.mypkg">
  *     <intent-filter>
- *         <action android:name="android.intent.action.MY_SLICE_INTENT" />
+ *         <action android:name="com.example.mypkg.intent.action.MY_SLICE_INTENT" />
  *     </intent-filter>
  * </provider>}
  * </pre>
diff --git a/core/java/android/hardware/radio/ProgramSelector.java b/core/java/android/hardware/radio/ProgramSelector.java
index 0294a29..2a878eb 100644
--- a/core/java/android/hardware/radio/ProgramSelector.java
+++ b/core/java/android/hardware/radio/ProgramSelector.java
@@ -441,6 +441,15 @@
      */
     public static @NonNull ProgramSelector createAmFmSelector(
             @RadioManager.Band int band, int frequencyKhz, int subChannel) {
+        if (band == RadioManager.BAND_INVALID) {
+            // 50MHz is a rough boundary between AM (<30MHz) and FM (>60MHz).
+            if (frequencyKhz < 50000) {
+                band = (subChannel <= 0) ? RadioManager.BAND_AM : RadioManager.BAND_AM_HD;
+            } else {
+                band = (subChannel <= 0) ? RadioManager.BAND_FM : RadioManager.BAND_FM_HD;
+            }
+        }
+
         boolean isAm = (band == RadioManager.BAND_AM || band == RadioManager.BAND_AM_HD);
         boolean isDigital = (band == RadioManager.BAND_AM_HD || band == RadioManager.BAND_FM_HD);
         if (!isAm && !isDigital && band != RadioManager.BAND_FM) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bd29d2d..c717dd9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -430,6 +430,20 @@
             "android.settings.WIFI_IP_SETTINGS";
 
     /**
+     * Activity Action: Show settings to allow configuration of data and view data usage.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_DATA_USAGE_SETTINGS =
+            "android.settings.DATA_USAGE_SETTINGS";
+
+    /**
      * Activity Action: Show settings to allow configuration of Bluetooth.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 75940e8..77a74e2 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -416,4 +416,10 @@
      * Returns true if window trace is enabled.
      */
     boolean isWindowTraceEnabled();
+
+    /**
+     * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
+     * on the next user activity.
+     */
+    void requestUserActivityNotification();
 }
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index a6f36bb..23dc9da 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -51,6 +51,12 @@
     int NAV_BAR_BOTTOM = 1 << 2;
 
     /**
+     * Broadcast sent when a user activity is detected.
+     */
+    String ACTION_USER_ACTIVITY_NOTIFICATION =
+            "android.intent.action.USER_ACTIVITY_NOTIFICATION";
+
+    /**
      * Sticky broadcast of the current HDMI plugged state.
      */
     String ACTION_HDMI_PLUGGED = "android.intent.action.HDMI_PLUGGED";
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 344c772..246a50f 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -38,11 +38,6 @@
  */
 public class PowerProfile {
 
-    /**
-     * No power consumption, or accounted for elsewhere.
-     */
-    public static final String POWER_NONE = "none";
-
     /*
      * POWER_CPU_SUSPEND: Power consumption when CPU is in power collapse mode.
      * POWER_CPU_IDLE: Power consumption when CPU is awake (when a wake lock is held). This should
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index ed032c7..c7ad2a4 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -51,6 +51,18 @@
     std::vector<minikin::FontVariation> axes;
 };
 
+static inline NativeFamilyBuilder* toNativeBuilder(jlong ptr) {
+    return reinterpret_cast<NativeFamilyBuilder*>(ptr);
+}
+
+static inline FontFamilyWrapper* toFamily(jlong ptr) {
+    return reinterpret_cast<FontFamilyWrapper*>(ptr);
+}
+
+template<typename Ptr> static inline jlong toJLong(Ptr ptr) {
+    return reinterpret_cast<jlong>(ptr);
+}
+
 static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring langs, jint variant) {
     NativeFamilyBuilder* builder;
     if (langs != nullptr) {
@@ -59,15 +71,14 @@
     } else {
         builder = new NativeFamilyBuilder(minikin::registerLocaleList(""), variant);
     }
-    return reinterpret_cast<jlong>(builder);
+    return toJLong(builder);
 }
 
 static jlong FontFamily_create(jlong builderPtr) {
     if (builderPtr == 0) {
         return 0;
     }
-    std::unique_ptr<NativeFamilyBuilder> builder(
-            reinterpret_cast<NativeFamilyBuilder*>(builderPtr));
+    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
     if (builder->fonts.empty()) {
         return 0;
     }
@@ -76,17 +87,23 @@
     if (family->getCoverage().length() == 0) {
         return 0;
     }
-    return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
+    return toJLong(new FontFamilyWrapper(std::move(family)));
 }
 
-static void FontFamily_abort(jlong builderPtr) {
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    delete builder;
+static void releaseBuilder(jlong builderPtr) {
+    delete toNativeBuilder(builderPtr);
 }
 
-static void FontFamily_unref(jlong familyPtr) {
-    FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(familyPtr);
-    delete family;
+static jlong FontFamily_getBuilderReleaseFunc() {
+    return toJLong(&releaseBuilder);
+}
+
+static void releaseFamily(jlong familyPtr) {
+    delete toFamily(familyPtr);
+}
+
+static jlong FontFamily_getFamilyReleaseFunc() {
+    return toJLong(&releaseFamily);
 }
 
 static bool addSkTypeface(NativeFamilyBuilder* builder, sk_sp<SkData>&& data, int ttcIndex,
@@ -175,7 +192,7 @@
 static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong builderPtr,
         jobject font, jint ttcIndex, jint weight, jint isItalic) {
     NPE_CHECK_RETURN_ZERO(env, font);
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
+    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
     const void* fontPtr = env->GetDirectBufferAddress(font);
     if (fontPtr == NULL) {
         ALOGE("addFont failed to create font, buffer invalid");
@@ -204,8 +221,7 @@
     NPE_CHECK_RETURN_ZERO(env, jassetMgr);
     NPE_CHECK_RETURN_ZERO(env, jpath);
 
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-
+    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
     Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, jassetMgr);
     if (NULL == mgr) {
         builder->axes.clear();
@@ -249,19 +265,19 @@
 }
 
 static void FontFamily_addAxisValue(jlong builderPtr, jint tag, jfloat value) {
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
+    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
     builder->axes.push_back({static_cast<minikin::AxisTag>(tag), value});
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 static const JNINativeMethod gFontFamilyMethods[] = {
-    { "nInitBuilder",          "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
-    { "nCreateFamily",         "(J)J", (void*)FontFamily_create },
-    { "nAbort",                "(J)V", (void*)FontFamily_abort },
-    { "nUnrefFamily",          "(J)V", (void*)FontFamily_unref },
-    { "nAddFont",              "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
-    { "nAddFontWeightStyle",   "(JLjava/nio/ByteBuffer;III)Z",
+    { "nInitBuilder",           "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
+    { "nCreateFamily",          "(J)J", (void*)FontFamily_create },
+    { "nGetBuilderReleaseFunc", "()J", (void*)FontFamily_getBuilderReleaseFunc },
+    { "nGetFamilyReleaseFunc",  "()J", (void*)FontFamily_getFamilyReleaseFunc },
+    { "nAddFont",               "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
+    { "nAddFontWeightStyle",    "(JLjava/nio/ByteBuffer;III)Z",
             (void*)FontFamily_addFontWeightStyle },
     { "nAddFontFromAssetManager",    "(JLandroid/content/res/AssetManager;Ljava/lang/String;IZIII)Z",
             (void*)FontFamily_addFontFromAssetManager },
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index d67c0b0..34ec365 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -28,8 +28,16 @@
 
 using namespace android;
 
+static inline Typeface* toTypeface(jlong ptr) {
+    return reinterpret_cast<Typeface*>(ptr);
+}
+
+template<typename Ptr> static inline jlong toJLong(Ptr ptr) {
+    return reinterpret_cast<jlong>(ptr);
+}
+
 static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandle, jint style) {
-    Typeface* family = reinterpret_cast<Typeface*>(familyHandle);
+    Typeface* family = toTypeface(familyHandle);
     Typeface* face = Typeface::createRelative(family, (Typeface::Style)style);
     // TODO: the following logic shouldn't be necessary, the above should always succeed.
     // Try to find the closest matching font, using the standard heuristic
@@ -39,13 +47,12 @@
     for (int i = 0; NULL == face && i < 4; i++) {
         face = Typeface::createRelative(family, (Typeface::Style)i);
     }
-    return reinterpret_cast<jlong>(face);
+    return toJLong(face);
 }
 
 static jlong Typeface_createFromTypefaceWithExactStyle(JNIEnv* env, jobject, jlong nativeInstance,
         jint weight, jboolean italic) {
-    Typeface* baseTypeface = reinterpret_cast<Typeface*>(nativeInstance);
-    return reinterpret_cast<jlong>(Typeface::createAbsolute(baseTypeface, weight, italic));
+    return toJLong(Typeface::createAbsolute(toTypeface(nativeInstance), weight, italic));
 }
 
 static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle,
@@ -60,30 +67,30 @@
         AxisHelper axis(env, axisObject);
         variations.push_back(minikin::FontVariation(axis.getTag(), axis.getStyleValue()));
     }
-    Typeface* baseTypeface = reinterpret_cast<Typeface*>(familyHandle);
-    Typeface* result = Typeface::createFromTypefaceWithVariation(baseTypeface, variations);
-    return reinterpret_cast<jlong>(result);
+    return toJLong(Typeface::createFromTypefaceWithVariation(toTypeface(familyHandle), variations));
 }
 
 static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) {
-    Typeface* family = reinterpret_cast<Typeface*>(familyHandle);
-    Typeface* face = Typeface::createWithDifferentBaseWeight(family, weight);
-    return reinterpret_cast<jlong>(face);
+    return toJLong(Typeface::createWithDifferentBaseWeight(toTypeface(familyHandle), weight));
 }
 
-static void Typeface_unref(JNIEnv* env, jobject obj, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
-    delete face;
+static void releaseFunc(jlong ptr) {
+    delete toTypeface(ptr);
 }
 
-static jint Typeface_getStyle(JNIEnv* env, jobject obj, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
-    return face->fAPIStyle;
+// CriticalNative
+static jlong Typeface_getReleaseFunc() {
+    return toJLong(&releaseFunc);
 }
 
-static jint Typeface_getWeight(JNIEnv* env, jobject obj, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
-    return face->fStyle.weight();
+// CriticalNative
+static jint Typeface_getStyle(jlong faceHandle) {
+    return toTypeface(faceHandle)->fAPIStyle;
+}
+
+// CriticalNative
+static jint Typeface_getWeight(jlong faceHandle) {
+    return toTypeface(faceHandle)->fStyle.weight();
 }
 
 static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
@@ -95,17 +102,16 @@
         FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
         familyVec.emplace_back(family->family);
     }
-    return reinterpret_cast<jlong>(
-            Typeface::createFromFamilies(std::move(familyVec), weight, italic));
+    return toJLong(Typeface::createFromFamilies(std::move(familyVec), weight, italic));
 }
 
-static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
-    Typeface::setDefault(face);
+// CriticalNative
+static void Typeface_setDefault(jlong faceHandle) {
+    Typeface::setDefault(toTypeface(faceHandle));
 }
 
 static jobject Typeface_getSupportedAxes(JNIEnv *env, jobject, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+    Typeface* face = toTypeface(faceHandle);
     const std::unordered_set<minikin::AxisTag>& tagSet = face->fFontCollection->getSupportedTags();
     const size_t length = tagSet.size();
     if (length == 0) {
@@ -131,7 +137,7 @@
     { "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J",
             (void*)Typeface_createFromTypefaceWithVariation },
     { "nativeCreateWeightAlias",  "(JI)J", (void*)Typeface_createWeightAlias },
-    { "nativeUnref",              "(J)V",  (void*)Typeface_unref },
+    { "nativeGetReleaseFunc",     "()J",  (void*)Typeface_getReleaseFunc },
     { "nativeGetStyle",           "(J)I",  (void*)Typeface_getStyle },
     { "nativeGetWeight",      "(J)I",  (void*)Typeface_getWeight },
     { "nativeCreateFromArray",    "([JII)J",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ef206f9..7aec812 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -87,6 +87,7 @@
     <protected-broadcast android:name="android.intent.action.OVERLAY_CHANGED" />
     <protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
     <protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
 
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index eff7c55..899d630 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -27,7 +27,6 @@
        are totally dependent on the platform and can vary
        significantly, so should be measured on the shipping platform
        with a power meter. -->
-  <item name="none">0</item>
   <item name="ambient.on">0.1</item>  <!-- ~100mA -->
   <item name="screen.on">0.1</item>  <!-- ~100mA -->
   <item name="screen.full">0.1</item>  <!-- ~100mA -->
diff --git a/core/res/res/xml/power_profile_test.xml b/core/res/res/xml/power_profile_test.xml
index 6dc5c7e..001cc68 100644
--- a/core/res/res/xml/power_profile_test.xml
+++ b/core/res/res/xml/power_profile_test.xml
@@ -24,9 +24,6 @@
          sample values, not meant to reflect any real device.
     -->
 
-    <!-- Nothing -->
-    <item name="none">0</item>
-
     <!-- This is the battery capacity in mAh -->
     <item name="battery.capacity">3000</item>
 
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index e7cfcfd..c69eb32 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -24,6 +24,8 @@
 
 import dalvik.annotation.optimization.CriticalNative;
 
+import libcore.util.NativeAllocationRegistry;
+
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -38,6 +40,14 @@
 
     private static String TAG = "FontFamily";
 
+    private static final NativeAllocationRegistry sBuilderRegistry = new NativeAllocationRegistry(
+            FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc(), 64);
+
+    private @Nullable Runnable mNativeBuilderCleaner;
+
+    private static final NativeAllocationRegistry sFamilyRegistry = new NativeAllocationRegistry(
+            FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc(), 64);
+
     /**
      * @hide
      */
@@ -48,6 +58,7 @@
 
     public FontFamily() {
         mBuilderPtr = nInitBuilder(null, 0);
+        mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
     }
 
     public FontFamily(@Nullable String[] langs, int variant) {
@@ -60,6 +71,7 @@
             langsString = TextUtils.join(",", langs);
         }
         mBuilderPtr = nInitBuilder(langsString, variant);
+        mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
     }
 
     /**
@@ -73,7 +85,11 @@
             throw new IllegalStateException("This FontFamily is already frozen");
         }
         mNativePtr = nCreateFamily(mBuilderPtr);
+        mNativeBuilderCleaner.run();
         mBuilderPtr = 0;
+        if (mNativePtr != 0) {
+            sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
+        }
         return mNativePtr != 0;
     }
 
@@ -81,24 +97,10 @@
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("This FontFamily is already frozen or abandoned");
         }
-        nAbort(mBuilderPtr);
+        mNativeBuilderCleaner.run();
         mBuilderPtr = 0;
     }
 
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            if (mNativePtr != 0) {
-                nUnrefFamily(mNativePtr);
-            }
-            if (mBuilderPtr != 0) {
-                nAbort(mBuilderPtr);
-            }
-        } finally {
-            super.finalize();
-        }
-    }
-
     public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
             int italic) {
         if (mBuilderPtr == 0) {
@@ -171,10 +173,10 @@
     private static native long nCreateFamily(long mBuilderPtr);
 
     @CriticalNative
-    private static native void nAbort(long mBuilderPtr);
+    private static native long nGetBuilderReleaseFunc();
 
     @CriticalNative
-    private static native void nUnrefFamily(long nativePtr);
+    private static native long nGetFamilyReleaseFunc();
     // By passing -1 to weigth argument, the weight value is resolved by OS/2 table in the font.
     // By passing -1 to italic argument, the italic value is resolved by OS/2 table in the font.
     private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 5602a3e..88701fa 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -493,7 +493,7 @@
     private boolean mRequireUnpremultiplied = false;
     private boolean mMutable = false;
     private boolean mConserveMemory = false;
-    private boolean mAsAlphaMask = false;
+    private boolean mDecodeAsAlphaMask = false;
     private Rect    mCropRect;
     private Rect    mOutPaddingRect;
     private Source  mSource;
@@ -730,7 +730,7 @@
      *  Will typically result in a {@link Bitmap.Config#HARDWARE}
      *  allocation, but may be software for small images. In addition, this will
      *  switch to software when HARDWARE is incompatible, e.g.
-     *  {@link #setMutable}, {@link #setAsAlphaMask}.
+     *  {@link #setMutable}, {@link #setDecodeAsAlphaMask}.
      */
     public static final int ALLOCATOR_DEFAULT = 0;
 
@@ -753,7 +753,7 @@
      *  Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}.
      *
      *  When this is combined with incompatible options, like
-     *  {@link #setMutable} or {@link #setAsAlphaMask}, {@link #decodeDrawable}
+     *  {@link #setMutable} or {@link #setDecodeAsAlphaMask}, {@link #decodeDrawable}
      *  / {@link #decodeBitmap} will throw an
      *  {@link java.lang.IllegalStateException}.
      */
@@ -783,6 +783,14 @@
     }
 
     /**
+     *  Return the allocator for the pixel memory.
+     */
+    @Allocator
+    public int getAllocator() {
+        return mAllocator;
+    }
+
+    /**
      *  Specify whether the {@link Bitmap} should have unpremultiplied pixels.
      *
      *  <p>By default, ImageDecoder will create a {@link Bitmap} with
@@ -803,6 +811,13 @@
     }
 
     /**
+     *  Return whether the {@link Bitmap} will have unpremultiplied pixels.
+     */
+    public boolean getRequireUnpremultiplied() {
+        return mRequireUnpremultiplied;
+    }
+
+    /**
      *  Modify the image after decoding and scaling.
      *
      *  <p>This allows adding effects prior to returning a {@link Drawable} or
@@ -823,6 +838,14 @@
     }
 
     /**
+     *  Return the {@link PostProcessor} currently set.
+     */
+    @Nullable
+    public PostProcessor getPostProcessor() {
+        return mPostProcessor;
+    }
+
+    /**
      *  Set (replace) the {@link OnPartialImageListener} on this object.
      *
      *  <p>Will be called if there is an error in the input. Without one, an
@@ -836,6 +859,14 @@
     }
 
     /**
+     *  Return the {@link OnPartialImageListener} currently set.
+     */
+    @Nullable
+    public OnPartialImageListener getOnPartialImageListener() {
+        return mOnPartialImageListener;
+    }
+
+    /**
      *  Crop the output to {@code subset} of the (possibly) scaled image.
      *
      *  <p>{@code subset} must be contained within the size set by
@@ -855,6 +886,14 @@
     }
 
     /**
+     *  Return the cropping rectangle, if set.
+     */
+    @Nullable
+    public Rect getCrop() {
+        return mCropRect;
+    }
+
+    /**
      *  Set a Rect for retrieving nine patch padding.
      *
      *  If the image is a nine patch, this Rect will be set to the padding
@@ -893,6 +932,13 @@
     }
 
     /**
+     *  Return whether the {@link Bitmap} will be mutable.
+     */
+    public boolean getMutable() {
+        return mMutable;
+    }
+
+    /**
      *  Specify whether to potentially save RAM at the expense of quality.
      *
      *  <p>Setting this to {@code true} may result in a {@link Bitmap} with a
@@ -912,24 +958,62 @@
     }
 
     /**
+     *  Return whether this object will try to save RAM at the expense of quality.
+     *
+     *  <p>This returns whether {@link #setConserveMemory} was set to {@code true}.
+     *  It may still return {@code true} even if the {@code ImageDecoder} does not
+     *  have a way to save RAM at the expense of quality for this image.</p>
+     */
+    public boolean getConserveMemory() {
+        return mConserveMemory;
+    }
+
+    /**
      *  Specify whether to potentially treat the output as an alpha mask.
      *
      *  <p>If this is set to {@code true} and the image is encoded in a format
      *  with only one channel, treat that channel as alpha. Otherwise this call has
      *  no effect.</p>
      *
-     *  <p>setAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to
+     *  <p>setDecodeAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to
      *  combine them will result in {@link #decodeDrawable}/
      *  {@link #decodeBitmap} throwing an
      *  {@link java.lang.IllegalStateException}.</p>
      *
      *  @return this object for chaining.
      */
-    public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
-        mAsAlphaMask = asAlphaMask;
+    public ImageDecoder setDecodeAsAlphaMask(boolean decodeAsAlphaMask) {
+        mDecodeAsAlphaMask = decodeAsAlphaMask;
         return this;
     }
 
+    /** @removed
+     * @deprecated Call {@link #setDecodeAsAlphaMask} instead.
+     */
+    @java.lang.Deprecated
+    public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
+        return this.setDecodeAsAlphaMask(asAlphaMask);
+    }
+
+    /**
+     *  Return whether to treat single channel input as alpha.
+     *
+     *  <p>This returns whether {@link #setDecodeAsAlphaMask} was set to {@code true}.
+     *  It may still return {@code true} even if the image has more than one
+     *  channel and therefore will not be treated as an alpha mask.</p>
+     */
+    public boolean getDecodeAsAlphaMask() {
+        return mDecodeAsAlphaMask;
+    }
+
+    /** @removed
+     * @deprecated Call {@link #getDecodeAsAlphaMask} instead.
+     */
+    @java.lang.Deprecated
+    public boolean getAsAlphaMask() {
+        return this.getDecodeAsAlphaMask();
+    }
+
     @Override
     public void close() {
         mCloseGuard.close();
@@ -960,7 +1044,7 @@
             if (mMutable) {
                 throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!");
             }
-            if (mAsAlphaMask) {
+            if (mDecodeAsAlphaMask) {
                 throw new IllegalStateException("Cannot make HARDWARE Alpha mask Bitmap!");
             }
         }
@@ -992,7 +1076,7 @@
         return nDecodeBitmap(mNativePtr, partialImagePtr,
                 postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect,
                 mMutable, mAllocator, mRequireUnpremultiplied,
-                mConserveMemory, mAsAlphaMask);
+                mConserveMemory, mDecodeAsAlphaMask);
     }
 
     private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
@@ -1224,7 +1308,7 @@
             int width, int height,
             @Nullable Rect cropRect, boolean mutable,
             int allocator, boolean requireUnpremul,
-            boolean conserveMemory, boolean asAlphaMask)
+            boolean conserveMemory, boolean decodeAsAlphaMask)
         throws IOException;
     private static native Size nGetSampledSize(long nativePtr,
                                                int sampleSize);
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 38beebd..f27c11d 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -42,6 +42,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
+import dalvik.annotation.optimization.CriticalNative;
+
+import libcore.util.NativeAllocationRegistry;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
@@ -71,6 +75,9 @@
 
     private static String TAG = "Typeface";
 
+    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+            Typeface.class.getClassLoader(), nativeGetReleaseFunc(), 64);
+
     /** The default NORMAL typeface object */
     public static final Typeface DEFAULT;
     /**
@@ -911,6 +918,7 @@
         }
 
         native_instance = ni;
+        sRegistry.registerNativeAllocation(this, native_instance);
         mStyle = nativeGetStyle(ni);
         mWeight = nativeGetWeight(ni);
     }
@@ -1120,16 +1128,6 @@
     }
 
     @Override
-    protected void finalize() throws Throwable {
-        try {
-            nativeUnref(native_instance);
-            native_instance = 0;  // Other finalizers can still call us.
-        } finally {
-            super.finalize();
-        }
-    }
-
-    @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
@@ -1173,10 +1171,18 @@
     private static native long nativeCreateFromTypefaceWithVariation(
             long native_instance, List<FontVariationAxis> axes);
     private static native long nativeCreateWeightAlias(long native_instance, int weight);
-    private static native void nativeUnref(long native_instance);
-    private static native int  nativeGetStyle(long native_instance);
-    private static native int  nativeGetWeight(long native_instance);
     private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
-    private static native void nativeSetDefault(long native_instance);
     private static native int[] nativeGetSupportedAxes(long native_instance);
+
+    @CriticalNative
+    private static native void nativeSetDefault(long nativePtr);
+
+    @CriticalNative
+    private static native int  nativeGetStyle(long nativePtr);
+
+    @CriticalNative
+    private static native int  nativeGetWeight(long nativePtr);
+
+    @CriticalNative
+    private static native long nativeGetReleaseFunc();
 }
diff --git a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
deleted file mode 100644
index 8908975..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-    Copyright (C) 2016 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="12dp"
-        android:height="24.0dp"
-        android:viewportWidth="20.0"
-        android:viewportHeight="40.0"
-        android:tint="?android:attr/colorControlNormal">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml b/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml
deleted file mode 100644
index ea794d4..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-    Copyright (C) 2016 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
-        android:viewportWidth="40.0"
-        android:viewportHeight="40.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 89d6e99..7ec437c 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -29,7 +29,7 @@
         android:alpha="0"
         android:text="@string/quick_settings_header_onboarding_text"
         android:textAppearance="@style/TextAppearance.QS.TileLabel"
-        android:textColor="?android:attr/colorAccent"
+        android:textColor="?android:attr/textColorSecondary"
         android:visibility="invisible" />
 
     <LinearLayout
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 2151436..ec4d1a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -65,7 +65,7 @@
     private static final long AUTO_FADE_OUT_DELAY_MS = DateUtils.SECOND_IN_MILLIS * 6;
     private static final int FADE_ANIMATION_DURATION_MS = 300;
     private static final int TOOLTIP_NOT_YET_SHOWN_COUNT = 0;
-    public static final int MAX_TOOLTIP_SHOWN_COUNT = 3;
+    public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
 
     private final Handler mHandler = new Handler();
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 0ce3e6a..8922094 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.service.quicksettings.Tile;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -52,16 +53,6 @@
 
 /** Quick settings tile: Cellular **/
 public class CellularTile extends QSTileImpl<SignalState> {
-    private static final ComponentName CELLULAR_SETTING_COMPONENT = new ComponentName(
-            "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity");
-    private static final ComponentName DATA_PLAN_CELLULAR_COMPONENT = new ComponentName(
-            "com.android.settings", "com.android.settings.Settings$DataPlanUsageSummaryActivity");
-
-    private static final Intent CELLULAR_SETTINGS =
-            new Intent().setComponent(CELLULAR_SETTING_COMPONENT);
-    private static final Intent DATA_PLAN_CELLULAR_SETTINGS =
-            new Intent().setComponent(DATA_PLAN_CELLULAR_COMPONENT);
-
     private static final String ENABLE_SETTINGS_DATA_PLAN = "enable.settings.data.plan";
 
     private final NetworkController mController;
@@ -107,7 +98,7 @@
 
     @Override
     public Intent getLongClickIntent() {
-        return getCellularSettingIntent(mContext);
+        return getCellularSettingIntent();
     }
 
     @Override
@@ -148,8 +139,7 @@
             showDetail(true);
         } else {
             mActivityStarter
-                    .postStartActivityDismissingKeyguard(getCellularSettingIntent(mContext),
-                            0 /* delay */);
+                    .postStartActivityDismissingKeyguard(getCellularSettingIntent(),0 /* delay */);
         }
     }
 
@@ -293,25 +283,8 @@
         }
     }
 
-    static Intent getCellularSettingIntent(Context context) {
-        // TODO(b/62349208): We should replace feature flag check below with data plans
-        // availability check. If the data plans are available we display the data plans usage
-        // summary otherwise we display data usage summary without data plans.
-        boolean isDataPlanFeatureEnabled =
-                SystemProperties.getBoolean(ENABLE_SETTINGS_DATA_PLAN, false /* default */);
-        context.getPackageManager()
-                .setComponentEnabledSetting(
-                        DATA_PLAN_CELLULAR_COMPONENT,
-                        isDataPlanFeatureEnabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
-                                : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                        PackageManager.DONT_KILL_APP);
-        context.getPackageManager()
-                .setComponentEnabledSetting(
-                        CELLULAR_SETTING_COMPONENT,
-                        isDataPlanFeatureEnabled ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
-                                : PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
-                        PackageManager.DONT_KILL_APP);
-        return isDataPlanFeatureEnabled ? DATA_PLAN_CELLULAR_SETTINGS : CELLULAR_SETTINGS;
+    static Intent getCellularSettingIntent() {
+        return new Intent(Settings.ACTION_DATA_USAGE_SETTINGS);
     }
 
     private final class CellularDetailAdapter implements DetailAdapter {
@@ -330,7 +303,7 @@
 
         @Override
         public Intent getSettingsIntent() {
-            return getCellularSettingIntent(mContext);
+            return getCellularSettingIntent();
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index a102696..ace361b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -55,7 +55,7 @@
 
     @Override
     public Intent getLongClickIntent() {
-        return CellularTile.getCellularSettingIntent(mContext);
+        return CellularTile.getCellularSettingIntent();
     }
     @Override
     protected void handleClick() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index bc14203..859dc39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -58,6 +58,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.text.NumberFormat;
+import java.util.IllegalFormatConversionException;
 
 /**
  * Controls the indications and error messages shown on the Keyguard
@@ -414,11 +415,24 @@
         String percentage = NumberFormat.getPercentInstance()
                 .format(mBatteryLevel / 100f);
         if (hasChargingTime) {
+            // We now have battery percentage in these strings and it's expected that all
+            // locales will also have it in the future. For now, we still have to support the old
+            // format until all languages get the new translations.
             String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
                     mContext, chargingTimeRemaining);
-            return mContext.getResources().getString(chargingId, chargingTimeFormatted, percentage);
+            try {
+                return mContext.getResources().getString(chargingId, chargingTimeFormatted,
+                        percentage);
+            } catch (IllegalFormatConversionException e) {
+                return mContext.getResources().getString(chargingId, chargingTimeFormatted);
+            }
         } else {
-            return mContext.getResources().getString(chargingId, percentage);
+            // Same as above
+            try {
+                return mContext.getResources().getString(chargingId, percentage);
+            } catch (IllegalFormatConversionException e) {
+                return mContext.getResources().getString(chargingId);
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 948f524..defb46c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
 import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
 
 import android.app.ActivityManager;
@@ -108,6 +110,7 @@
         mLp.setTitle("StatusBar");
         mLp.accessibilityTitle = mContext.getString(R.string.status_bar);
         mLp.packageName = mContext.getPackageName();
+        mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         mStatusBarView = statusBarView;
         mBarHeight = barHeight;
         mWindowManager.addView(mStatusBarView, mLp);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index f0854ed..d3f74ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -251,8 +251,11 @@
             if (mConfig.inflateSignalStrengths) {
                 level++;
             }
-            return SignalDrawable.getState(level, getNumLevels(),
-                    mCurrentState.inetCondition == 0);
+            boolean dataDisabled = mCurrentState.userSetup
+                    && mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
+            boolean noInternet = mCurrentState.inetCondition == 0;
+            boolean cutOut = dataDisabled || noInternet;
+            return SignalDrawable.getState(level, getNumLevels(), cutOut);
         } else if (mCurrentState.enabled) {
             return SignalDrawable.getEmptyState(getNumLevels());
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index aaa0568..09a1e44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -44,10 +44,6 @@
     static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus;
     static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
 
-    static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled;
-
-    static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled;
-
     static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
             "CARRIER_NETWORK_CHANGE",
             null,
@@ -232,9 +228,9 @@
             0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_cell_data_off,
-            TelephonyIcons.ICON_DATA_DISABLED,
+            0,
             false,
-            TelephonyIcons.QS_ICON_DATA_DISABLED
+            0
             );
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 8aab837..27cd9a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -353,6 +353,13 @@
 
     protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
             boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut) {
+        verifyLastMobileDataIndicators(
+                visible, icon, typeIcon, qsVisible, qsIcon, qsTypeIcon, dataIn, dataOut, false);
+    }
+
+    protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
+            boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut,
+            boolean cutOut) {
         ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
         ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
         ArgumentCaptor<IconState> qsIconArg = ArgumentCaptor.forClass(IconState.class);
@@ -372,7 +379,7 @@
         IconState iconState = iconArg.getValue();
 
         int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS,
-                false);
+                cutOut);
         assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
         assertEquals("Signal icon in status bar", state, iconState.icon);
         assertEquals("Visibility in status bar", visible, iconState.visible);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 3b796ca..cf3620d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -111,6 +111,20 @@
     }
 
     @Test
+    public void testNoInternetIcon() {
+        setupNetworkController();
+        when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
+        setupDefaultSignal();
+        updateDataConnectionState(TelephonyManager.DATA_CONNECTED, 0);
+        setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
+
+        // Verify that a SignalDrawable with a cut out is used to display data disabled.
+        verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
+                true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
+                false, true);
+    }
+
+    @Test
     public void testDataDisabledIcon() {
         setupNetworkController();
         when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
@@ -118,8 +132,10 @@
         updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
         setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
 
-        verifyDataIndicators(TelephonyIcons.ICON_DATA_DISABLED,
-                TelephonyIcons.QS_ICON_DATA_DISABLED);
+        // Verify that a SignalDrawable with a cut out is used to display data disabled.
+        verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
+                true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
+                false, true);
     }
 
     @Test
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bf25928..62d91a8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3364,7 +3364,8 @@
 
     /**
      * Update AMS states when an activity is resumed. This should only be called by
-     * {@link ActivityStack#setResumedActivityLocked} when an activity is resumed.
+     * {@link ActivityStack#onActivityStateChanged(ActivityRecord, ActivityState, String)} when an
+     * activity is resumed.
      */
     @GuardedBy("this")
     void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index e6d6fdf..59f027a 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1636,7 +1636,11 @@
 
         mRecentTransitions.add(new StateTransition(prev, state, reason));
 
-        mState = state;
+        final TaskRecord parent = getTask();
+
+        if (parent != null) {
+            parent.onActivityStateChanged(this, state, reason);
+        }
 
         if (isState(DESTROYING, DESTROYED)) {
             makeFinishingLocked();
@@ -2111,7 +2115,7 @@
         if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) {
             final ActivityStack stack = mStackSupervisor.getFocusedStack();
             // Try to use the one which is closest to top.
-            ActivityRecord r = stack.mResumedActivity;
+            ActivityRecord r = stack.getResumedActivity();
             if (r == null) {
                 r = stack.mPausingActivity;
             }
@@ -2208,7 +2212,7 @@
             return false;
         }
         final ActivityStack stack = getStack();
-        if (stack == null || this == stack.mResumedActivity || this == stack.mPausingActivity
+        if (stack == null || this == stack.getResumedActivity() || this == stack.mPausingActivity
                 || !haveState || !stopped) {
             // We're not ready for this kind of thing.
             return false;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 666f3a2..7749bd7 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -475,6 +475,28 @@
         return mWindowContainerController;
     }
 
+    /**
+     * This should be called when an activity in a child task changes state. This should only
+     * be called from
+     * {@link TaskRecord#onActivityStateChanged(ActivityRecord, ActivityState, String)}.
+     * @param record The {@link ActivityRecord} whose state has changed.
+     * @param state The new state.
+     * @param reason The reason for the change.
+     */
+    void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
+        if (record == mResumedActivity && state != RESUMED) {
+            clearResumedActivity(reason + " - onActivityStateChanged");
+        }
+
+        if (state == RESUMED) {
+            if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
+                    + reason);
+            mResumedActivity = record;
+            mService.setResumedActivityUncheckLocked(record, reason);
+            mStackSupervisor.mRecentTasks.add(record.getTask());
+        }
+    }
+
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
         final int prevWindowingMode = getWindowingMode();
@@ -1229,7 +1251,7 @@
     void minimalResumeActivityLocked(ActivityRecord r) {
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)"
                 + " callers=" + Debug.getCallers(5));
-        setResumedActivityLocked(r, "minimalResumeActivityLocked");
+        r.setState(RESUMED, "minimalResumeActivityLocked");
         r.completeResumeLocked();
         setLaunchTime(r);
         if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
@@ -1454,7 +1476,6 @@
 
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
         else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
-        mResumedActivity = null;
         mPausingActivity = prev;
         mLastPausedActivity = prev;
         mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
@@ -2282,13 +2303,21 @@
         return result;
     }
 
-    void setResumedActivityLocked(ActivityRecord r, String reason) {
-        // TODO: move mResumedActivity to stack supervisor,
-        // there should only be 1 global copy of resumed activity.
-        mResumedActivity = r;
-        r.setState(RESUMED, "setResumedActivityLocked");
-        mService.setResumedActivityUncheckLocked(r, reason);
-        mStackSupervisor.mRecentTasks.add(r.getTask());
+    /**
+     * Returns the currently resumed activity.
+     */
+    protected ActivityRecord getResumedActivity() {
+        return mResumedActivity;
+    }
+
+    /**
+     * Clears reference to currently resumed activity.
+     */
+    private void clearResumedActivity(String reason) {
+        if (DEBUG_STACK) Slog.d(TAG_STACK, "clearResumedActivity: " + mResumedActivity + " reason:"
+                + reason);
+
+        mResumedActivity = null;
     }
 
     @GuardedBy("mService")
@@ -2577,7 +2606,7 @@
                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
                         + " (in existing)");
 
-                setResumedActivityLocked(next, "resumeTopActivityInnerLocked");
+                next.setState(RESUMED, "resumeTopActivityInnerLocked");
 
                 mService.updateLruProcessLocked(next.app, true, null);
                 updateLRUListLocked(next);
@@ -2679,7 +2708,7 @@
                             + lastState + ": " + next);
                     next.setState(lastState, "resumeTopActivityInnerLocked");
                     if (lastStack != null) {
-                        lastStack.mResumedActivity = lastResumedActivity;
+                        lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                     }
                     Slog.i(TAG, "Restarting because process died: " + next);
                     if (!next.hasBeenLaunched) {
@@ -3779,9 +3808,6 @@
         mStackSupervisor.mStoppingActivities.remove(r);
         mStackSupervisor.mGoingToSleepActivities.remove(r);
         mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r);
-        if (mResumedActivity == r) {
-            mResumedActivity = null;
-        }
         final ActivityState prevState = r.getState();
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
 
@@ -3994,7 +4020,7 @@
      */
     void onActivityRemovedFromStack(ActivityRecord r) {
         if (mResumedActivity == r) {
-            mResumedActivity = null;
+            clearResumedActivity("onActivityRemovedFromStack");
         }
         if (mPausingActivity == r) {
             mPausingActivity = null;
@@ -5186,7 +5212,7 @@
                         + " other stack to this stack mResumedActivity=" + mResumedActivity
                         + " other mResumedActivity=" + topRunningActivity);
             }
-            mResumedActivity = topRunningActivity;
+            topRunningActivity.setState(RESUMED, "positionChildAt");
         }
 
         // The task might have already been running and its visibility needs to be synchronized with
@@ -5231,7 +5257,7 @@
         // so that we don't resume the same activity again in the new stack.
         // Apps may depend on onResume()/onPause() being called in pairs.
         if (setResume) {
-            mResumedActivity = r;
+            r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded");
             updateLRUListLocked(r);
         }
         // If the activity was previously pausing, then ensure we transfer that as well
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index d372bd8..0216439 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -930,7 +930,7 @@
         if (stack == null) {
             return null;
         }
-        ActivityRecord resumedActivity = stack.mResumedActivity;
+        ActivityRecord resumedActivity = stack.getResumedActivity();
         if (resumedActivity == null || resumedActivity.app == null) {
             resumedActivity = stack.mPausingActivity;
             if (resumedActivity == null || resumedActivity.app == null) {
@@ -985,7 +985,7 @@
                 if (!isFocusedStack(stack) || stack.numActivities() == 0) {
                     continue;
                 }
-                final ActivityRecord resumedActivity = stack.mResumedActivity;
+                final ActivityRecord resumedActivity = stack.getResumedActivity();
                 if (resumedActivity == null || !resumedActivity.idle) {
                     if (DEBUG_STATES) Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
                              + stack.mStackId + " " + resumedActivity + " not idle");
@@ -1004,7 +1004,7 @@
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 if (isFocusedStack(stack)) {
-                    final ActivityRecord r = stack.mResumedActivity;
+                    final ActivityRecord r = stack.getResumedActivity();
                     if (r != null && !r.isState(RESUMED)) {
                         return false;
                     }
@@ -1025,7 +1025,7 @@
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
-                final ActivityRecord r = stack.mResumedActivity;
+                final ActivityRecord r = stack.getResumedActivity();
                 if (r != null) {
                     if (!r.nowVisible || mActivitiesWaitingForVisibleActivity.contains(r)) {
                         return false;
@@ -1051,9 +1051,9 @@
             final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
-                if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
+                if (!isFocusedStack(stack) && stack.getResumedActivity() != null) {
                     if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
-                            " mResumedActivity=" + stack.mResumedActivity);
+                            " mResumedActivity=" + stack.getResumedActivity());
                     someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
                             dontWait);
                 }
@@ -2063,8 +2063,9 @@
             for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 if (isFocusedStack(stack)) {
-                    if (stack.mResumedActivity != null) {
-                        fgApp = stack.mResumedActivity.app;
+                    final ActivityRecord resumedActivity = stack.getResumedActivity();
+                    if (resumedActivity != null) {
+                        fgApp = resumedActivity.app;
                     } else if (stack.mPausingActivity != null) {
                         fgApp = stack.mPausingActivity.app;
                     }
@@ -3734,7 +3735,7 @@
                                 + " state=" + state);
                     }
                 } else {
-                    final ActivityRecord resumed = stack.mResumedActivity;
+                    final ActivityRecord resumed = stack.getResumedActivity();
                     if (resumed != null && resumed == r) Slog.e(TAG,
                             "validateTop...: back stack has resumed activity r=" + r
                             + " state=" + state);
@@ -3884,7 +3885,7 @@
                     printed = true;
                     needSep = false;
                 }
-                pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
+                pr = printThisActivity(pw, stack.getResumedActivity(), dumpPackage, needSep,
                         "    mResumedActivity: ");
                 if (pr) {
                     printed = true;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index fcdf3d2..bd53eac 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -820,8 +820,8 @@
 
         // If we are starting an activity that is not from the same uid as the currently resumed
         // one, check whether app switches are allowed.
-        if (voiceSession == null && (stack.mResumedActivity == null
-                || stack.mResumedActivity.info.applicationInfo.uid != realCallingUid)) {
+        if (voiceSession == null && (stack.getResumedActivity() == null
+                || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
             if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                     realCallingPid, realCallingUid, "Activity start")) {
                 mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 8174f40..7280f57 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -650,7 +650,7 @@
             final ActivityRecord r = topRunningActivityLocked();
             final boolean wasFocused = r != null && supervisor.isFocusedStack(sourceStack)
                     && (topRunningActivityLocked() == r);
-            final boolean wasResumed = r != null && sourceStack.mResumedActivity == r;
+            final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
             final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
 
             // In some cases the focused stack isn't the front stack. E.g. pinned stack.
@@ -1754,6 +1754,22 @@
         return !mTmpConfig.equals(newConfig);
     }
 
+    /**
+     * This should be called when an child activity changes state. This should only
+     * be called from
+     * {@link ActivityRecord#setState(ActivityState, String)} .
+     * @param record The {@link ActivityRecord} whose state has changed.
+     * @param state The new state.
+     * @param reason The reason for the change.
+     */
+    void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
+        final ActivityStack parent = getStack();
+
+        if (parent != null) {
+            parent.onActivityStateChanged(record, state, reason);
+        }
+    }
+
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
         final boolean wasInMultiWindowMode = inMultiWindowMode();
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
index 2a9d3860..ff1e29b 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
@@ -120,6 +120,12 @@
         }
     }
 
+    private boolean checkConfiguredLocked() {
+        if (mTunerCallback.isInitialConfigurationDone()) return true;
+        Slog.w(TAG, "Initial configuration is still pending, skipping the operation");
+        return false;
+    }
+
     @Override
     public void setConfiguration(RadioManager.BandConfig config) {
         if (config == null) {
@@ -170,6 +176,7 @@
     public void step(boolean directionDown, boolean skipSubChannel) {
         synchronized (mLock) {
             checkNotClosedLocked();
+            if (!checkConfiguredLocked()) return;
             nativeStep(mNativeContext, directionDown, skipSubChannel);
         }
     }
@@ -178,6 +185,7 @@
     public void scan(boolean directionDown, boolean skipSubChannel) {
         synchronized (mLock) {
             checkNotClosedLocked();
+            if (!checkConfiguredLocked()) return;
             nativeScan(mNativeContext, directionDown, skipSubChannel);
         }
     }
@@ -190,6 +198,7 @@
         Slog.i(TAG, "Tuning to " + selector);
         synchronized (mLock) {
             checkNotClosedLocked();
+            if (!checkConfiguredLocked()) return;
             nativeTune(mNativeContext, selector);
         }
     }
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
index 7ad73c3..32b1d1a 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
@@ -47,6 +47,7 @@
     @NonNull private final ITunerCallback mClientCallback;
 
     private final AtomicReference<ProgramList.Filter> mProgramListFilter = new AtomicReference<>();
+    private boolean mInitialConfigurationDone = false;
 
     TunerCallback(@NonNull Tuner tuner, @NonNull ITunerCallback clientCallback, int halRev) {
         mTuner = tuner;
@@ -95,6 +96,10 @@
         mProgramListFilter.set(null);
     }
 
+    boolean isInitialConfigurationDone() {
+        return mInitialConfigurationDone;
+    }
+
     @Override
     public void onError(int status) {
         dispatch(() -> mClientCallback.onError(status));
@@ -107,6 +112,7 @@
 
     @Override
     public void onConfigurationChanged(RadioManager.BandConfig config) {
+        mInitialConfigurationDone = true;
         dispatch(() -> mClientCallback.onConfigurationChanged(config));
     }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8bc9830..a0e4f4f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -427,6 +427,8 @@
                 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
     }
 
+    private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
+
     /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
     static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
 
@@ -674,6 +676,7 @@
 
     private boolean mPendingKeyguardOccluded;
     private boolean mKeyguardOccludedChanged;
+    private boolean mNotifyUserActivity;
 
     boolean mShowingDream;
     private boolean mLastShowingDream;
@@ -721,6 +724,9 @@
     // 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
@@ -828,6 +834,7 @@
     private static final int MSG_LAUNCH_ASSIST = 26;
     private static final int MSG_LAUNCH_ASSIST_LONG_PRESS = 27;
     private static final int MSG_POWER_VERY_LONG_PRESS = 28;
+    private static final int MSG_NOTIFY_USER_ACTIVITY = 29;
 
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -929,6 +936,13 @@
                 case MSG_HANDLE_ALL_APPS:
                     launchAllAppsAction();
                     break;
+                case MSG_NOTIFY_USER_ACTIVITY:
+                    removeMessages(MSG_NOTIFY_USER_ACTIVITY);
+                    Intent intent = new Intent(ACTION_USER_ACTIVITY_NOTIFICATION);
+                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                    mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+                            android.Manifest.permission.USER_ACTIVITY);
+                    break;
             }
         }
     }
@@ -984,6 +998,9 @@
             resolver.registerContentObserver(Settings.Global.getUriFor(
                     Settings.Global.POLICY_CONTROL), false, this,
                     UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED), false, this,
+                    UserHandle.USER_ALL);
             updateSettings();
         }
 
@@ -2359,6 +2376,9 @@
                     Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
                     Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
                     UserHandle.USER_CURRENT);
+            mSystemNavigationKeysEnabled = Settings.Secure.getIntForUser(resolver,
+                    Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
+                    0, UserHandle.USER_CURRENT) == 1;
 
             // Configure rotation suggestions.
             int showRotationSuggestions = Settings.Secure.getIntForUser(resolver,
@@ -6224,7 +6244,7 @@
         if (event.getAction() == KeyEvent.ACTION_UP) {
             if (!mAccessibilityManager.isEnabled()
                     || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
-                if (areSystemNavigationKeysEnabled()) {
+                if (mSystemNavigationKeysEnabled) {
                     sendSystemKeyToStatusBarAsync(event.getKeyCode());
                 }
             }
@@ -7486,6 +7506,13 @@
         mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
     }
 
+    @Override
+    public void requestUserActivityNotification() {
+        if (!mNotifyUserActivity && !mHandler.hasMessages(MSG_NOTIFY_USER_ACTIVITY)) {
+            mNotifyUserActivity = true;
+        }
+    }
+
     /** {@inheritDoc} */
     @Override
     public void userActivity() {
@@ -7507,6 +7534,12 @@
                 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
             }
         }
+
+        if (mAwake && mNotifyUserActivity) {
+            mHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
+                    USER_ACTIVITY_NOTIFICATION_DELAY);
+            mNotifyUserActivity = false;
+        }
     }
 
     class ScreenLockTimeout implements Runnable {
@@ -7803,11 +7836,6 @@
                 Settings.Global.THEATER_MODE_ON, 0) == 1;
     }
 
-    private boolean areSystemNavigationKeysEnabled() {
-        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
-    }
-
     @Override
     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
         if (!mVibrator.hasVibrator()) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index d5c12f7..cd6ff30 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1718,4 +1718,10 @@
                 return Integer.toString(mode);
         }
     }
+
+    /**
+     * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
+     * on the next user activity.
+     */
+    public void requestUserActivityNotification();
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2041c6f..b44d8a9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6989,6 +6989,15 @@
         mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
     }
 
+    @Override
+    public void requestUserActivityNotification() {
+        if (!checkCallingPermission(android.Manifest.permission.USER_ACTIVITY,
+                "requestUserActivityNotification()")) {
+            throw new SecurityException("Requires USER_ACTIVITY permission");
+        }
+        mPolicy.requestUserActivityNotification();
+    }
+
     void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
         if (seamlesslyRotated == w.mSeamlesslyRotated) {
             return;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f36b692..c4185fa 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2284,13 +2284,14 @@
         // interactive, the value may persist until the next animation, which could potentially
         // be occurring while turning off the screen. This would lead to the screen incorrectly
         // turning back on.
-        if (hasTurnScreenOnFlag && allowTheaterMode && canTurnScreenOn
-                && !mPowerManagerWrapper.isInteractive()) {
-            if (DEBUG_VISIBILITY || DEBUG_POWER) {
-                Slog.v(TAG, "Relayout window turning screen on: " + this);
+        if (hasTurnScreenOnFlag) {
+            if (allowTheaterMode && canTurnScreenOn && !mPowerManagerWrapper.isInteractive()) {
+                if (DEBUG_VISIBILITY || DEBUG_POWER) {
+                    Slog.v(TAG, "Relayout window turning screen on: " + this);
+                }
+                mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),
+                        "android.server.wm:TURN_ON");
             }
-            mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),
-                    "android.server.wm:TURN_ON");
 
             if (mAppToken != null) {
                 mAppToken.setCanTurnScreenOn(false);
diff --git a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
index 14e3578..ecf1a33 100644
--- a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
+++ b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
@@ -72,6 +72,7 @@
 struct Module {
     sp<V1_0::IBroadcastRadio> radioModule;
     HalRevision halRev;
+    std::vector<hardware::broadcastradio::V1_0::BandConfig> bands;
 };
 
 struct ServiceContext {
@@ -169,7 +170,8 @@
             if (module10 == nullptr) continue;
 
             auto idx = ctx.mModules.size();
-            ctx.mModules.push_back({module10, halRev});
+            ctx.mModules.push_back({module10, halRev, {}});
+            auto& nModule = ctx.mModules[idx];
             ALOGI("loaded broadcast radio module %zu: %s:%s (HAL 1.%d)",
                     idx, serviceName.c_str(), V1_0::toString(clazz).c_str(), halMinor);
 
@@ -178,6 +180,7 @@
             Return<void> hidlResult;
             if (module11 != nullptr) {
                 hidlResult = module11->getProperties_1_1([&](const V1_1::Properties& properties) {
+                    nModule.bands = properties.base.bands;
                     jModule = convert::ModulePropertiesFromHal(env, properties, idx, serviceName);
                 });
             } else {
@@ -185,6 +188,7 @@
                         const V1_0::Properties& properties) {
                     halResult = result;
                     if (result != Result::OK) return;
+                    nModule.bands = properties.bands;
                     jModule = convert::ModulePropertiesFromHal(env, properties, idx, serviceName);
                 });
             }
@@ -217,7 +221,21 @@
     auto module = ctx.mModules[moduleId];
 
     Region region;
-    BandConfig bandConfigHal = convert::BandConfigToHal(env, bandConfig, region);
+    BandConfig bandConfigHal;
+    if (bandConfig != nullptr) {
+        bandConfigHal = convert::BandConfigToHal(env, bandConfig, region);
+    } else {
+        region = Region::INVALID;
+        if (module.bands.size() == 0) {
+            ALOGE("No bands defined");
+            return nullptr;
+        }
+        bandConfigHal = module.bands[0];
+        if (bandConfigHal.spacings.size() > 1) {
+            bandConfigHal.spacings = hidl_vec<uint32_t>({ *std::min_element(
+                    bandConfigHal.spacings.begin(), bandConfigHal.spacings.end()) });
+        }
+    }
 
     auto tuner = make_javaref(env, env->NewObject(gjni.Tuner.clazz, gjni.Tuner.cstor,
             callback, module.halRev, region, withAudio, bandConfigHal.type));
diff --git a/services/core/jni/BroadcastRadio/types.h b/services/core/jni/BroadcastRadio/types.h
index 64a4f63..910bb7c 100644
--- a/services/core/jni/BroadcastRadio/types.h
+++ b/services/core/jni/BroadcastRadio/types.h
@@ -41,6 +41,7 @@
 
 // Keep in sync with REGION_* constants from RadioManager.java.
 enum class Region : jint {
+    INVALID = -1,
     ITU_1 = 0,
     ITU_2 = 1,
     OIRT = 2,
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index d60623d..bda68d1 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -26,6 +26,8 @@
 
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 
 import static org.junit.Assert.assertEquals;
@@ -99,7 +101,7 @@
         // Simulate the a resumed activity set during
         // {@link ActivityStack#resumeTopActivityUncheckedLocked}.
         mSupervisor.inResumeTopActivity = true;
-        mStack.mResumedActivity = r;
+        r.setState(RESUMED, "testNoPauseDuringResumeTopActivity");
 
         final boolean waiting = mStack.goToSleepIfPossible(false);
 
@@ -107,7 +109,18 @@
         assertFalse(waiting);
 
         // Make sure the resumed activity is untouched.
-        assertEquals(mStack.mResumedActivity, r);
+        assertEquals(mStack.getResumedActivity(), r);
+    }
+
+    @Test
+    public void testResumedActivity() throws Exception {
+        final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
+        assertEquals(mStack.getResumedActivity(), null);
+        r.setState(RESUMED, "testResumedActivity");
+        assertEquals(mStack.getResumedActivity(), r);
+        r.setState(PAUSING, "testResumedActivity");
+        assertEquals(mStack.getResumedActivity(), null);
+
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
index 091d9bd..f740654 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
@@ -42,7 +42,11 @@
 import java.io.ByteArrayOutputStream;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
+import java.time.Instant;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -257,7 +261,7 @@
     @Test
     public void testInstallationOptionWithoutFreeze() {
         // Also duplicated at com.google.android.gts.deviceowner.SystemUpdatePolicyTest
-        final long millis_2018_01_01 = TimeUnit.SECONDS.toMillis(1514764800);
+        final long millis_2018_01_01 = toMillis(2018, 1, 1);
 
         SystemUpdatePolicy p = SystemUpdatePolicy.createAutomaticInstallPolicy();
         assertInstallationOption(SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, Long.MAX_VALUE,
@@ -294,11 +298,11 @@
 
     @Test
     public void testInstallationOptionWithFreeze() throws Exception {
-        final long millis_2016_02_29 = TimeUnit.SECONDS.toMillis(1456704000);
-        final long millis_2017_01_31 = TimeUnit.SECONDS.toMillis(1485820800);
-        final long millis_2017_02_28 = TimeUnit.SECONDS.toMillis(1488240000);
-        final long millis_2018_01_01 = TimeUnit.SECONDS.toMillis(1514764800);
-        final long millis_2018_08_01 = TimeUnit.SECONDS.toMillis(1533081600);
+        final long millis_2016_02_29 = toMillis(2016, 2, 29);
+        final long millis_2017_01_31 = toMillis(2017, 1, 31);
+        final long millis_2017_02_28 = toMillis(2017, 2, 28);
+        final long millis_2018_01_01 = toMillis(2018, 1, 1);
+        final long millis_2018_08_01 = toMillis(2018, 8, 1);
 
         SystemUpdatePolicy p = SystemUpdatePolicy.createAutomaticInstallPolicy();
         setFreezePeriods(p, "01-01", "01-31");
@@ -313,12 +317,12 @@
 
         // Freeze period contains leap day Feb 29
         p = SystemUpdatePolicy.createPostponeInstallPolicy();
-        setFreezePeriods(p, "02-01", "03-15");
-        // Freezed until 3/31, note 2016 is a leap year
-        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+        setFreezePeriods(p, "02-01", "03-05");
+        // Freezed until 3/5, note 2016 is a leap year
+        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(6),
                 millis_2016_02_29, p);
-        // Freezed until 3/31, note 2017 is not a leap year
-        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+        // Freezed until 3/5, note 2017 is not a leap year
+        assertInstallationOption(SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(6),
                 millis_2017_02_28, p);
         // Next freeze is 2018/2/1
         assertInstallationOption(SystemUpdatePolicy.TYPE_POSTPONE, TimeUnit.DAYS.toMillis(31),
@@ -333,12 +337,12 @@
         assertInstallationOption(
                 SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(1),
                 millis_2017_02_28, p);
-        setFreezePeriods(p, "02-28", "03-15");
+        setFreezePeriods(p, "02-28", "03-05");
         assertInstallationOption(
-                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(6),
                 millis_2016_02_29, p);
         assertInstallationOption(
-                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(16),
+                SystemUpdatePolicy.TYPE_PAUSE, TimeUnit.DAYS.toMillis(6),
                 millis_2017_02_28, p);
 
         // Freeze period end on or right after leap day
@@ -382,10 +386,10 @@
 
         // Two freeze periods
         p = SystemUpdatePolicy.createAutomaticInstallPolicy();
-        setFreezePeriods(p, "05-01", "06-01", "12-01", "01-31");
-        // automatic policy for August, September, November and December
+        setFreezePeriods(p, "05-01", "06-01", "11-01", "01-29");
+        // automatic policy for July, August, September and October
         assertInstallationOption(
-                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(122),
+                SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC, TimeUnit.DAYS.toMillis(92),
                 millis_2018_08_01, p);
     }
 
@@ -510,4 +514,9 @@
             return result;
         }
     }
+
+    private long toMillis(int year, int month, int day) {
+        return LocalDateTime.of(year, month, day, 0, 0, 0).atZone(ZoneId.systemDefault())
+                .toInstant().toEpochMilli();
+    }
 }
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 34c5db3..6784e30 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -652,4 +652,8 @@
     @Override
     public void onScreenMagnificationStateChanged(boolean active) {
     }
+
+    @Override
+    public void requestUserActivityNotification() {
+    }
 }
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a79f2c9..73243d2 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -879,42 +879,76 @@
         /**
          * @hide
          */
-        @IntDef({HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_DEST_NOT_SUPPORTED,
-                HANDOVER_FAILURE_DEST_INVALID_PERM, HANDOVER_FAILURE_DEST_USER_REJECTED,
-                HANDOVER_FAILURE_ONGOING_EMERG_CALL})
+        @IntDef(prefix = { "HANDOVER_" },
+                value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
+                HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERG_CALL,
+                HANDOVER_FAILURE_UNKNOWN})
         @Retention(RetentionPolicy.SOURCE)
         public @interface HandoverFailureErrors {}
 
         /**
          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
-         * to handover the call rejects handover.
+         * to handover the call to rejects the handover request.
+         * <p>
+         * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
+         * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
+         * {@code null} {@link Connection} from
+         * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+         * ConnectionRequest)}.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
         public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
 
         /**
-         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there is
-         * an error associated with unsupported handover.
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+         * is initiated but the source or destination app does not support handover.
+         * <p>
+         * Will be returned when a handover is requested via
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
+         * {@link PhoneAccountHandle} does not declare
+         * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.  May also be returned when a handover is
+         * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
+         * {@link Details#getAccountHandle()}) does not declare
+         * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2;
+        public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
 
         /**
-         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
-         * are some permission errors associated with APIs doing handover.
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
+         * user rejects the handover request.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3;
-
-        /**
-         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when user
-         * rejects handover.
-         */
-        public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4;
+        public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
 
         /**
          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
          * is ongoing emergency call.
+         * <p>
+         * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
+         * called on an emergency call, or if any other call is an emergency call.
+         * <p>
+         * Handovers are not permitted while there are ongoing emergency calls.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5;
+        public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4;
 
+        /**
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+         * fails for an unknown reason.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
+         */
+        public static final int HANDOVER_FAILURE_UNKNOWN = 5;
 
         /**
          * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
@@ -1055,6 +1089,10 @@
         /**
          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
          * has completed successfully.
+         * <p>
+         * For a full discussion of the handover process and the APIs involved, see
+         * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+         *
          * @param call The call which had initiated handover.
          */
         public void onHandoverComplete(Call call) {}
@@ -1062,8 +1100,12 @@
         /**
          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
          * has failed.
+         * <p>
+         * For a full discussion of the handover process and the APIs involved, see
+         * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+         *
          * @param call The call which had initiated handover.
-         * @param failureReason Error reason for failure
+         * @param failureReason Error reason for failure.
          */
         public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
     }
@@ -1260,7 +1302,7 @@
      * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
      * @param videoState The video state in which to answer the call.
      */
-    public void answer(int videoState) {
+    public void answer(@VideoProfile.VideoState int videoState) {
         mInCallAdapter.answerCall(mTelecomCallId, videoState);
     }
 
@@ -1474,16 +1516,65 @@
      * by {@code toHandle}.  The videoState specified indicates the desired video state after the
      * handover.
      * <p>
-     * A handover request is initiated by the user from one app to indicate a desire
-     * to handover a call to another.
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the device this method is called on is considered the
+     * <em>initiating</em> device (since the user initiates the handover from this device), and the
+     * other device is considered the <em>receiving</em> device.
+     * <p>
+     * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
+     * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
+     * and invoke
+     * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+     * ConnectionRequest)} to inform the destination app that a request has been made to handover a
+     * call to it.  The app returns an instance of {@link Connection} to represent the handover call
+     * At this point the app should display UI to indicate to the user that a call
+     * handover is in process.
+     * <p>
+     * The destination app is responsible for communicating the handover request from the
+     * <em>initiating</em> device to the <em>receiving</em> device.
+     * <p>
+     * When the app on the <em>receiving</em> device receives the handover request, it calls
+     * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
+     * process from the <em>initiating</em> device to the <em>receiving</em> device.  At this point
+     * the destination app on the <em>receiving</em> device should show UI to allow the user to
+     * choose whether they want to continue their call in the destination app.
+     * <p>
+     * When the destination app on the <em>receiving</em> device calls
+     * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
+     * {@link ConnectionService} and call
+     * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
+     * ConnectionRequest)} to inform it of the handover request.  The app returns an instance of
+     * {@link Connection} to represent the handover call.
+     * <p>
+     * If the user of the <em>receiving</em> device accepts the handover, the app calls
+     * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
+     * original call.  If the user rejects the handover, the app calls
+     * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
+     * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
+     * <p>
+     * Telecom will only allow handovers from {@link PhoneAccount}s which declare
+     * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.  Similarly, the {@link PhoneAccount}
+     * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
+     * <p>
+     * Errors in the handover process are reported to the {@link InCallService} via
+     * {@link Callback#onHandoverFailed(Call, int)}.  Errors in the handover process are reported to
+     * the involved {@link ConnectionService}s via
+     * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
      *
      * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
      *                 this call to.
-     * @param videoState Indicates the video state desired after the handover.
+     * @param videoState Indicates the video state desired after the handover (see the
+     *               {@code STATE_*} constants defined in {@link VideoProfile}).
      * @param extras Bundle containing extra information to be passed to the
      *               {@link ConnectionService}
      */
-    public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) {
+    public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
+            Bundle extras) {
         mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
     }
 
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index ffa0c94..fc32b17 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -2219,12 +2219,50 @@
     }
 
     /**
-     * Called by Telecom on the initiating side of the handover to create an instance of a
-     * handover connection.
+     * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+     * outgoing handover {@link Connection}.
+     * <p>
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+     * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+     * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+     * device.
+     * <p>
+     * This method is called on the destination {@link ConnectionService} on <em>initiating</em>
+     * device when the user initiates a handover request from one app to another.  The user request
+     * originates in the {@link InCallService} via
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * Implementations of this method should return an instance of {@link Connection} which
+     * represents the handover.  If your app does not wish to accept a handover to it at this time,
+     * you can return {@code null}.  The code below shows an example of how this is done.
+     * <pre>
+     * {@code
+     * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+     *     fromPhoneAccountHandle, ConnectionRequest request) {
+     *   if (!isHandoverAvailable()) {
+     *       return null;
+     *   }
+     *   MyConnection connection = new MyConnection();
+     *   connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+     *   connection.setVideoState(request.getVideoState());
+     *   return connection;
+     * }
+     * }
+     * </pre>
+     *
      * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
      *                               ConnectionService which needs to handover the call.
-     * @param request Details about the call which needs to be handover.
-     * @return Connection object corresponding to the handover call.
+     * @param request Details about the call to handover.
+     * @return {@link Connection} instance corresponding to the handover call.
      */
     public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
                                                          ConnectionRequest request) {
@@ -2232,12 +2270,46 @@
     }
 
     /**
-     * Called by Telecom on the receiving side of the handover to request the
-     * {@link ConnectionService} to create an instance of a handover connection.
+     * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+     * incoming handover {@link Connection}.
+     * <p>
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+     * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+     * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+     * device.
+     * <p>
+     * This method is called on the destination app on the <em>receiving</em> device when the
+     * destination app calls {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to
+     * accept an incoming handover from the <em>initiating</em> device.
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * Implementations of this method should return an instance of {@link Connection} which
+     * represents the handover.  The code below shows an example of how this is done.
+     * <pre>
+     * {@code
+     * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+     *     fromPhoneAccountHandle, ConnectionRequest request) {
+     *   // Given that your app requested to accept the handover, you should not return null here.
+     *   MyConnection connection = new MyConnection();
+     *   connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+     *   connection.setVideoState(request.getVideoState());
+     *   return connection;
+     * }
+     * }
+     * </pre>
+     *
      * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
      *                               ConnectionService which needs to handover the call.
      * @param request Details about the call which needs to be handover.
-     * @return {@link Connection} object corresponding to the handover call.
+     * @return {@link Connection} instance corresponding to the handover call.
      */
     public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
                                                          ConnectionRequest request) {
@@ -2247,11 +2319,15 @@
     /**
      * Called by Telecom in response to a {@code TelecomManager#acceptHandover()}
      * invocation which failed.
-     * @param request Details about the call which needs to be handover.
-     * @param error Reason for handover failure as defined in
-     *              {@link android.telecom.Call.Callback#HANDOVER_FAILURE_DEST_INVALID_PERM}
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}
+     *
+     * @param request Details about the call which failed to handover.
+     * @param error Reason for handover failure.  Will be one of the
      */
-    public void onHandoverFailed(ConnectionRequest request, int error) {
+    public void onHandoverFailed(ConnectionRequest request,
+            @Call.Callback.HandoverFailureErrors int error) {
         return;
     }
 
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 59ce590..bb4b483 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -93,6 +93,10 @@
                     // failure on the providing end, so immediately mark it destroyed
                     connection.setDestroyed();
                 }
+                connection.setStatusHints(parcel.getStatusHints());
+                connection.setIsVoipAudioMode(parcel.getIsVoipAudioMode());
+                connection.setRingbackRequested(parcel.isRingbackRequested());
+                connection.putExtras(parcel.getExtras());
             }
         }
 
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index e456830..72c67d3 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1794,8 +1794,25 @@
     }
 
     /**
-     * Called from the recipient side of a handover to indicate a desire to accept the handover
-     * of an ongoing call to another {@link ConnectionService} identified by
+     * Called by an app to indicate that it wishes to accept the handover of an ongoing call to a
+     * {@link PhoneAccountHandle} it defines.
+     * <p>
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+     * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+     * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+     * device.
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * This method is called from the <em>receiving</em> side of a handover to indicate a desire to
+     * accept the handover of an ongoing call to another {@link ConnectionService} identified by
      * {@link PhoneAccountHandle} destAcct. For managed {@link ConnectionService}s, the specified
      * {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
      * the user must have enabled the corresponding {@link PhoneAccount}.  This can be checked using
@@ -1819,7 +1836,8 @@
      * @param videoState Video state after the handover.
      * @param destAcct The {@link PhoneAccountHandle} registered to the calling package.
      */
-    public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
+    public void acceptHandover(Uri srcAddr, @VideoProfile.VideoState int videoState,
+            PhoneAccountHandle destAcct) {
         try {
             if (isServiceConnected()) {
                 getTelecomService().acceptHandover(srcAddr, videoState, destAcct);
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index e0e3a08..90ed36f 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -62,6 +62,7 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(
             flag = true,
+            prefix = { "STATE_" },
             value = {STATE_AUDIO_ONLY, STATE_TX_ENABLED, STATE_RX_ENABLED, STATE_BIDIRECTIONAL,
                     STATE_PAUSED})
     public @interface VideoState {}
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index ea2b0ae..4e56396 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -161,6 +161,7 @@
         mTdScdmaRscp = INVALID;
         mWcdmaSignalStrength = 99;
         mWcdmaRscp = INVALID;
+        mWcdmaRscpAsu = 255;
         mLteRsrpBoost = 0;
         mIsGsm = gsmFlag;
         mUseOnlyRsrpForLteLevel = false;
@@ -383,7 +384,7 @@
         // but are reported in ASU which is 0 through 96, so we do the conversion here
         mWcdmaRscpAsu =
                 ((mWcdmaRscpAsu - 120 >= MIN_WCDMA_RSCP) && (mWcdmaRscpAsu - 120 <= MAX_WCDMA_RSCP))
-                ? mWcdmaRscpAsu : INVALID;
+                ? mWcdmaRscpAsu : 255;
         mWcdmaRscp = ((mWcdmaRscp >= MIN_WCDMA_RSCP) && (mWcdmaRscp <= MAX_WCDMA_RSCP))
                 ? mWcdmaRscp : INVALID;