Merge "Allow mainline modules to set private window flags"
diff --git a/Android.mk b/Android.mk
index 5c4c237..73c0233 100644
--- a/Android.mk
+++ b/Android.mk
@@ -312,6 +312,9 @@
 $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE))
 $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE))
 $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE))
+$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE):apistubs/android/public/api/android.txt)
+$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE):apistubs/android/system/api/android.txt)
+$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE):apistubs/android/test/api/android.txt)
 
 # sdk.atree needs to copy the whole dir: $(OUT_DOCS)/offline-sdk to the final zip.
 # So keep offline-sdk-timestamp target here, and unzip offline-sdk-docs.zip to
diff --git a/api/current.txt b/api/current.txt
index c1a1c52..816148a 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -14015,6 +14015,7 @@
     method public android.os.LocaleList getTextLocales();
     method public void getTextPath(char[], int, int, float, float, android.graphics.Path);
     method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path);
+    method public float getTextRunAdvances(char[], int, int, int, int, boolean, float[], int);
     method public float getTextScaleX();
     method public float getTextSize();
     method public float getTextSkewX();
@@ -18676,6 +18677,37 @@
     field public static final int WORD_NUMBER_LIMIT = 200; // 0xc8
   }
 
+  public abstract class CaseMap {
+    method public static android.icu.text.CaseMap.Fold fold();
+    method public abstract android.icu.text.CaseMap omitUnchangedText();
+    method public static android.icu.text.CaseMap.Lower toLower();
+    method public static android.icu.text.CaseMap.Title toTitle();
+    method public static android.icu.text.CaseMap.Upper toUpper();
+  }
+
+  public static final class CaseMap.Fold extends android.icu.text.CaseMap {
+    method public <A extends java.lang.Appendable> A apply(java.lang.CharSequence, A, android.icu.text.Edits);
+    method public android.icu.text.CaseMap.Fold omitUnchangedText();
+    method public android.icu.text.CaseMap.Fold turkic();
+  }
+
+  public static final class CaseMap.Lower extends android.icu.text.CaseMap {
+    method public <A extends java.lang.Appendable> A apply(java.util.Locale, java.lang.CharSequence, A, android.icu.text.Edits);
+    method public android.icu.text.CaseMap.Lower omitUnchangedText();
+  }
+
+  public static final class CaseMap.Title extends android.icu.text.CaseMap {
+    method public <A extends java.lang.Appendable> A apply(java.util.Locale, android.icu.text.BreakIterator, java.lang.CharSequence, A, android.icu.text.Edits);
+    method public android.icu.text.CaseMap.Title noBreakAdjustment();
+    method public android.icu.text.CaseMap.Title noLowercase();
+    method public android.icu.text.CaseMap.Title omitUnchangedText();
+  }
+
+  public static final class CaseMap.Upper extends android.icu.text.CaseMap {
+    method public <A extends java.lang.Appendable> A apply(java.util.Locale, java.lang.CharSequence, A, android.icu.text.Edits);
+    method public android.icu.text.CaseMap.Upper omitUnchangedText();
+  }
+
   public final class CollationElementIterator {
     method public int getMaxExpansion(int);
     method public int getOffset();
@@ -19341,6 +19373,30 @@
     enum_constant public static final android.icu.text.DisplayContext.Type SUBSTITUTE_HANDLING;
   }
 
+  public final class Edits {
+    ctor public Edits();
+    method public void addReplace(int, int);
+    method public void addUnchanged(int);
+    method public android.icu.text.Edits.Iterator getCoarseChangesIterator();
+    method public android.icu.text.Edits.Iterator getCoarseIterator();
+    method public android.icu.text.Edits.Iterator getFineChangesIterator();
+    method public android.icu.text.Edits.Iterator getFineIterator();
+    method public boolean hasChanges();
+    method public int lengthDelta();
+    method public void reset();
+  }
+
+  public static final class Edits.Iterator {
+    method public int destinationIndex();
+    method public boolean findSourceIndex(int);
+    method public boolean hasChange();
+    method public int newLength();
+    method public boolean next();
+    method public int oldLength();
+    method public int replacementIndex();
+    method public int sourceIndex();
+  }
+
   public abstract class IDNA {
     method public static android.icu.text.IDNA getUTS46Instance(int);
     method public abstract java.lang.StringBuilder labelToASCII(java.lang.CharSequence, java.lang.StringBuilder, android.icu.text.IDNA.Info);
@@ -49697,6 +49753,7 @@
     method public boolean isScrollable();
     method public boolean isSelected();
     method public boolean isShowingHintText();
+    method public boolean isTextEntryKey();
     method public boolean isVisibleToUser();
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View, int);
@@ -49758,6 +49815,7 @@
     method public void setSource(android.view.View);
     method public void setSource(android.view.View, int);
     method public void setText(java.lang.CharSequence);
+    method public void setTextEntryKey(boolean);
     method public void setTextSelection(int, int);
     method public void setTooltipText(java.lang.CharSequence);
     method public void setTraversalAfter(android.view.View);
diff --git a/api/system-current.txt b/api/system-current.txt
index e26f8b37..43b97ab 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -91,6 +91,7 @@
     field public static final java.lang.String KILL_UID = "android.permission.KILL_UID";
     field public static final java.lang.String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
     field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
+    field public static final java.lang.String LOCK_DEVICE = "android.permission.LOCK_DEVICE";
     field public static final java.lang.String LOOP_RADIO = "android.permission.LOOP_RADIO";
     field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
     field public static final java.lang.String MANAGE_APP_OPS_RESTRICTIONS = "android.permission.MANAGE_APP_OPS_RESTRICTIONS";
@@ -155,6 +156,7 @@
     field public static final java.lang.String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER";
     field public static final java.lang.String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION";
     field public static final java.lang.String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES";
+    field public static final java.lang.String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
     field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
     field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
     field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
@@ -217,6 +219,14 @@
     field public static final int config_sendPackageName = 17891328; // 0x1110000
   }
 
+  public static final class R.dimen {
+    field public static final int config_restricted_icon_size = 17104903; // 0x1050007
+  }
+
+  public static final class R.drawable {
+    field public static final int ic_info = 17301684; // 0x10800b4
+  }
+
   public static final class R.raw {
     field public static final int loaderror = 17825792; // 0x1100000
     field public static final int nodomain = 17825793; // 0x1100001
@@ -1113,6 +1123,7 @@
   public class PackageItemInfo {
     method public deprecated java.lang.CharSequence loadSafeLabel(android.content.pm.PackageManager);
     method public java.lang.CharSequence loadSafeLabel(android.content.pm.PackageManager, float, int);
+    method public static void setForceSafeLabels(boolean);
     field public static final int SAFE_LABEL_FLAG_FIRST_LINE = 4; // 0x4
     field public static final int SAFE_LABEL_FLAG_SINGLE_LINE = 2; // 0x2
     field public static final int SAFE_LABEL_FLAG_TRIM = 1; // 0x1
@@ -4193,6 +4204,7 @@
     method public final void attachBaseContext(android.content.Context);
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract java.util.List<android.content.pm.permission.RuntimePermissionPresentationInfo> onGetAppPermissions(java.lang.String);
+    method public abstract void onRevokeRuntimePermission(java.lang.String, java.lang.String);
     field public static final java.lang.String SERVICE_INTERFACE = "android.permissionpresenterservice.RuntimePermissionPresenterService";
   }
 
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index b11e843..e14f2eb 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -207,7 +207,14 @@
 
     result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);
 
-    if (base == NULL) {
+    if (base == nullptr || result != NO_ERROR) {
+        String8 reason;
+        if (base == nullptr) {
+            reason = "Failed to write to buffer";
+        } else {
+            reason.appendFormat("Error Code: %d", result);
+        }
+        fprintf(stderr, "Failed to take screenshot (%s)\n", reason.c_str());
         close(fd);
         return 1;
     }
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 6ab4dd9..c8e6b46 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -168,6 +168,7 @@
         AppSize app_size = 10027;
         CategorySize category_size = 10028;
         android.service.procstats.ProcessStatsSectionProto proc_stats = 10029;
+        BatteryVoltage battery_voltage = 10030;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP. Field numbers above
@@ -431,9 +432,9 @@
  * Logs reporting of a ble scan finding results.
  *
  * Logged from:
- *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ *   packages/apps/Bluetooth/src/com/android/bluetooth/gatt/AppScanStats.java
  */
-// TODO: Consider changing to tracking per-scanner-id (log from AppScanStats).
+// TODO: Consider also tracking per-scanner-id.
 message BleScanResultReceived {
     repeated AttributionNode attribution_node = 1;
 
@@ -2176,6 +2177,16 @@
 }
 
 /**
+ * Pulls battery voltage.
+ * Pulled from:
+ *   frameworks/base/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
+ */
+message BatteryVoltage {
+    // The voltage of the battery, in millivolts.
+    optional int32 voltage_mV = 1;
+}
+
+/**
  * Pulls the temperature of various parts of the device.
  * The units are tenths of a degree Celsius. Eg: 30.3C is reported as 303.
  *
@@ -2261,6 +2272,14 @@
     optional int64 exception_count = 2;
 }
 
+/**
+ * Pulls the statistics of message dispatching on HandlerThreads.
+ *
+ * Looper stats will be reset every time the data is pulled. It means it can only be pulled by one
+ * config on the device.
+ *
+ * Next tag: 11
+ */
 message LooperStats {
     // Currently not collected and always set to 0.
     optional int32 uid = 1 [(is_uid) = true];
@@ -2304,8 +2323,11 @@
     // Total CPU usage of all processed message.
     // Average can be computed using recorded_total_cpu_micros /
     // recorded_message_count. Total can be computed using
-    // recorded_total_cpu_micros / recorded_message_count * call_count.
+    // recorded_total_cpu_micros / recorded_message_count * message_count.
     optional int64 recorded_total_cpu_micros = 9;
+
+    // True if the screen was interactive PowerManager#isInteractive at the end of the call.
+    optional bool screen_interactive = 10;
 }
 
 /**
diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
index ae97d7a..ae2cf74 100644
--- a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
+++ b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
@@ -67,6 +67,7 @@
     data->clear();
     bool result_success = true;
 
+    // Get the data from the Health HAL (hardware/interfaces/health/1.0/types.hal).
     Return<void> ret = gHealthHal->getHealthInfo([&](Result r, HealthInfo v) {
         if (r != Result::SUCCESS) {
             result_success = false;
@@ -84,6 +85,12 @@
             ptr->write(v.legacy.batteryFullCharge);
             ptr->init();
             data->push_back(ptr);
+        } else if (mTagId == android::util::BATTERY_VOLTAGE) {
+            auto ptr = make_shared<LogEvent>(android::util::BATTERY_VOLTAGE,
+                wallClockTimestampNs, elapsedTimestampNs);
+            ptr->write(v.legacy.batteryVoltage);
+            ptr->init();
+            data->push_back(ptr);
         } else {
             ALOGE("Unsupported tag in ResourceHealthManagerPuller: %d", mTagId);
         }
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index f6ba0b6..745ff74 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -161,6 +161,12 @@
           {},
           1 * NS_PER_SEC,
           new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}},
+        // battery_voltage
+        {android::util::BATTERY_VOLTAGE,
+         {{},
+          {},
+          1 * NS_PER_SEC,
+          new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
         // process_memory_state
         {android::util::PROCESS_MEMORY_STATE,
          {{4, 5, 6, 7, 8},
@@ -184,7 +190,7 @@
         // looper_stats
         {android::util::LOOPER_STATS,
          {{5, 6, 7, 8, 9},
-          {2, 3, 4},
+          {2, 3, 4, 10},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::LOOPER_STATS)}},
         // Disk Stats
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 8c347fc..0367d9b 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2134,6 +2134,7 @@
 Lcom/android/internal/telephony/SmsHeader$ConcatRef;-><init>()V
 Lcom/android/internal/telephony/SmsHeader$PortAddrs;-><init>()V
 Lcom/android/internal/telephony/SmsMessageBase;-><init>()V
+Lcom/android/internal/telephony/uicc/IccUtils;->bytesToHexString([B)Ljava/lang/String;
 Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/util/HexDump;->toHexString([BZ)Ljava/lang/String;
 Lcom/android/internal/view/BaseIWindow;-><init>()V
@@ -2247,6 +2248,108 @@
 Lcom/android/org/conscrypt/TrustedCertificateStore;->getCertificateChain(Ljava/security/cert/X509Certificate;)Ljava/util/List;
 Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
 Lcom/android/org/conscrypt/TrustManagerImpl;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
+Lcom/google/android/mms/ContentType;->getAudioTypes()Ljava/util/ArrayList;
+Lcom/google/android/mms/ContentType;->getImageTypes()Ljava/util/ArrayList;
+Lcom/google/android/mms/ContentType;->getVideoTypes()Ljava/util/ArrayList;
+Lcom/google/android/mms/ContentType;->isAudioType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isDrmType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isImageType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isTextType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isVideoType(Ljava/lang/String;)Z
+Lcom/google/android/mms/MmsException;-><init>()V
+Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/String;)V
+Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/Throwable;)V
+Lcom/google/android/mms/pdu/AcknowledgeInd;-><init>(I[B)V
+Lcom/google/android/mms/pdu/CharacterSets;->getMimeName(I)Ljava/lang/String;
+Lcom/google/android/mms/pdu/DeliveryInd;->getMessageId()[B
+Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(I[B)V
+Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(Ljava/lang/String;)V
+Lcom/google/android/mms/pdu/EncodedStringValue;-><init>([B)V
+Lcom/google/android/mms/pdu/EncodedStringValue;->concat([Lcom/google/android/mms/pdu/EncodedStringValue;)Ljava/lang/String;
+Lcom/google/android/mms/pdu/EncodedStringValue;->encodeStrings([Ljava/lang/String;)[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/EncodedStringValue;->getString()Ljava/lang/String;
+Lcom/google/android/mms/pdu/GenericPdu;->getMessageType()I
+Lcom/google/android/mms/pdu/GenericPdu;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getBody()Lcom/google/android/mms/pdu/PduBody;
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getDate()J
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getPriority()I
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getSubject()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getTo()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setBody(Lcom/google/android/mms/pdu/PduBody;)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setDate(J)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setPriority(I)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setSubject(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/NotificationInd;->getContentLocation()[B
+Lcom/google/android/mms/pdu/NotificationInd;->getExpiry()J
+Lcom/google/android/mms/pdu/NotificationInd;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/NotificationInd;->getMessageClass()[B
+Lcom/google/android/mms/pdu/NotificationInd;->getMessageSize()J
+Lcom/google/android/mms/pdu/NotificationInd;->getSubject()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/NotificationInd;->getTransactionId()[B
+Lcom/google/android/mms/pdu/NotificationInd;->setContentLocation([B)V
+Lcom/google/android/mms/pdu/NotifyRespInd;-><init>(I[BI)V
+Lcom/google/android/mms/pdu/PduBody;-><init>()V
+Lcom/google/android/mms/pdu/PduBody;->addPart(ILcom/google/android/mms/pdu/PduPart;)V
+Lcom/google/android/mms/pdu/PduBody;->addPart(Lcom/google/android/mms/pdu/PduPart;)Z
+Lcom/google/android/mms/pdu/PduBody;->getPart(I)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartByContentId(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartByContentLocation(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartByFileName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartByName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartsNum()I
+Lcom/google/android/mms/pdu/PduComposer;-><init>(Landroid/content/Context;Lcom/google/android/mms/pdu/GenericPdu;)V
+Lcom/google/android/mms/pdu/PduComposer;->make()[B
+Lcom/google/android/mms/pdu/PduParser;->parse()Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduPart;-><init>()V
+Lcom/google/android/mms/pdu/PduPart;->generateLocation()Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduPart;->getCharset()I
+Lcom/google/android/mms/pdu/PduPart;->getContentLocation()[B
+Lcom/google/android/mms/pdu/PduPart;->getContentType()[B
+Lcom/google/android/mms/pdu/PduPart;->getData()[B
+Lcom/google/android/mms/pdu/PduPart;->getDataUri()Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPart;->getFilename()[B
+Lcom/google/android/mms/pdu/PduPart;->getName()[B
+Lcom/google/android/mms/pdu/PduPart;->setCharset(I)V
+Lcom/google/android/mms/pdu/PduPart;->setContentId([B)V
+Lcom/google/android/mms/pdu/PduPart;->setContentLocation([B)V
+Lcom/google/android/mms/pdu/PduPart;->setContentType([B)V
+Lcom/google/android/mms/pdu/PduPart;->setData([B)V
+Lcom/google/android/mms/pdu/PduPart;->setDataUri(Landroid/net/Uri;)V
+Lcom/google/android/mms/pdu/PduPersister;->getBytes(Ljava/lang/String;)[B
+Lcom/google/android/mms/pdu/PduPersister;->getPduPersister(Landroid/content/Context;)Lcom/google/android/mms/pdu/PduPersister;
+Lcom/google/android/mms/pdu/PduPersister;->getPendingMessages(J)Landroid/database/Cursor;
+Lcom/google/android/mms/pdu/PduPersister;->load(Landroid/net/Uri;)Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduPersister;->move(Landroid/net/Uri;Landroid/net/Uri;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->persist(Lcom/google/android/mms/pdu/GenericPdu;Landroid/net/Uri;ZZLjava/util/HashMap;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->persistPart(Lcom/google/android/mms/pdu/PduPart;JLjava/util/HashMap;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->toIsoString([B)Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduPersister;->updateHeaders(Landroid/net/Uri;Lcom/google/android/mms/pdu/SendReq;)V
+Lcom/google/android/mms/pdu/PduPersister;->updateParts(Landroid/net/Uri;Lcom/google/android/mms/pdu/PduBody;Ljava/util/HashMap;)V
+Lcom/google/android/mms/pdu/ReadOrigInd;->getMessageId()[B
+Lcom/google/android/mms/pdu/ReadRecInd;-><init>(Lcom/google/android/mms/pdu/EncodedStringValue;[BII[Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/ReadRecInd;->setDate(J)V
+Lcom/google/android/mms/pdu/RetrieveConf;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/RetrieveConf;->getMessageId()[B
+Lcom/google/android/mms/pdu/RetrieveConf;->getTransactionId()[B
+Lcom/google/android/mms/pdu/SendConf;->getMessageId()[B
+Lcom/google/android/mms/pdu/SendConf;->getResponseStatus()I
+Lcom/google/android/mms/pdu/SendConf;->getTransactionId()[B
+Lcom/google/android/mms/pdu/SendReq;-><init>()V
+Lcom/google/android/mms/pdu/SendReq;->getBcc()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/SendReq;->getTransactionId()[B
+Lcom/google/android/mms/pdu/SendReq;->setDeliveryReport(I)V
+Lcom/google/android/mms/pdu/SendReq;->setExpiry(J)V
+Lcom/google/android/mms/pdu/SendReq;->setMessageClass([B)V
+Lcom/google/android/mms/pdu/SendReq;->setMessageSize(J)V
+Lcom/google/android/mms/pdu/SendReq;->setReadReport(I)V
+Lcom/google/android/mms/pdu/SendReq;->setTo([Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/util/AbstractCache;->get(Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/google/android/mms/util/PduCache;->getInstance()Lcom/google/android/mms/util/PduCache;
+Lcom/google/android/mms/util/PduCache;->isUpdating(Landroid/net/Uri;)Z
+Lcom/google/android/mms/util/PduCache;->purge(Landroid/net/Uri;)Lcom/google/android/mms/util/PduCacheEntry;
+Lcom/google/android/mms/util/PduCache;->purgeAll()V
+Lcom/google/android/mms/util/PduCacheEntry;->getPdu()Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/util/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
 Ldalvik/system/BaseDexClassLoader;-><init>(Ljava/lang/String;Ljava/io/File;Ljava/lang/String;Ljava/lang/ClassLoader;Z)V
 Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;)V
 Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;Z)V
@@ -2553,6 +2656,7 @@
 Ljava/net/SocketException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
 Ljava/net/SocketImpl;->serverSocket:Ljava/net/ServerSocket;
 Ljava/net/SocketImpl;->socket:Ljava/net/Socket;
+Ljava/net/SocksSocketImpl;-><init>()V
 Ljava/net/URI;->fragment:Ljava/lang/String;
 Ljava/net/URI;->host:Ljava/lang/String;
 Ljava/net/URI;->port:I
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 50e97c5..63c583f 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -1436,6 +1436,12 @@
 android.hardware.usb.UsbDeviceConnection
 android.hardware.usb.UsbManager
 android.hardware.usb.UsbRequest
+android.hidl.base.V1_0.DebugInfo
+android.hidl.base.V1_0.IBase
+android.hidl.manager.V1_0.IServiceManager
+android.hidl.manager.V1_0.IServiceManager$Proxy
+android.hidl.manager.V1_0.IServiceNotification
+android.hidl.manager.V1_0.IServiceNotification$Stub
 android.icu.impl.BMPSet
 android.icu.impl.CacheBase
 android.icu.impl.CacheValue
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 5499d59..2ee266d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -545,12 +545,12 @@
  * <a name="SavingPersistentState"></a>
  * <h3>Saving Persistent State</h3>
  *
- * <p>There are generally two kinds of persistent state than an activity
+ * <p>There are generally two kinds of persistent state that an activity
  * will deal with: shared document-like data (typically stored in a SQLite
  * database using a {@linkplain android.content.ContentProvider content provider})
  * and internal state such as user preferences.</p>
  *
- * <p>For content provider data, we suggest that activities use a
+ * <p>For content provider data, we suggest that activities use an
  * "edit in place" user model.  That is, any edits a user makes are effectively
  * made immediately without requiring an additional confirmation step.
  * Supporting this model is generally a simple matter of following two rules:</p>
@@ -1383,6 +1383,7 @@
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this);
         getApplication().dispatchActivityResumed(this);
         mActivityTransitionState.onResume(this, isTopOfTask());
+        enableAutofillCompatibilityIfNeeded();
         if (mAutoFillResetNeeded) {
             if (!mAutoFillIgnoreFirstResumePause) {
                 View focus = getCurrentFocus();
@@ -7165,7 +7166,6 @@
         mWindow.setColorMode(info.colorMode);
 
         setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
-        enableAutofillCompatibilityIfNeeded();
     }
 
     private void enableAutofillCompatibilityIfNeeded() {
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 0dd6186..0469a90 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -125,7 +125,7 @@
  *
  * <p><strong>Data Authority</strong> matches if any of the given values match
  * the Intent's data authority <em>and</em> one of the data schemes in the filter
- * has matched the Intent, <em>or</em> no authories were supplied in the filter.
+ * has matched the Intent, <em>or</em> no authorities were supplied in the filter.
  * The Intent authority is determined by calling
  * {@link Intent#getData} and {@link android.net.Uri#getAuthority} on that URI.
  * <em>Note that authority matching here is <b>case sensitive</b>, unlike
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 0c70a3d..963f881 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -22,7 +22,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -104,7 +103,7 @@
     private static volatile boolean sForceSafeLabels = false;
 
     /** {@hide} */
-    @UnsupportedAppUsage
+    @SystemApi
     public static void setForceSafeLabels(boolean forceSafeLabels) {
         sForceSafeLabels = forceSafeLabels;
     }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1b4878c..a15711f5 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1979,6 +1979,8 @@
      * </ul>
      * A version of 1.1.0 or higher also indicates:
      * <ul>
+     * <li>The {@code VK_ANDROID_external_memory_android_hardware_buffer} extension is
+     *     supported.</li>
      * <li>{@code SYNC_FD} external semaphore and fence handles are supported.</li>
      * <li>{@code VkPhysicalDeviceSamplerYcbcrConversionFeatures::samplerYcbcrConversion} is
      *     supported.</li>
diff --git a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
index e0bffae..f2da21e 100644
--- a/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
+++ b/core/java/android/permissionpresenterservice/RuntimePermissionPresenterService.java
@@ -17,7 +17,6 @@
 package android.permissionpresenterservice;
 
 import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
@@ -78,10 +77,7 @@
      *
      * @param packageName The package for which to revoke
      * @param permissionName The permission to revoke
-     *
-     * @hide
      */
-    @UnsupportedAppUsage
     public abstract void onRevokeRuntimePermission(String packageName, String permissionName);
 
     @Override
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4c7f0f3..aa178fb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11537,14 +11537,6 @@
         public static final String EMERGENCY_AFFORDANCE_NEEDED = "emergency_affordance_needed";
 
         /**
-         * Enable faster emergency phone call feature.
-         * The value is a boolean (1 or 0).
-         * @hide
-         */
-        public static final String FASTER_EMERGENCY_PHONE_CALL_ENABLED =
-                "faster_emergency_phone_call_enabled";
-
-        /**
          * See RIL_PreferredNetworkType in ril.h
          * @hide
          */
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index ff6e86e..183e833 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -35,6 +35,7 @@
     public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override.";
     public static final String PERSIST_PREFIX = "persist." + FFLAG_OVERRIDE_PREFIX;
     public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
+    public static final String EMERGENCY_DIAL_SHORTCUTS = "settings_emergency_dial_shortcuts";
 
     private static final Map<String, String> DEFAULT_FLAGS;
     static {
@@ -47,6 +48,7 @@
         DEFAULT_FLAGS.put("settings_data_usage_v2", "false");
         DEFAULT_FLAGS.put("settings_seamless_transfer", "false");
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "true");
+        DEFAULT_FLAGS.put(EMERGENCY_DIAL_SHORTCUTS, "false");
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index a3fa2ce..4d3f0fc 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -632,6 +632,8 @@
 
     private static final int BOOLEAN_PROPERTY_IS_HEADING = 0x0200000;
 
+    private static final int BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY = 0x0400000;
+
     /**
      * Bits that provide the id of a virtual descendant of a view.
      */
@@ -2461,6 +2463,30 @@
     }
 
     /**
+     * Returns whether node represents a text entry key that is part of a keyboard or keypad.
+     *
+     * @return {@code true} if the node is a text entry key., {@code false} otherwise.
+     */
+    public boolean isTextEntryKey() {
+        return getBooleanProperty(BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY);
+    }
+
+    /**
+     * Sets whether the node represents a text entry key that is part of a keyboard or keypad.
+     *
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param isTextEntryKey {@code true} if the node is a text entry key, {@code false} otherwise.
+     */
+    public void setTextEntryKey(boolean isTextEntryKey) {
+        setBooleanProperty(BOOLEAN_PROPERTY_IS_TEXT_ENTRY_KEY, isTextEntryKey);
+    }
+
+    /**
      * Gets the package this node comes from.
      *
      * @return The package name.
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 9419e93..e87048e 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -45,6 +45,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Choreographer;
 import android.view.KeyEvent;
@@ -559,6 +560,9 @@
             // different bridge based on which activity is currently focused
             // in the current process. Since compat would be rarely used, just
             // create and register a new instance every time.
+            if (sDebug) {
+                Slog.d(TAG, "creating CompatibilityBridge for " + mContext);
+            }
             mCompatibilityBridge = new CompatibilityBridge();
         }
     }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index d0795c9..31f13c3 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -5758,8 +5758,6 @@
         for (int i = 0; i < N; i++) {
             int uid = mapUid(ws.get(i));
             getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
-            StatsLog.write_non_chained(StatsLog.BLE_SCAN_RESULT_RECEIVED, ws.get(i), ws.getName(i),
-                    numNewResults);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -5768,8 +5766,6 @@
                 final WorkChain wc = workChains.get(i);
                 int uid = mapUid(wc.getAttributionUid());
                 getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
-                StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED,
-                        wc.getUids(), wc.getTags(), numNewResults);
             }
         }
     }
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
index 02a8b22..0650d0af 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -106,6 +106,7 @@
         synchronized (entry) {
             entry.exceptionCount++;
         }
+
         recycleSession(session);
     }
 
@@ -116,29 +117,29 @@
 
     /** Returns an array of {@link ExportedEntry entries} with the aggregated statistics. */
     public List<ExportedEntry> getEntries() {
-        final ArrayList<ExportedEntry> entries;
+        final ArrayList<ExportedEntry> exportedEntries;
         synchronized (mLock) {
             final int size = mEntries.size();
-            entries = new ArrayList<>(size);
+            exportedEntries = new ArrayList<>(size);
             for (int i = 0; i < size; i++) {
                 Entry entry = mEntries.valueAt(i);
                 synchronized (entry) {
-                    entries.add(new ExportedEntry(entry));
+                    exportedEntries.add(new ExportedEntry(entry));
                 }
             }
         }
         // Add the overflow and collision entries only if they have any data.
-        if (mOverflowEntry.messageCount > 0 || mOverflowEntry.exceptionCount > 0) {
-            synchronized (mOverflowEntry) {
-                entries.add(new ExportedEntry(mOverflowEntry));
+        maybeAddSpecialEntry(exportedEntries, mOverflowEntry);
+        maybeAddSpecialEntry(exportedEntries, mHashCollisionEntry);
+        return exportedEntries;
+    }
+
+    private void maybeAddSpecialEntry(List<ExportedEntry> exportedEntries, Entry specialEntry) {
+        synchronized (specialEntry) {
+            if (specialEntry.messageCount > 0 || specialEntry.exceptionCount > 0) {
+                exportedEntries.add(new ExportedEntry(specialEntry));
             }
         }
-        if (mHashCollisionEntry.messageCount > 0 || mHashCollisionEntry.exceptionCount > 0) {
-            synchronized (mHashCollisionEntry) {
-                entries.add(new ExportedEntry(mHashCollisionEntry));
-            }
-        }
-        return entries;
     }
 
     /** Removes all collected data. */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 814973d..1df3f7f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3054,6 +3054,18 @@
     <permission android:name="android.permission.MANAGE_DEVICE_ADMINS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows an app to reset the device password.
+         <p>Not for use by third-party applications.
+         @hide -->
+    <permission android:name="android.permission.RESET_PASSWORD"
+        android:protectionLevel="signature|privileged" />
+
+    <!-- @SystemApi Allows an app to lock the device.
+         <p>Not for use by third-party applications.
+         @hide -->
+    <permission android:name="android.permission.LOCK_DEVICE"
+        android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows low-level access to setting the orientation (actually
          rotation) of the screen.
          <p>Not for use by third-party applications.
diff --git a/packages/SettingsLib/res/drawable/ic_info.xml b/core/res/res/drawable/ic_info.xml
similarity index 94%
rename from packages/SettingsLib/res/drawable/ic_info.xml
rename to core/res/res/drawable/ic_info.xml
index afe7e6b..f14c4b4 100644
--- a/packages/SettingsLib/res/drawable/ic_info.xml
+++ b/core/res/res/drawable/ic_info.xml
@@ -18,7 +18,7 @@
         android:height="24dp"
         android:viewportWidth="24"
         android:viewportHeight="24"
-        android:tint="?android:attr/colorAccent">
+        android:tint="?attr/colorControlNormal">
     <path
         android:fillColor="@android:color/white"
         android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
diff --git a/core/res/res/values-mcc302-mnc370/strings.xml b/core/res/res/values-mcc302-mnc370/strings.xml
deleted file mode 100644
index f5b8496..0000000
--- a/core/res/res/values-mcc302-mnc370/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Template for showing mobile network operator name while WFC is active -->
-    <string-array name="wfcSpnFormats">
-        <item>%s</item>
-        <item>%s Wi-Fi</item>
-    </string-array>
-</resources>
diff --git a/core/res/res/values-mcc302-mnc720/strings.xml b/core/res/res/values-mcc302-mnc720/strings.xml
deleted file mode 100644
index f5b8496..0000000
--- a/core/res/res/values-mcc302-mnc720/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Template for showing mobile network operator name while WFC is active -->
-    <string-array name="wfcSpnFormats">
-        <item>%s</item>
-        <item>%s Wi-Fi</item>
-    </string-array>
-</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 293d90e..1404383 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -913,7 +913,7 @@
     <!--  Control whether to lock day/night mode change from normal application. When it is
           true, day / night mode change is only allowed to apps with MODIFY_DAY_NIGHT_MODE
           permission. -->
-    <bool name="config_lockDayNightMode">true</bool>
+    <bool name="config_lockDayNightMode">false</bool>
 
     <!-- Control the default night mode to use when there is no other mode override set.
          One of the following values (see UiModeManager.java):
@@ -3486,6 +3486,9 @@
     <!-- Name of the font family used for system surfaces where the font should use medium weight -->
     <string name="config_headlineFontFamilyMedium">@string/font_family_button_material</string>
 
+    <!-- Size of icon shown beside a preference locked by admin -->
+    <dimen name="config_restricted_icon_size">@dimen/restricted_icon_size_material</dimen>
+
     <string translatable="false" name="config_batterySaverDeviceSpecificConfig"></string>
 
     <!-- Package name that should be granted Notification Assistant access -->
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 210f30e..a0b40ed 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -117,6 +117,9 @@
     <!-- Default rounded corner for controls -->
     <dimen name="control_corner_material">2dp</dimen>
 
+    <!-- Size of icon shown beside a preference locked by admin -->
+    <dimen name="restricted_icon_size_material">16dp</dimen>
+
     <dimen name="edit_text_inset_horizontal_material">4dp</dimen>
     <dimen name="edit_text_inset_top_material">10dp</dimen>
     <dimen name="edit_text_inset_bottom_material">7dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c751af3..cc99a4e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2909,14 +2909,16 @@
         <public name="opticalInsetBottom" />
         <public name="allowForceDark" />
         <public name="supportsAmbientMode" />
-    </public-group>
-
-    <public-group type="attr" first-id="0x0101058d">
         <!-- @hide For use by platform and tools only. Developers should not specify this value. -->
         <public name="usesNonSdkApi" />
         <public name="minimumUiTimeout" />
     </public-group>
 
+    <public-group type="drawable" first-id="0x010800b4">
+        <!-- @hide @SystemApi -->
+        <public name="ic_info" />
+    </public-group>
+
     <public-group type="style" first-id="0x010302e2">
     </public-group>
 
@@ -2943,6 +2945,11 @@
         <public name="config_sendPackageName" />
     </public-group>
 
+    <public-group type="dimen" first-id="0x01050007">
+        <!-- @hide @SystemApi -->
+        <public name="config_restricted_icon_size" />
+    </public-group>
+
   <!-- ===============================================================
        DO NOT ADD UN-GROUPED ITEMS HERE
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1a5b7b6..64620f3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -240,10 +240,31 @@
         <item>Issue registering Wi\u2011Fi calling with your carrier: <xliff:g id="code" example="REG09 - No 911 Address">%1$s</xliff:g></item>
     </string-array>
     <!-- Template for showing mobile network operator name while WFC is active -->
-    <string-array name="wfcSpnFormats">
-        <item>%s</item>
-        <item>%s Wi-Fi Calling</item>
+    <string-array name="wfcSpnFormats" translatable="false">
+        <item>@string/wfcSpnFormat_spn</item>
+        <item>@string/wfcSpnFormat_spn_wifi_calling</item>
+        <item>@string/wfcSpnFormat_wlan_call</item>
+        <item>@string/wfcSpnFormat_spn_wlan_call</item>
+        <item>@string/wfcSpnFormat_spn_wifi</item>
+        <item>@string/wfcSpnFormat_wifi_calling_bar_spn</item>
+        <item>@string/wfcSpnFormat_spn_vowifi</item>
     </string-array>
+
+    <!-- Spn during Wi-Fi Calling: "<operator>" -->
+    <string name="wfcSpnFormat_spn"><xliff:g id="spn" example="Operator">%s</xliff:g></string>
+    <!-- Spn during Wi-Fi Calling: "<operator> Wi-Fi Calling" -->
+    <string name="wfcSpnFormat_spn_wifi_calling"><xliff:g id="spn" example="Operator">%s</xliff:g> Wi-Fi Calling</string>
+    <!-- Spn during Wi-Fi Calling: "WLAN Call" -->
+    <string name="wfcSpnFormat_wlan_call">WLAN Call</string>
+    <!-- Spn during Wi-Fi Calling: "<operator> WLAN Call" -->
+    <string name="wfcSpnFormat_spn_wlan_call"><xliff:g id="spn" example="Operator">%s</xliff:g> WLAN Call</string>
+    <!-- Spn during Wi-Fi Calling: "<operator> Wi-Fi" -->
+    <string name="wfcSpnFormat_spn_wifi"><xliff:g id="spn" example="Operator">%s</xliff:g> Wi-Fi</string>
+    <!-- Spn during Wi-Fi Calling: "WiFi Calling | <operator>" -->
+    <string name="wfcSpnFormat_wifi_calling_bar_spn">WiFi Calling | <xliff:g id="spn" example="Operator">%s</xliff:g></string>
+    <!-- Spn during Wi-Fi Calling: "<operator> VoWifi" -->
+    <string name="wfcSpnFormat_spn_vowifi"><xliff:g id="spn" example="Operator">%s</xliff:g> VoWifi</string>
+
     <!-- WFC, summary for Disabled -->
     <string name="wifi_calling_off_summary">Off</string>
     <!-- WFC, summary for Wi-Fi Preferred -->
diff --git a/core/tests/coretests/src/android/graphics/PaintTest.java b/core/tests/coretests/src/android/graphics/PaintTest.java
index 2f28606..b5ed01f 100644
--- a/core/tests/coretests/src/android/graphics/PaintTest.java
+++ b/core/tests/coretests/src/android/graphics/PaintTest.java
@@ -186,44 +186,28 @@
         Paint p = new Paint();
 
         final int count = end - start;
-        final float[][] advanceArrays = new float[4][count];
-
-        final float advance = p.getTextRunAdvances(str, start, end, contextStart, contextEnd,
-                isRtl, advanceArrays[0], 0);
-
+        final int contextCount = contextEnd - contextStart;
+        final float[][] advanceArrays = new float[2][count];
         char chars[] = str.toCharArray();
-        final float advance_c = p.getTextRunAdvances(chars, start, count, contextStart,
-                contextEnd - contextStart, isRtl, advanceArrays[1], 0);
-        assertEquals(advance, advance_c, 1.0f);
-
+        final float advance = p.getTextRunAdvances(chars, start, count,
+                contextStart, contextCount, isRtl, advanceArrays[0], 0);
         for (int c = 1; c < count; ++c) {
-            final float firstPartAdvance = p.getTextRunAdvances(str, start, start + c,
-                    contextStart, contextEnd, isRtl, advanceArrays[2], 0);
-            final float secondPartAdvance = p.getTextRunAdvances(str, start + c, end,
-                    contextStart, contextEnd, isRtl, advanceArrays[2], c);
+            final float firstPartAdvance = p.getTextRunAdvances(chars, start, c,
+                    contextStart, contextCount, isRtl, advanceArrays[1], 0);
+            final float secondPartAdvance = p.getTextRunAdvances(chars, start + c, count - c,
+                    contextStart, contextCount, isRtl, advanceArrays[1], c);
             assertEquals(advance, firstPartAdvance + secondPartAdvance, 1.0f);
 
-
-            final float firstPartAdvance_c = p.getTextRunAdvances(chars, start, c,
-                    contextStart, contextEnd - contextStart, isRtl, advanceArrays[3], 0);
-            final float secondPartAdvance_c = p.getTextRunAdvances(chars, start + c,
-                    count - c, contextStart, contextEnd - contextStart, isRtl,
-                    advanceArrays[3], c);
-            assertEquals(advance, firstPartAdvance_c + secondPartAdvance_c, 1.0f);
-            assertEquals(firstPartAdvance, firstPartAdvance_c, 1.0f);
-            assertEquals(secondPartAdvance, secondPartAdvance_c, 1.0f);
-
-            for (int i = 1; i < advanceArrays.length; i++) {
-                for (int j = 0; j < count; j++) {
-                    assertEquals(advanceArrays[0][j], advanceArrays[i][j], 1.0f);
-                }
+            for (int j = 0; j < count; j++) {
+                assertEquals(advanceArrays[0][j], advanceArrays[1][j], 1.0f);
             }
 
+
             // Compare results with measureText, getRunAdvance, and getTextWidths.
             if (compareWithOtherMethods && start == contextStart && end == contextEnd) {
                 assertEquals(advance, p.measureText(str, start, end), 1.0f);
                 assertEquals(advance, p.getRunAdvance(
-                        str, start, end, contextStart, contextEnd, isRtl, end), 1.0f);
+                        chars, start, count, contextStart, contextCount, isRtl, end), 1.0f);
 
                 final float[] widths = new float[count];
                 p.getTextWidths(str, start, end, widths);
@@ -236,19 +220,7 @@
 
     public void testGetTextRunAdvances_invalid() {
         Paint p = new Paint();
-        String text = "test";
-
-        try {
-            p.getTextRunAdvances((String)null, 0, 0, 0, 0, false, null, 0);
-            fail("Should throw an IllegalArgumentException.");
-        } catch (IllegalArgumentException e) {
-        }
-
-        try {
-            p.getTextRunAdvances((CharSequence)null, 0, 0, 0, 0, false, null, 0);
-            fail("Should throw an IllegalArgumentException.");
-        } catch (IllegalArgumentException e) {
-        }
+        char[] text = "test".toCharArray();
 
         try {
             p.getTextRunAdvances((char[])null, 0, 0, 0, 0, false, null, 0);
@@ -257,50 +229,43 @@
         }
 
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length(), false,
-                    new float[text.length() - 1], 0);
+            p.getTextRunAdvances(text, 0, text.length, 0, text.length, false,
+                    new float[text.length - 1], 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length(), false,
-                    new float[text.length()], 1);
+            p.getTextRunAdvances(text, 0, text.length, 0, text.length, false,
+                    new float[text.length], 1);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         // 0 > contextStart
         try {
-            p.getTextRunAdvances(text, 0, text.length(), -1, text.length(), false, null, 0);
+            p.getTextRunAdvances(text, 0, text.length, -1, text.length, false, null, 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         // contextStart > start
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 1, text.length(), false, null, 0);
-            fail("Should throw an IndexOutOfBoundsException.");
-        } catch (IndexOutOfBoundsException e) {
-        }
-
-        // start > end
-        try {
-            p.getTextRunAdvances(text, 1, 0, 0, text.length(), false, null, 0);
+            p.getTextRunAdvances(text, 0, text.length, 1, text.length, false, null, 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         // end > contextEnd
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length() - 1, false, null, 0);
+            p.getTextRunAdvances(text, 0, text.length, 0, text.length - 1, false, null, 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
 
         // contextEnd > text.length
         try {
-            p.getTextRunAdvances(text, 0, text.length(), 0, text.length() + 1, false, null, 0);
+            p.getTextRunAdvances(text, 0, text.length, 0, text.length + 1, false, null, 0);
             fail("Should throw an IndexOutOfBoundsException.");
         } catch (IndexOutOfBoundsException e) {
         }
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index e84aed1..fee470d 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -241,7 +241,6 @@
                     Settings.Global.EUICC_SUPPORTED_COUNTRIES,
                     Settings.Global.EUICC_FACTORY_RESET_TIMEOUT_MILLIS,
                     Settings.Global.FANCY_IME_ANIMATIONS,
-                    Settings.Global.FASTER_EMERGENCY_PHONE_CALL_ENABLED,
                     Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
                     Settings.Global.FORCED_APP_STANDBY_ENABLED,
                     Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 922b79a..69d2828 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -57,7 +57,7 @@
 
     // The number of flags held in boolean properties. Their values should also be double-checked
     // in the methods above.
-    private static final int NUM_BOOLEAN_PROPERTIES = 17;
+    private static final int NUM_BOOLEAN_PROPERTIES = 18;
 
     @Test
     public void testStandardActions_serializationFlagIsValid() {
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index 0eb3d06..565a3ec 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -342,6 +342,20 @@
         assertThat(looperStats.getEntries().get(0).messageCount).isEqualTo(2);
     }
 
+    @Test
+    public void testReset() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 1);
+
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.messageDispatched(token2, mHandlerFirst.obtainMessage(2000));
+        looperStats.reset();
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(0);
+    }
+
     private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
         try {
             r.run();
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index c4017d15..73c10d2 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -210,6 +210,11 @@
     <allow-in-power-save-except-idle package="com.android.providers.calendar" />
     <allow-in-power-save-except-idle package="com.android.providers.contacts" />
 
+    <!-- The PAC proxy process must have network access, otherwise no app will
+         be able to connect to the internet when such a proxy is in use, since
+         all outgoing connections originate from this app. -->
+    <allow-in-power-save-except-idle package="com.android.proxyhandler" />
+
     <!-- These are the packages that are white-listed to be able to run as system user -->
     <system-user-whitelisted-app package="com.android.settings" />
 
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 6f30653..85b39fe 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -17,7 +17,9 @@
 package android.graphics;
 
 import android.annotation.ColorInt;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.Px;
 import android.annotation.Size;
 import android.annotation.UnsupportedAppUsage;
@@ -2325,17 +2327,53 @@
     }
 
     /**
-     * Convenience overload that takes a char array instead of a
-     * String.
+     * Retrieve the character advances of the text.
      *
-     * @see #getTextRunAdvances(String, int, int, int, int, boolean, float[], int)
-     * @hide
+     * Returns the total advance width for the characters in the run from {@code index} for
+     * {@code count} of chars, and if {@code advances} is not null, the advance assigned to each of
+     * these characters (java chars).
+     *
+     * <p>
+     * The trailing surrogate in a valid surrogate pair is assigned an advance of 0.  Thus the
+     * number of returned advances is always equal to count, not to the number of unicode codepoints
+     * represented by the run.
+     * </p>
+     *
+     * <p>
+     * In the case of conjuncts or combining marks, the total advance is assigned to the first
+     * logical character, and the following characters are assigned an advance of 0.
+     * </p>
+     *
+     * <p>
+     * This generates the sum of the advances of glyphs for characters in a reordered cluster as the
+     * width of the first logical character in the cluster, and 0 for the widths of all other
+     * characters in the cluster.  In effect, such clusters are treated like conjuncts.
+     * </p>
+     *
+     * <p>
+     * The shaping bounds limit the amount of context available outside start and end that can be
+     * used for shaping analysis.  These bounds typically reflect changes in bidi level or font
+     * metrics across which shaping does not occur.
+     * </p>
+     *
+     * @param chars the text to measure.
+     * @param index the index of the first character to measure
+     * @param count the number of characters to measure
+     * @param contextIndex the index of the first character to use for shaping context.
+     *                     Context must cover the measureing target.
+     * @param contextCount the number of character to use for shaping context.
+     *                     Context must cover the measureing target.
+     * @param isRtl whether the run is in RTL direction
+     * @param advances array to receive the advances, must have room for all advances.
+     *                 This can be null if only total advance is needed
+     * @param advancesIndex the position in advances at which to put the advance corresponding to
+     *                      the character at start
+     * @return the total advance in pixels
      */
-    @UnsupportedAppUsage
-    public float getTextRunAdvances(char[] chars, int index, int count,
-            int contextIndex, int contextCount, boolean isRtl, float[] advances,
-            int advancesIndex) {
-
+    public float getTextRunAdvances(@NonNull char[] chars, @IntRange(from = 0) int index,
+            @IntRange(from = 0) int count, @IntRange(from = 0) int contextIndex,
+            @IntRange(from = 0) int contextCount, boolean isRtl, @Nullable float[] advances,
+            @IntRange(from = 0) int advancesIndex) {
         if (chars == null) {
             throw new IllegalArgumentException("text cannot be null");
         }
@@ -2372,131 +2410,6 @@
     }
 
     /**
-     * Convenience overload that takes a CharSequence instead of a
-     * String.
-     *
-     * @see #getTextRunAdvances(String, int, int, int, int, boolean, float[], int)
-     * @hide
-     */
-    public float getTextRunAdvances(CharSequence text, int start, int end,
-            int contextStart, int contextEnd, boolean isRtl, float[] advances,
-            int advancesIndex) {
-        if (text == null) {
-            throw new IllegalArgumentException("text cannot be null");
-        }
-        if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
-                | (start - contextStart) | (contextEnd - end)
-                | (text.length() - contextEnd)
-                | (advances == null ? 0 :
-                    (advances.length - advancesIndex - (end - start)))) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        if (text instanceof String) {
-            return getTextRunAdvances((String) text, start, end,
-                    contextStart, contextEnd, isRtl, advances, advancesIndex);
-        }
-        if (text instanceof SpannedString ||
-            text instanceof SpannableString) {
-            return getTextRunAdvances(text.toString(), start, end,
-                    contextStart, contextEnd, isRtl, advances, advancesIndex);
-        }
-        if (text instanceof GraphicsOperations) {
-            return ((GraphicsOperations) text).getTextRunAdvances(start, end,
-                    contextStart, contextEnd, isRtl, advances, advancesIndex, this);
-        }
-        if (text.length() == 0 || end == start) {
-            return 0f;
-        }
-
-        int contextLen = contextEnd - contextStart;
-        int len = end - start;
-        char[] buf = TemporaryBuffer.obtain(contextLen);
-        TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
-        float result = getTextRunAdvances(buf, start - contextStart, len,
-                0, contextLen, isRtl, advances, advancesIndex);
-        TemporaryBuffer.recycle(buf);
-        return result;
-    }
-
-    /**
-     * Returns the total advance width for the characters in the run
-     * between start and end, and if advances is not null, the advance
-     * assigned to each of these characters (java chars).
-     *
-     * <p>The trailing surrogate in a valid surrogate pair is assigned
-     * an advance of 0.  Thus the number of returned advances is
-     * always equal to count, not to the number of unicode codepoints
-     * represented by the run.
-     *
-     * <p>In the case of conjuncts or combining marks, the total
-     * advance is assigned to the first logical character, and the
-     * following characters are assigned an advance of 0.
-     *
-     * <p>This generates the sum of the advances of glyphs for
-     * characters in a reordered cluster as the width of the first
-     * logical character in the cluster, and 0 for the widths of all
-     * other characters in the cluster.  In effect, such clusters are
-     * treated like conjuncts.
-     *
-     * <p>The shaping bounds limit the amount of context available
-     * outside start and end that can be used for shaping analysis.
-     * These bounds typically reflect changes in bidi level or font
-     * metrics across which shaping does not occur.
-     *
-     * @param text the text to measure. Cannot be null.
-     * @param start the index of the first character to measure
-     * @param end the index past the last character to measure
-     * @param contextStart the index of the first character to use for shaping context,
-     * must be <= start
-     * @param contextEnd the index past the last character to use for shaping context,
-     * must be >= end
-     * @param isRtl whether the run is in RTL direction
-     * @param advances array to receive the advances, must have room for all advances,
-     * can be null if only total advance is needed
-     * @param advancesIndex the position in advances at which to put the
-     * advance corresponding to the character at start
-     * @return the total advance
-     *
-     * @hide
-     */
-    public float getTextRunAdvances(String text, int start, int end, int contextStart,
-            int contextEnd, boolean isRtl, float[] advances, int advancesIndex) {
-        if (text == null) {
-            throw new IllegalArgumentException("text cannot be null");
-        }
-        if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
-                | (start - contextStart) | (contextEnd - end)
-                | (text.length() - contextEnd)
-                | (advances == null ? 0 :
-                    (advances.length - advancesIndex - (end - start)))) < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        if (text.length() == 0 || start == end) {
-            return 0f;
-        }
-
-        if (!mHasCompatScaling) {
-            return nGetTextAdvances(mNativePaint, text, start, end, contextStart, contextEnd,
-                    isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances, advancesIndex);
-        }
-
-        final float oldSize = getTextSize();
-        setTextSize(oldSize * mCompatScaling);
-        final float totalAdvance = nGetTextAdvances(mNativePaint, text, start, end, contextStart,
-                contextEnd, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances, advancesIndex);
-        setTextSize(oldSize);
-
-        if (advances != null) {
-            for (int i = advancesIndex, e = i + (end - start); i < e; i++) {
-                advances[i] *= mInvCompatScaling;
-            }
-        }
-        return totalAdvance * mInvCompatScaling; // assume errors are insignificant
-    }
-
-    /**
      * Returns the next cursor position in the run.  This avoids placing the
      * cursor between surrogates, between characters that form conjuncts,
      * between base characters and combining marks, or within a reordering
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index b5b87d5..21fbbdc 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -26,8 +26,6 @@
 
 #include <log/log.h>
 
-#include <GLES2/gl2.h>
-
 namespace android {
 namespace uirenderer {
 
@@ -46,39 +44,12 @@
         1920,   // viewportH
 };
 
-static DeviceInfo* sDeviceInfo = nullptr;
-static std::once_flag sInitializedFlag;
-
 const DeviceInfo* DeviceInfo::get() {
-    LOG_ALWAYS_FATAL_IF(!sDeviceInfo, "DeviceInfo not yet initialized.");
-    return sDeviceInfo;
+        static DeviceInfo sDeviceInfo;
+        return &sDeviceInfo;
 }
 
-void DeviceInfo::initialize() {
-    std::call_once(sInitializedFlag, []() {
-        sDeviceInfo = new DeviceInfo();
-        sDeviceInfo->load();
-    });
-}
-
-void DeviceInfo::initialize(int maxTextureSize) {
-    std::call_once(sInitializedFlag, [maxTextureSize]() {
-        sDeviceInfo = new DeviceInfo();
-        sDeviceInfo->mDisplayInfo = DeviceInfo::queryDisplayInfo();
-        sDeviceInfo->mMaxTextureSize = maxTextureSize;
-        sDeviceInfo->queryCompositionPreference(&sDeviceInfo->mTargetDataSpace,
-                                                &sDeviceInfo->mTargetPixelFormat);
-    });
-}
-
-void DeviceInfo::load() {
-    mDisplayInfo = queryDisplayInfo();
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
-    sDeviceInfo->queryCompositionPreference(&sDeviceInfo->mTargetDataSpace,
-                                            &sDeviceInfo->mTargetPixelFormat);
-}
-
-DisplayInfo DeviceInfo::queryDisplayInfo() {
+DisplayInfo QueryDisplayInfo() {
     if (Properties::isolatedProcess) {
         return sDummyDisplay;
     }
@@ -90,17 +61,36 @@
     return displayInfo;
 }
 
-void DeviceInfo::queryCompositionPreference(ui::Dataspace* dataSpace,
-                                            ui::PixelFormat* pixelFormat) {
+void QueryCompositionPreference(ui::Dataspace* dataSpace,
+                                ui::PixelFormat* pixelFormat) {
     if (Properties::isolatedProcess) {
         *dataSpace = ui::Dataspace::V0_SRGB;
         *pixelFormat = ui::PixelFormat::RGBA_8888;
     }
 
     status_t status =
-        SurfaceComposerClient::getCompositionPreference(dataSpace, pixelFormat);
+            SurfaceComposerClient::getCompositionPreference(dataSpace, pixelFormat);
     LOG_ALWAYS_FATAL_IF(status, "Failed to get composition preference, error %d", status);
 }
 
+DeviceInfo::DeviceInfo() {
+#if HWUI_NULL_GPU
+        mMaxTextureSize = NULL_GPU_MAX_TEXTURE_SIZE;
+#else
+        mMaxTextureSize = -1;
+#endif
+    mDisplayInfo = QueryDisplayInfo();
+    QueryCompositionPreference(&mTargetDataSpace, &mTargetPixelFormat);
+}
+
+int DeviceInfo::maxTextureSize() const {
+    LOG_ALWAYS_FATAL_IF(mMaxTextureSize < 0, "MaxTextureSize has not been initialized yet.");
+    return mMaxTextureSize;
+}
+
+void DeviceInfo::setMaxTextureSize(int maxTextureSize) {
+    const_cast<DeviceInfo*>(DeviceInfo::get())->mMaxTextureSize = maxTextureSize;
+}
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index 416af17..1d747741 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -19,51 +19,38 @@
 #include <ui/DisplayInfo.h>
 #include <ui/GraphicTypes.h>
 
-#include "Extensions.h"
 #include "utils/Macros.h"
 
 namespace android {
 namespace uirenderer {
 
+namespace renderthread {
+    class RenderThread;
+}
+
 class DeviceInfo {
     PREVENT_COPY_AND_ASSIGN(DeviceInfo);
 
 public:
-    // returns nullptr if DeviceInfo is not initialized yet
-    // Note this does not have a memory fence so it's up to the caller
-    // to use one if required. Normally this should not be necessary
     static const DeviceInfo* get();
 
-    // only call this after GL has been initialized, or at any point if compiled
-    // with HWUI_NULL_GPU
-    static void initialize();
-    static void initialize(int maxTextureSize);
+    // this value is only valid after the GPU has been initialized and there is a valid graphics
+    // context or if you are using the HWUI_NULL_GPU
+    int maxTextureSize() const;
 
-    int maxTextureSize() const { return mMaxTextureSize; }
     ui::Dataspace getTargetDataSpace() const { return mTargetDataSpace; }
     ui::PixelFormat getTargetPixelFormat() const { return mTargetPixelFormat; }
     const DisplayInfo& displayInfo() const { return mDisplayInfo; }
-    const Extensions& extensions() const { return mExtensions; }
-
-    static uint32_t multiplyByResolution(uint32_t in) {
-        auto di = DeviceInfo::get()->displayInfo();
-        return di.w * di.h * in;
-    }
-
-    static DisplayInfo queryDisplayInfo();
 
 private:
-    static void queryCompositionPreference(ui::Dataspace* dataSpace,
-                                           ui::PixelFormat* pixelFormat);
+    friend class renderthread::RenderThread;
+    static void setMaxTextureSize(int maxTextureSize);
 
-    DeviceInfo() {}
-    ~DeviceInfo() {}
-
-    void load();
+    DeviceInfo();
 
     int mMaxTextureSize;
     DisplayInfo mDisplayInfo;
-    Extensions mExtensions;
+
     // TODO(lpy) Replace below with android_ prefix types.
     ui::Dataspace mTargetDataSpace;
     ui::PixelFormat mTargetPixelFormat;
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
deleted file mode 100644
index e90f40c1..0000000
--- a/libs/hwui/Extensions.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_HWUI_EXTENSIONS_H
-#define ANDROID_HWUI_EXTENSIONS_H
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Classes
-///////////////////////////////////////////////////////////////////////////////
-
-class Extensions {
-public:
-    Extensions() {}
-
-    inline bool hasNPot() const { return false; }
-    inline bool hasFramebufferFetch() const { return false; }
-    inline bool hasDiscardFramebuffer() const { return false; }
-    inline bool hasDebugMarker() const { return false; }
-    inline bool has1BitStencil() const { return false; }
-    inline bool has4BitStencil() const { return false; }
-    inline bool hasUnpackRowLength() const { return mVersionMajor >= 3; }
-    inline bool hasPixelBufferObjects() const { return mVersionMajor >= 3; }
-    inline bool hasOcclusionQueries() const { return mVersionMajor >= 3; }
-    inline bool hasFloatTextures() const { return mVersionMajor >= 3; }
-    inline bool hasRenderableFloatTextures() const {
-        return (mVersionMajor >= 3 && mVersionMinor >= 2);
-    }
-    inline bool hasSRGB() const { return false; }
-    inline bool hasSRGBWriteControl() const { return hasSRGB() && false; }
-    inline bool hasLinearBlending() const { return hasSRGB() && false; }
-
-    inline int getMajorGlVersion() const { return mVersionMajor; }
-    inline int getMinorGlVersion() const { return mVersionMinor; }
-
-private:
-    int mVersionMajor = 2;
-    int mVersionMinor = 0;
-};  // class Extensions
-
-};  // namespace uirenderer
-};  // namespace android
-
-#endif  // ANDROID_HWUI_EXTENSIONS_H
diff --git a/libs/hwui/debug/wrap_gles.h b/libs/hwui/debug/wrap_gles.h
index 27a29aa..3da6e80 100644
--- a/libs/hwui/debug/wrap_gles.h
+++ b/libs/hwui/debug/wrap_gles.h
@@ -28,6 +28,9 @@
 #include <GLES3/gl31.h>
 #include <GLES3/gl32.h>
 
+// constant used by the NULL GPU implementation as well as HWUI's unit tests
+constexpr int NULL_GPU_MAX_TEXTURE_SIZE = 2048;
+
 // Generate stubs that route all the calls to our function table
 #include "gles_redefine.h"
 
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 675df41..0cb23e5 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -23,7 +23,6 @@
 #include "utils/Color.h"
 #include "utils/StringUtils.h"
 
-#include "DeviceInfo.h"
 #include "Frame.h"
 #include "Properties.h"
 
@@ -127,7 +126,6 @@
     createContext();
     createPBufferSurface();
     makeCurrent(mPBufferSurface, nullptr, /* force */ true);
-    DeviceInfo::initialize();
 
     mSurfaceColorGamut = DataSpaceToColorGamut(
         static_cast<android_dataspace>(DeviceInfo::get()->getTargetDataSpace()));
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 7258a0a..a5dcc72 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -162,7 +162,7 @@
 }
 
 void RenderThread::initThreadLocals() {
-    mDisplayInfo = DeviceInfo::queryDisplayInfo();
+    mDisplayInfo = DeviceInfo::get()->displayInfo();
     nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
     mTimeLord.setFrameInterval(frameIntervalNanos);
     initializeDisplayEventReceiver();
@@ -246,6 +246,9 @@
         mGrContext->releaseResourcesAndAbandonContext();
     }
     mGrContext = std::move(context);
+    if (mGrContext) {
+        DeviceInfo::setMaxTextureSize(mGrContext->maxRenderTargetSize());
+    }
 }
 
 int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 038e13c..4881172 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -16,7 +16,6 @@
 
 #include "VulkanManager.h"
 
-#include "DeviceInfo.h"
 #include "Properties.h"
 #include "RenderThread.h"
 #include "renderstate/RenderState.h"
@@ -399,8 +398,6 @@
 
     free_features_extensions_structs(features);
 
-    DeviceInfo::initialize(mRenderThread.getGrContext()->maxRenderTargetSize());
-
     if (Properties::enablePartialUpdates && Properties::useBufferAge) {
         mSwapBehavior = SwapBehavior::BufferAge;
     }
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 0e6582c..c35f512 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -16,7 +16,6 @@
 
 #pragma once
 
-#include <DeviceInfo.h>
 #include <DisplayList.h>
 #include <Matrix.h>
 #include <Properties.h>
@@ -179,12 +178,6 @@
     static sp<RenderNode> createNode(
             int left, int top, int right, int bottom,
             std::function<void(RenderProperties& props, Canvas& canvas)> setup) {
-#if HWUI_NULL_GPU
-        // if RenderNodes are being sync'd/used, device info will be needed, since
-        // DeviceInfo::maxTextureSize() affects layer property
-        DeviceInfo::initialize();
-#endif
-
         sp<RenderNode> node = new RenderNode();
         RenderProperties& props = node->mutateStagingProperties();
         props.setLeftTopRightBottom(left, top, right, bottom);
@@ -202,12 +195,6 @@
     static sp<RenderNode> createNode(
             int left, int top, int right, int bottom,
             std::function<void(RenderProperties& props, RecordingCanvasType& canvas)> setup) {
-#if HWUI_NULL_GPU
-        // if RenderNodes are being sync'd/used, device info will be needed, since
-        // DeviceInfo::maxTextureSize() affects layer property
-        DeviceInfo::initialize();
-#endif
-
         sp<RenderNode> node = new RenderNode();
         RenderProperties& props = node->mutateStagingProperties();
         props.setLeftTopRightBottom(left, top, right, bottom);
@@ -233,11 +220,6 @@
             std::function<void(RenderProperties& props, skiapipeline::SkiaRecordingCanvas& canvas)>
                     setup,
             const char* name = nullptr, skiapipeline::SkiaDisplayList* displayList = nullptr) {
-#if HWUI_NULL_GPU
-        // if RenderNodes are being sync'd/used, device info will be needed, since
-        // DeviceInfo::maxTextureSize() affects layer property
-        DeviceInfo::initialize();
-#endif
         sp<RenderNode> node = new RenderNode();
         if (name) {
             node->setName(name);
diff --git a/libs/hwui/tests/unit/RenderPropertiesTests.cpp b/libs/hwui/tests/unit/RenderPropertiesTests.cpp
index 85655fc..3e8e057 100644
--- a/libs/hwui/tests/unit/RenderPropertiesTests.cpp
+++ b/libs/hwui/tests/unit/RenderPropertiesTests.cpp
@@ -22,8 +22,6 @@
 using namespace android::uirenderer;
 
 TEST(RenderProperties, layerValidity) {
-    DeviceInfo::initialize();
-
     const int maxTextureSize = DeviceInfo::get()->maxTextureSize();
     ASSERT_LE(2048, maxTextureSize);
     ASSERT_GT(100000, maxTextureSize);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d1d605f..1d27c03 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -43,6 +43,8 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  MediaCodec class can be used to access low-level media codecs, i.e. encoder/decoder components.
@@ -3582,7 +3584,18 @@
     }
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    private long mNativeContext;
+    private long mNativeContext = 0;
+    private final Lock mNativeContextLock = new ReentrantLock();
+
+    private final long lockAndGetContext() {
+        mNativeContextLock.lock();
+        return mNativeContext;
+    }
+
+    private final void setAndUnlockContext(long context) {
+        mNativeContext = context;
+        mNativeContextLock.unlock();
+    }
 
     /** @hide */
     public static class MediaImage extends Image {
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 6ae4d40..6187900 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -544,29 +544,11 @@
     private static final int INVOKE_ID_GET_SELECTED_TRACK = 7;
 
     /**
-     * Create a request parcel which can be routed to the native media
-     * player using {@link #invoke(Parcel, Parcel)}. The Parcel
-     * returned has the proper InterfaceToken set. The caller should
-     * not overwrite that token, i.e it can only append data to the
-     * Parcel.
-     *
-     * @return A parcel suitable to hold a request for the native
-     * player.
-     * {@hide}
-     */
-    @Override
-    public Parcel newRequest() {
-        Parcel parcel = Parcel.obtain();
-        return parcel;
-    }
-
-    /**
      * Invoke a generic method on the native player using opaque protocol
      * buffer message for the request and reply. Both payloads' format is a
      * convention between the java caller and the native player.
      *
-     * @param request PlayerMessage for the extension. The
-     * caller must use {@link #newRequest()} to get one.
+     * @param msg PlayerMessage for the extension.
      *
      * @return PlayerMessage with the data returned by the
      * native player.
@@ -1536,91 +1518,6 @@
     }
 
     /**
-     * Gets the media metadata.
-     *
-     * @param update_only controls whether the full set of available
-     * metadata is returned or just the set that changed since the
-     * last call. See {@see #METADATA_UPDATE_ONLY} and {@see
-     * #METADATA_ALL}.
-     *
-     * @param apply_filter if true only metadata that matches the
-     * filter is returned. See {@see #APPLY_METADATA_FILTER} and {@see
-     * #BYPASS_METADATA_FILTER}.
-     *
-     * @return The metadata, possibly empty. null if an error occured.
-     // FIXME: unhide.
-     * {@hide}
-     */
-    @Override
-    public Metadata getMetadata(final boolean update_only,
-                                final boolean apply_filter) {
-        Parcel reply = Parcel.obtain();
-        Metadata data = new Metadata();
-
-        if (!native_getMetadata(update_only, apply_filter, reply)) {
-            reply.recycle();
-            return null;
-        }
-
-        // Metadata takes over the parcel, don't recycle it unless
-        // there is an error.
-        if (!data.parse(reply)) {
-            reply.recycle();
-            return null;
-        }
-        return data;
-    }
-
-    /**
-     * Set a filter for the metadata update notification and update
-     * retrieval. The caller provides 2 set of metadata keys, allowed
-     * and blocked. The blocked set always takes precedence over the
-     * allowed one.
-     * Metadata.MATCH_ALL and Metadata.MATCH_NONE are 2 sets available as
-     * shorthands to allow/block all or no metadata.
-     *
-     * By default, there is no filter set.
-     *
-     * @param allow Is the set of metadata the client is interested
-     *              in receiving new notifications for.
-     * @param block Is the set of metadata the client is not interested
-     *              in receiving new notifications for.
-     * @return The call status code.
-     *
-     // FIXME: unhide.
-     * {@hide}
-     */
-    @Override
-    public int setMetadataFilter(Set<Integer> allow, Set<Integer> block) {
-        // Do our serialization manually instead of calling
-        // Parcel.writeArray since the sets are made of the same type
-        // we avoid paying the price of calling writeValue (used by
-        // writeArray) which burns an extra int per element to encode
-        // the type.
-        Parcel request =  newRequest();
-
-        // The parcel starts already with an interface token. There
-        // are 2 filters. Each one starts with a 4bytes number to
-        // store the len followed by a number of int (4 bytes as well)
-        // representing the metadata type.
-        int capacity = request.dataSize() + 4 * (1 + allow.size() + 1 + block.size());
-
-        if (request.dataCapacity() < capacity) {
-            request.setDataCapacity(capacity);
-        }
-
-        request.writeInt(allow.size());
-        for(Integer t: allow) {
-            request.writeInt(t);
-        }
-        request.writeInt(block.size());
-        for(Integer t: block) {
-            request.writeInt(t);
-        }
-        return native_setMetadataFilter(request);
-    }
-
-    /**
      * Resets the MediaPlayer2 to its uninitialized state. After calling
      * this method, you will have to initialize it again by setting the
      * data source and calling prepare().
@@ -1802,32 +1699,6 @@
 
     private native void _setAuxEffectSendLevel(float level);
 
-    /*
-     * @param update_only If true fetch only the set of metadata that have
-     *                    changed since the last invocation of getMetadata.
-     *                    The set is built using the unfiltered
-     *                    notifications the native player sent to the
-     *                    MediaPlayer2Manager during that period of
-     *                    time. If false, all the metadatas are considered.
-     * @param apply_filter  If true, once the metadata set has been built based on
-     *                     the value update_only, the current filter is applied.
-     * @param reply[out] On return contains the serialized
-     *                   metadata. Valid only if the call was successful.
-     * @return The status code.
-     */
-    private native final boolean native_getMetadata(boolean update_only,
-                                                    boolean apply_filter,
-                                                    Parcel reply);
-
-    /*
-     * @param request Parcel with the 2 serialized lists of allowed
-     *                metadata types followed by the one to be
-     *                dropped. Each list starts with an integer
-     *                indicating the number of metadata type elements.
-     * @return The status code.
-     */
-    private native final int native_setMetadataFilter(Parcel request);
-
     private static native final void native_init();
     private native final void native_setup(Object mediaplayer2_this);
     private native final void native_finalize();
@@ -1903,25 +1774,6 @@
             mFormat = format;
         }
 
-        /**
-         * Flatten this object in to a Parcel.
-         *
-         * @param dest The Parcel in which the object should be written.
-         * @param flags Additional flags about how the object should be written.
-         * May be 0 or {@link android.os.Parcelable#PARCELABLE_WRITE_RETURN_VALUE}.
-         */
-        /* package private */ void writeToParcel(Parcel dest, int flags) {
-            dest.writeInt(mTrackType);
-            dest.writeString(getLanguage());
-
-            if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-                dest.writeString(mFormat.getString(MediaFormat.KEY_MIME));
-                dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_AUTOSELECT));
-                dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_DEFAULT));
-                dest.writeInt(mFormat.getInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE));
-            }
-        }
-
         @Override
         public String toString() {
             StringBuilder out = new StringBuilder(128);
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 3490ff8..5037209 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -108,8 +108,9 @@
 } gCodecInfo;
 
 struct fields_t {
-    jfieldID context;
     jmethodID postEventFromNativeID;
+    jmethodID lockAndGetContextID;
+    jmethodID setAndUnlockContextID;
     jfieldID cryptoInfoNumSubSamplesID;
     jfieldID cryptoInfoNumBytesOfClearDataID;
     jfieldID cryptoInfoNumBytesOfEncryptedDataID;
@@ -931,7 +932,7 @@
 
 static sp<JMediaCodec> setMediaCodec(
         JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
-    sp<JMediaCodec> old = (JMediaCodec *)env->GetLongField(thiz, gFields.context);
+    sp<JMediaCodec> old = (JMediaCodec *)env->CallLongMethod(thiz, gFields.lockAndGetContextID);
     if (codec != NULL) {
         codec->incStrong(thiz);
     }
@@ -944,13 +945,15 @@
         old->release();
         old->decStrong(thiz);
     }
-    env->SetLongField(thiz, gFields.context, (jlong)codec.get());
+    env->CallVoidMethod(thiz, gFields.setAndUnlockContextID, (jlong)codec.get());
 
     return old;
 }
 
 static sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
-    return (JMediaCodec *)env->GetLongField(thiz, gFields.context);
+    sp<JMediaCodec> codec = (JMediaCodec *)env->CallLongMethod(thiz, gFields.lockAndGetContextID);
+    env->CallVoidMethod(thiz, gFields.setAndUnlockContextID, (jlong)codec.get());
+    return codec;
 }
 
 static void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
@@ -1876,15 +1879,21 @@
             env, env->FindClass("android/media/MediaCodec"));
     CHECK(clazz.get() != NULL);
 
-    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
-    CHECK(gFields.context != NULL);
-
     gFields.postEventFromNativeID =
         env->GetMethodID(
                 clazz.get(), "postEventFromNative", "(IIILjava/lang/Object;)V");
-
     CHECK(gFields.postEventFromNativeID != NULL);
 
+    gFields.lockAndGetContextID =
+        env->GetMethodID(
+                clazz.get(), "lockAndGetContext", "()J");
+    CHECK(gFields.lockAndGetContextID != NULL);
+
+    gFields.setAndUnlockContextID =
+        env->GetMethodID(
+                clazz.get(), "setAndUnlockContext", "(J)V");
+    CHECK(gFields.setAndUnlockContextID != NULL);
+
     jfieldID field;
     field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_UNENCRYPTED", "I");
     CHECK(field != NULL);
diff --git a/packages/SettingsLib/HelpUtils/res/values/strings.xml b/packages/SettingsLib/HelpUtils/res/values/strings.xml
index ae07f5d..3e882bc 100644
--- a/packages/SettingsLib/HelpUtils/res/values/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values/strings.xml
@@ -17,7 +17,7 @@
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <!-- Label for Help and feedback menu item -->
+    <!-- Label for Help and feedback menu item [CHAR LIMIT=45]-->
     <string name="help_feedback_label">Help &amp; feedback</string>
 
 </resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/RestrictedLockUtils/Android.bp b/packages/SettingsLib/RestrictedLockUtils/Android.bp
index d4c9794..b2f0882 100644
--- a/packages/SettingsLib/RestrictedLockUtils/Android.bp
+++ b/packages/SettingsLib/RestrictedLockUtils/Android.bp
@@ -2,6 +2,7 @@
     name: "SettingsLibRestrictedLockUtils",
 
     srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
 
     libs: [
         "androidx.annotation_annotation",
diff --git a/packages/SettingsLib/res/layout/restricted_icon.xml b/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml
similarity index 76%
rename from packages/SettingsLib/res/layout/restricted_icon.xml
rename to packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml
index 724a524..0f02abd 100644
--- a/packages/SettingsLib/res/layout/restricted_icon.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml
@@ -15,6 +15,7 @@
 -->
 <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/restricted_icon"
-    android:layout_width="@dimen/restricted_icon_size"
-    android:layout_height="@dimen/restricted_icon_size"
-    android:src="@drawable/ic_info" />
\ No newline at end of file
+    android:layout_width="@*android:dimen/config_restricted_icon_size"
+    android:layout_height="@*android:dimen/config_restricted_icon_size"
+    android:tint="?android:attr/colorAccent"
+    android:src="@*android:drawable/ic_info" />
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/values/strings.xml b/packages/SettingsLib/RestrictedLockUtils/res/values/strings.xml
new file mode 100644
index 0000000..7e4460b
--- /dev/null
+++ b/packages/SettingsLib/RestrictedLockUtils/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
+    <string name="enabled_by_admin">Enabled by admin</string>
+    <!-- Summary for switch preference to denote it is switched off [CHAR LIMIT=50] -->
+    <string name="disabled_by_admin">Disabled by admin</string>
+
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/restricted_switch_widget.xml b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
index b286df0..e1f6cdf 100644
--- a/packages/SettingsLib/res/layout/restricted_switch_widget.xml
+++ b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
@@ -16,9 +16,10 @@
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
     <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/restricted_icon"
-        android:layout_width="@dimen/restricted_icon_size"
-        android:layout_height="@dimen/restricted_icon_size"
-        android:src="@drawable/ic_info"
+        android:layout_width="@*android:dimen/config_restricted_icon_size"
+        android:layout_height="@*android:dimen/config_restricted_icon_size"
+        android:tint="?android:attr/colorAccent"
+        android:src="@*android:drawable/ic_info"
         android:gravity="end|center_vertical" />
     <!-- Based off frameworks/base/core/res/res/layout/preference_widget_switch.xml -->
     <Switch xmlns:android="http://schemas.android.com/apk/res/android"
@@ -28,4 +29,4 @@
         android:focusable="false"
         android:clickable="false"
         android:background="@null" />
-</merge>
\ No newline at end of file
+</merge>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 8094b02..a9c5061 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -36,7 +36,6 @@
     <dimen name="two_target_pref_medium_icon_size">32dp</dimen>
 
     <!-- Lock icon for preferences locked by admin -->
-    <dimen name="restricted_icon_size">16dp</dimen>
     <dimen name="restricted_icon_padding">4dp</dimen>
 
     <dimen name="wifi_preference_badge_padding">8dip</dimen>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index ea6844e..332ced6 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -965,11 +965,6 @@
     <!-- Summary for settings preference disabled by administrator [CHAR LIMIT=50] -->
     <string name="disabled_by_admin_summary_text">Controlled by admin</string>
 
-    <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
-    <string name="enabled_by_admin">Enabled by admin</string>
-    <!-- Summary for switch preference to denote it is switched off [CHAR LIMIT=50] -->
-    <string name="disabled_by_admin">Disabled by admin</string>
-
     <!-- [CHAR LIMIT=25] Manage applications, text telling using an application is disabled. -->
     <string name="disabled">Disabled</string>
     <!-- Summary of app trusted to install apps [CHAR LIMIT=45] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
index 0094c2c..c03ba9a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
@@ -29,6 +29,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -55,9 +56,15 @@
      * @return drawables for displaying with settings that are locked by a device admin.
      */
     public static Drawable getRestrictedPadlock(Context context) {
-        Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_info);
+        Drawable restrictedPadlock = context.getDrawable(android.R.drawable.ic_info);
         final int iconSize = context.getResources().getDimensionPixelSize(
-                R.dimen.restricted_icon_size);
+                android.R.dimen.config_restricted_icon_size);
+
+        TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.colorAccent});
+        int colorAccent = ta.getColor(0, 0);
+        ta.recycle();
+        restrictedPadlock.setTint(colorAccent);
+
         restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
         return restrictedPadlock;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index e8f47e1..5a64e02 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -211,6 +211,26 @@
         }
     }
 
+    /**
+     * Attempts to get the name of a remote device, otherwise returns the address.
+     *
+     * @param device The remote device.
+     * @return The name, or if unavailable, the address.
+     */
+    public String getName(BluetoothDevice device) {
+        CachedBluetoothDevice cachedDevice = findDevice(device);
+        if (cachedDevice != null && cachedDevice.getName() != null) {
+            return cachedDevice.getName();
+        }
+
+        String name = device.getAliasName();
+        if (name != null) {
+            return name;
+        }
+
+        return device.getAddress();
+    }
+
     public synchronized void clearNonBondedDevices() {
 
         mCachedDevicesMapForHearingAids.entrySet().removeIf(entries
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
index 8c4bff5..c8d4fc8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
@@ -29,7 +29,7 @@
 import java.util.List;
 
 /**
- * HidProfile handles Bluetooth HID profile.
+ * HidDeviceProfile handles Bluetooth HID Device role
  */
 public class HidDeviceProfile implements LocalBluetoothProfile {
     private static final String TAG = "HidDeviceProfile";
@@ -37,7 +37,6 @@
     private static final int ORDINAL = 18;
     // HID Device Profile is always preferred.
     private static final int PREFERRED_VALUE = -1;
-    private static final boolean DEBUG = true;
 
     private final CachedBluetoothDeviceManager mDeviceManager;
     private final LocalBluetoothProfileManager mProfileManager;
@@ -59,9 +58,7 @@
             implements BluetoothProfile.ServiceListener {
 
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (DEBUG) {
-                Log.d(TAG,"Bluetooth service connected :-)");
-            }
+            Log.d(TAG, "Bluetooth service connected :-), profile:" + profile);
             mService = (BluetoothHidDevice) proxy;
             // We just bound to the service, so refresh the UI for any connected HID devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -81,9 +78,7 @@
         }
 
         public void onServiceDisconnected(int profile) {
-            if (DEBUG) {
-                Log.d(TAG, "Bluetooth service disconnected");
-            }
+            Log.d(TAG, "Bluetooth service disconnected, profile:" + profile);
             mIsProfileReady = false;
         }
     }
@@ -110,6 +105,7 @@
 
     @Override
     public boolean connect(BluetoothDevice device) {
+        // Don't invoke method in service because settings is not allowed to connect this profile.
         return false;
     }
 
@@ -126,11 +122,7 @@
         if (mService == null) {
             return BluetoothProfile.STATE_DISCONNECTED;
         }
-        List<BluetoothDevice> deviceList = mService.getConnectedDevices();
-
-        return !deviceList.isEmpty() && deviceList.contains(device)
-                ? mService.getConnectionState(device)
-                : BluetoothProfile.STATE_DISCONNECTED;
+        return mService.getConnectionState(device);
     }
 
     @Override
@@ -185,9 +177,7 @@
     }
 
     protected void finalize() {
-        if (DEBUG) {
-            Log.d(TAG, "finalize()");
-        }
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HID_DEVICE,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
index 7d334eb..7ad2e28c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
@@ -32,11 +32,10 @@
 import java.util.List;
 
 /**
- * MapClientProfile handles Bluetooth MAP profile.
+ * MapClientProfile handles the Bluetooth MAP MCE role.
  */
 public final class MapClientProfile implements LocalBluetoothProfile {
     private static final String TAG = "MapClientProfile";
-    private static boolean V = false;
 
     private BluetoothMapClient mService;
     private boolean mIsProfileReady;
@@ -60,7 +59,7 @@
             implements BluetoothProfile.ServiceListener {
 
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (V) Log.d(TAG,"Bluetooth service connected");
+            Log.d(TAG, "Bluetooth service connected, profile:" + profile);
             mService = (BluetoothMapClient) proxy;
             // We just bound to the service, so refresh the UI for any connected MAP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -82,14 +81,14 @@
         }
 
         public void onServiceDisconnected(int profile) {
-            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            Log.d(TAG, "Bluetooth service disconnected, profile:" + profile);
             mProfileManager.callServiceDisconnectedListeners();
             mIsProfileReady=false;
         }
     }
 
     public boolean isProfileReady() {
-        if(V) Log.d(TAG,"isProfileReady(): "+ mIsProfileReady);
+        Log.d(TAG, "isProfileReady(): "+ mIsProfileReady);
         return mIsProfileReady;
     }
 
@@ -115,18 +114,16 @@
     }
 
     public boolean connect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> connectedDevices = getConnectedDevices();
-        if (connectedDevices != null && connectedDevices.contains(device)) {
-            // Connect to same device, Ignore it
-            Log.d(TAG,"Ignoring Connect");
-            return true;
+        if (mService == null) {
+            return false;
         }
         return mService.connect(device);
     }
 
     public boolean disconnect(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         // Downgrade priority as user is disconnecting.
         if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
             mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -135,23 +132,30 @@
     }
 
     public int getConnectionStatus(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
-
+        if (mService == null) {
+            return BluetoothProfile.STATE_DISCONNECTED;
+        }
         return mService.getConnectionState(device);
     }
 
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
     }
 
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return BluetoothProfile.PRIORITY_OFF;
+        }
         return mService.getPriority(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -162,7 +166,9 @@
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
         return mService.getDevicesMatchingConnectionStates(
               new int[] {BluetoothProfile.STATE_CONNECTED,
                          BluetoothProfile.STATE_CONNECTING,
@@ -200,11 +206,11 @@
     }
 
     protected void finalize() {
-        if (V) Log.d(TAG, "finalize()");
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.MAP_CLIENT,
-                                                                       mService);
+                        mService);
                 mService = null;
             }catch (Throwable t) {
                 Log.w(TAG, "Error cleaning up MAP Client proxy", t);
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsDetailLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsDetailLoader.java
new file mode 100644
index 0000000..a070b2a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsDetailLoader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.net;
+
+import android.app.usage.NetworkStatsManager;
+import android.app.usage.NetworkStats;
+import android.content.Context;
+import android.os.RemoteException;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import androidx.loader.content.AsyncTaskLoader;
+
+/**
+ * Loader for retrieving the network stats details for all UIDs.
+ */
+public class NetworkStatsDetailLoader extends AsyncTaskLoader<NetworkStats> {
+
+    private static final String TAG = "NetworkDetailLoader";
+    private final NetworkStatsManager mNetworkStatsManager;
+    private final TelephonyManager mTelephonyManager;
+    private final long mStart;
+    private final long mEnd;
+    private final int mSubId;
+    private final int mNetworkType;
+
+    private NetworkStatsDetailLoader(Builder builder) {
+        super(builder.mContext);
+        mStart = builder.mStart;
+        mEnd = builder.mEnd;
+        mSubId = builder.mSubId;
+        mNetworkType = builder.mNetworkType;
+        mNetworkStatsManager = (NetworkStatsManager)
+                builder.mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
+        mTelephonyManager =
+                (TelephonyManager) builder.mContext.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
+    @Override
+    protected void onStartLoading() {
+        super.onStartLoading();
+        forceLoad();
+    }
+
+    @Override
+    public NetworkStats loadInBackground() {
+        try {
+            return mNetworkStatsManager.queryDetails(
+                    mNetworkType, mTelephonyManager.getSubscriberId(mSubId), mStart, mEnd);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception querying network detail.", e);
+            return null;
+        }
+    }
+
+    @Override
+    protected void onStopLoading() {
+        super.onStopLoading();
+        cancelLoad();
+    }
+
+    @Override
+    protected void onReset() {
+        super.onReset();
+        cancelLoad();
+    }
+
+    public static class Builder {
+        private final Context mContext;
+        private long mStart;
+        private long mEnd;
+        private int mSubId;
+        private int mNetworkType;
+
+        public Builder(Context context) {
+            mContext = context;
+        }
+
+        public Builder setStartTime(long start) {
+            mStart = start;
+            return this;
+        }
+
+        public Builder setEndTime(long end) {
+            mEnd = end;
+            return this;
+        }
+
+        public Builder setSubscriptionId(int subId) {
+            mSubId = subId;
+            return this;
+        }
+
+        public Builder setNetworkType(int networkType) {
+            mNetworkType = networkType;
+            return this;
+        }
+
+        public NetworkStatsDetailLoader build() {
+            return new NetworkStatsDetailLoader(this);
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java
index c311337..82bb011 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java
@@ -25,6 +25,12 @@
 
 import androidx.loader.content.AsyncTaskLoader;
 
+/**
+ * Deprecated in favor of {@link NetworkStatsDetailLoader}
+ *
+ * @deprecated
+ */
+@Deprecated
 public class SummaryForAllUidLoaderCompat extends AsyncTaskLoader<NetworkStats> {
     private static final String KEY_TEMPLATE = "template";
     private static final String KEY_START = "start";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
index dde1746..0ca2e87 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
@@ -52,6 +52,8 @@
                 @Override
                 public List<ResourcePath> getIncludedResourcePaths() {
                     final List<ResourcePath> paths = super.getIncludedResourcePaths();
+                    paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/HelpUtils/res"));
+                    paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/RestrictedLockUtils/res"));
                     paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/res"));
                     paths.add(resourcePath("file:frameworks/base/core/res/res"));
                     paths.add(resourcePath("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.appcompat_appcompat-nodeps/android_common/aar/res/"));
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index 8ac611f..7baded8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -139,7 +139,7 @@
     public void testGetName_validCachedDevice_nameFound() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
         assertThat(cachedDevice1).isNotNull();
-        assertThat(mCachedDeviceManager.findDevice(mDevice1).getName()).isEqualTo(DEVICE_ALIAS_1);
+        assertThat(mCachedDeviceManager.getName(mDevice1)).isEqualTo(DEVICE_ALIAS_1);
     }
 
     /**
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java
new file mode 100644
index 0000000..c91ee22
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHidDevice;
+import android.bluetooth.BluetoothProfile;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class HidDeviceProfileTest {
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothHidDevice mService;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private HidDeviceProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new HidDeviceProfile(RuntimeEnvironment.application,
+                mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
+        mServiceListener.onServiceConnected(BluetoothProfile.HID_DEVICE, mService);
+    }
+
+    @Test
+    public void connect_shouldReturnFalse() {
+        assertThat(mProfile.connect(mBluetoothDevice)).isFalse();
+    }
+
+    @Test
+    public void disconnect_shouldDisconnectBluetoothHidDevice() {
+        mProfile.disconnect(mBluetoothDevice);
+        verify(mService).disconnect(mBluetoothDevice);
+    }
+
+    @Test
+    public void getConnectionStatus_shouldReturnConnectionState() {
+        when(mService.getConnectionState(mBluetoothDevice)).
+                thenReturn(BluetoothProfile.STATE_CONNECTED);
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+                isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java
new file mode 100644
index 0000000..c4c48a8
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothMapClient;
+import android.bluetooth.BluetoothProfile;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class MapClientProfileTest {
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothMapClient mService;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private MapClientProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new MapClientProfile(RuntimeEnvironment.application,
+                mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
+        mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT, mService);
+    }
+
+    @Test
+    public void connect_shouldConnectBluetoothMapClient() {
+        mProfile.connect(mBluetoothDevice);
+        verify(mService).connect(mBluetoothDevice);
+    }
+
+    @Test
+    public void disconnect_shouldDisconnectBluetoothMapClient() {
+        mProfile.disconnect(mBluetoothDevice);
+        verify(mService).disconnect(mBluetoothDevice);
+    }
+
+    @Test
+    public void getConnectionStatus_shouldReturnConnectionState() {
+        when(mService.getConnectionState(mBluetoothDevice)).
+                thenReturn(BluetoothProfile.STATE_CONNECTED);
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+                isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
index a501ffa..40e7386 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
@@ -77,10 +77,10 @@
 
     @Test
     public void getIcon_hasIconMetadata_returnIcon() {
-        mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_info);
+        mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, android.R.drawable.ic_info);
 
         assertThat(mTile.getIcon(RuntimeEnvironment.application).getResId())
-                .isEqualTo(R.drawable.ic_info);
+                .isEqualTo(android.R.drawable.ic_info);
     }
 
     @Test
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index cc1b9e8..bde7f1b 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -55,6 +55,7 @@
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArraySet;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -318,8 +319,8 @@
         ArraySet<String> addedKeys = new ArraySet<String>();
         mHasLogoutButton = false;
         mHasLockdownButton = false;
-        mSeparatedEmergencyButtonEnabled = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.FASTER_EMERGENCY_PHONE_CALL_ENABLED, 0) != 0;
+        mSeparatedEmergencyButtonEnabled = FeatureFlagUtils
+                .isEnabled(mContext, FeatureFlagUtils.EMERGENCY_DIAL_SHORTCUTS);
         for (int i = 0; i < defaultActions.length; i++) {
             String actionKey = defaultActions[i];
             if (addedKeys.contains(actionKey)) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index ca1b489..123fca7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -391,6 +391,9 @@
                 position = mPages.size() - 1 - position;
             }
             ViewGroup view = mPages.get(position);
+            if (view.getParent() != null) {
+                container.removeView(view);
+            }
             container.addView(view);
             updateListening();
             return view;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 167bba6..51a5df2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -135,6 +135,7 @@
         mWindowManager.addView(mStatusBarView, mLp);
         mLpChanged = new WindowManager.LayoutParams();
         mLpChanged.copyFrom(mLp);
+        onThemeChanged();
     }
 
     public void setDozeScreenBrightness(int value) {
@@ -483,6 +484,10 @@
 
     @Override
     public void onThemeChanged() {
+        if (mStatusBarView == null) {
+            return;
+        }
+
         StatusBarStateController state = Dependency.get(StatusBarStateController.class);
         int which;
         if (state.getState() == StatusBarState.KEYGUARD
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index f8223f6..f7a7e04 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -83,4 +84,16 @@
                 & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
         assertThat(flag).isEqualTo(0);
     }
+
+    @Test
+    public void testOnThemeChanged_doesntCrash() {
+        mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
+                mActivityManager, mDozeParameters);
+        mStatusBarWindowController.onThemeChanged();
+    }
+
+    @Test
+    public void testAdd_updatesVisibilityFlags() {
+        verify(mStatusBarView).setSystemUiVisibility(anyInt());
+    }
 }
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index 51d95a2..872261a 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -202,6 +202,15 @@
                     reset();
                     pw.println("binder_calls_stats reset.");
                     return;
+                } else if ("--enable".equals(arg)) {
+                    Binder.setObserver(mBinderCallsStats);
+                    return;
+                } else if ("--disable".equals(arg)) {
+                    Binder.setObserver(null);
+                    return;
+                } else if ("--no-sampling".equals(arg)) {
+                    mBinderCallsStats.setSamplingInterval(1);
+                    return;
                 } else if ("--enable-detailed-tracking".equals(arg)) {
                     SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "1");
                     mBinderCallsStats.setDetailedTracking(true);
@@ -215,6 +224,9 @@
                 } else if ("-h".equals(arg)) {
                     pw.println("binder_calls_stats commands:");
                     pw.println("  --reset: Reset stats");
+                    pw.println("  --enable: Enable tracking binder calls");
+                    pw.println("  --disable: Disables tracking binder calls");
+                    pw.println("  --no-sampling: Tracks all calls");
                     pw.println("  --enable-detailed-tracking: Enables detailed tracking");
                     pw.println("  --disable-detailed-tracking: Disables detailed tracking");
                     return;
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index 1866420..01421c7 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -126,11 +126,6 @@
 
     private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
 
-    @VisibleForTesting
-    ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
-        this(supervisor, supervisor.mDisplayManager.getDisplay(displayId));
-    }
-
     ActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
         mSupervisor = supervisor;
         mDisplayId = display.getDisplayId();
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index eb41fe7..bcb2b9b 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -52,6 +52,7 @@
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
@@ -1901,14 +1902,20 @@
         // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
         // the same behavior as if a new instance was being started, which means not bringing it
         // to the front if the caller is not itself in the front.
-        final ActivityStack focusStack = mSupervisor.getTopDisplayFocusedStack();
-        ActivityRecord curTop = (focusStack == null)
-                ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
+        final boolean differentTopTask;
+        if (mPreferredDisplayId == mTargetStack.mDisplayId) {
+            final ActivityStack focusStack = mTargetStack.getDisplay().getFocusedStack();
+            final ActivityRecord curTop = (focusStack == null)
+                    ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
+            final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
+            differentTopTask = topTask != null
+                    && (topTask != intentActivity.getTask() || topTask != focusStack.topTask());
+        } else {
+            // The existing task should always be different from those in other displays.
+            differentTopTask = true;
+        }
 
-        final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
-        if (topTask != null
-                && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
-                && !mAvoidMoveToFront) {
+        if (differentTopTask && !mAvoidMoveToFront) {
             mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
             if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
                     mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 2e2a3c1..33f0172 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4402,22 +4402,12 @@
     }
 
     protected boolean isBlocked(NotificationRecord r, NotificationUsageStats usageStats) {
-        final String pkg = r.sbn.getPackageName();
-        final int callingUid = r.sbn.getUid();
-
-        final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid);
-        if (isPackageSuspended) {
-            Slog.e(TAG, "Suppressing notification from package due to package "
-                    + "suspended by administrator.");
-            usageStats.registerSuspendedByAdmin(r);
-            return isPackageSuspended;
-        }
-        final boolean isBlocked = isBlocked(r);
-        if (isBlocked) {
+        if (isBlocked(r)) {
             Slog.e(TAG, "Suppressing notification from package by user request.");
             usageStats.registerBlocked(r);
+            return true;
         }
-        return isBlocked;
+        return false;
     }
 
     private boolean isBlocked(NotificationRecord r) {
@@ -4691,7 +4681,11 @@
                         return;
                     }
 
-                    r.setHidden(isPackageSuspendedLocked(r));
+                    final boolean isPackageSuspended = isPackageSuspendedLocked(r);
+                    r.setHidden(isPackageSuspended);
+                    if (isPackageSuspended) {
+                        mUsageStats.registerSuspendedByAdmin(r);
+                    }
                     NotificationRecord old = mNotificationsByKey.get(key);
                     final StatusBarNotification n = r.sbn;
                     final Notification notification = n.getNotification();
@@ -6922,7 +6916,6 @@
                 if (!oldSbnVisible && !sbnVisible) {
                     continue;
                 }
-
                 // If the notification is hidden, don't notifyPosted listeners targeting < P.
                 // Instead, those listeners will receive notifyPosted when the notification is
                 // unhidden.
@@ -7356,7 +7349,7 @@
                 new String[]{pkg});
 
         final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED
-            : Intent.ACTION_PACKAGES_UNSUSPENDED;
+                : Intent.ACTION_PACKAGES_UNSUSPENDED;
         final Intent intent = new Intent(action);
         intent.putExtras(extras);
 
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index bca3ca7..5c6fe16 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -63,6 +63,7 @@
 
     private final Context mContext;
     private final PackageManagerService mPackageManagerService;
+    private final MetricsLogger metricsLogger;
 
     // TODO: Evaluate the need for WeakReferences here.
 
@@ -95,6 +96,7 @@
     public OtaDexoptService(Context context, PackageManagerService packageManagerService) {
         this.mContext = context;
         this.mPackageManagerService = packageManagerService;
+        metricsLogger = new MetricsLogger();
     }
 
     public static OtaDexoptService main(Context context,
@@ -445,24 +447,22 @@
     private void performMetricsLogging() {
         long finalTime = System.nanoTime();
 
-        MetricsLogger.histogram(mContext, "ota_dexopt_available_space_before_mb",
+        metricsLogger.histogram("ota_dexopt_available_space_before_mb",
                 inMegabytes(availableSpaceBefore));
-        MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_bulk_delete_mb",
+        metricsLogger.histogram("ota_dexopt_available_space_after_bulk_delete_mb",
                 inMegabytes(availableSpaceAfterBulkDelete));
-        MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_dexopt_mb",
+        metricsLogger.histogram("ota_dexopt_available_space_after_dexopt_mb",
                 inMegabytes(availableSpaceAfterDexopt));
 
-        MetricsLogger.histogram(mContext, "ota_dexopt_num_important_packages",
-                importantPackageCount);
-        MetricsLogger.histogram(mContext, "ota_dexopt_num_other_packages", otherPackageCount);
+        metricsLogger.histogram("ota_dexopt_num_important_packages", importantPackageCount);
+        metricsLogger.histogram("ota_dexopt_num_other_packages", otherPackageCount);
 
-        MetricsLogger.histogram(mContext, "ota_dexopt_num_commands", dexoptCommandCountTotal);
-        MetricsLogger.histogram(mContext, "ota_dexopt_num_commands_executed",
-                dexoptCommandCountExecuted);
+        metricsLogger.histogram("ota_dexopt_num_commands", dexoptCommandCountTotal);
+        metricsLogger.histogram("ota_dexopt_num_commands_executed", dexoptCommandCountExecuted);
 
         final int elapsedTimeSeconds =
                 (int) TimeUnit.NANOSECONDS.toSeconds(finalTime - otaDexoptTimeStart);
-        MetricsLogger.histogram(mContext, "ota_dexopt_time_s", elapsedTimeSeconds);
+        metricsLogger.histogram("ota_dexopt_time_s", elapsedTimeSeconds);
     }
 
     private static class OTADexoptPackageDexOptimizer extends
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 350d6b6..3b19beb 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3543,8 +3543,6 @@
             return 0;
         } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) {
             return -1;
-        } else if (mHasFeatureLeanback && interceptAccessibilityGestureTv(keyCode, down)) {
-            return -1;
         } else if (keyCode == KeyEvent.KEYCODE_ALL_APPS) {
             if (!down) {
                 mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
@@ -6037,6 +6035,22 @@
             }
         }
 
+        // Intercept the Accessibility keychord for TV (DPAD_DOWN + Back) before the keyevent is
+        // processed through interceptKeyEventBeforeDispatch since Talkback may consume this event
+        // before it has a chance to reach that method.
+        if (mHasFeatureLeanback) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_DPAD_DOWN:
+                case KeyEvent.KEYCODE_BACK: {
+                    boolean handled = interceptAccessibilityGestureTv(keyCode, down);
+                    if (handled) {
+                        result &= ~ACTION_PASS_TO_USER;
+                    }
+                    break;
+                }
+            }
+        }
+
         if (useHapticFeedback) {
             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false,
                     "Virtual Key - Press");
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 2091899..a4d42a1 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -976,10 +976,11 @@
         }
 
         List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        looperStats.reset();
         long elapsedNanos = SystemClock.elapsedRealtimeNanos();
         for (LooperStats.ExportedEntry entry : entries) {
-            StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 9 /* fields */);
-            e.writeLong(0); // uid collection not implemented yet
+            StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 10 /* fields */);
+            e.writeInt(1000); // uid collection not implemented yet
             e.writeString(entry.handlerClassName);
             e.writeString(entry.threadName);
             e.writeString(entry.messageName);
@@ -988,6 +989,7 @@
             e.writeLong(entry.recordedMessageCount);
             e.writeLong(entry.totalLatencyMicros);
             e.writeLong(entry.cpuUsageMicros);
+            e.writeBoolean(entry.isInteractive);
             pulledData.add(e);
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ac65826..6c7304d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -409,6 +409,9 @@
 
     private InputMonitor mInputMonitor;
 
+    /** Caches the value whether told display manager that we have content. */
+    private boolean mLastHasContent;
+
     /**
      * The input method window for this display.
      */
@@ -3092,8 +3095,9 @@
         forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
         prepareSurfaces();
 
+        mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
         mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
-                mTmpApplySurfaceChangesTransactionState.displayHasContent,
+                mLastHasContent,
                 mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
                 mTmpApplySurfaceChangesTransactionState.preferredModeId,
                 true /* inTraversal, must call performTraversalInTrans... below */);
@@ -4267,4 +4271,11 @@
     InputMonitor getInputMonitor() {
         return mInputMonitor;
     }
+
+    /**
+     * @return Cached value whether we told display manager that we have content.
+     */
+    boolean getLastHasContent() {
+        return mLastHasContent;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 685c444..bd82553 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -21,6 +21,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
+import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -732,10 +733,13 @@
             boolean shouldUpdateOrientationListener = false;
 
             // Configure rotation suggestions.
-            final int showRotationSuggestions = Settings.Secure.getIntForUser(resolver,
-                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
-                    Settings.Secure.SHOW_ROTATION_SUGGESTIONS_DEFAULT,
-                    UserHandle.USER_CURRENT);
+            final int showRotationSuggestions =
+                    ActivityManager.isLowRamDeviceStatic()
+                            ? Settings.Secure.SHOW_ROTATION_SUGGESTIONS_DISABLED
+                            : Settings.Secure.getIntForUser(resolver,
+                            Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
+                            Settings.Secure.SHOW_ROTATION_SUGGESTIONS_DEFAULT,
+                            UserHandle.USER_CURRENT);
             if (mShowRotationSuggestions != showRotationSuggestions) {
                 mShowRotationSuggestions = showRotationSuggestions;
                 shouldUpdateOrientationListener = true;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index fec8039..979149a 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1176,15 +1176,17 @@
                         if (mIsWallpaper) {
                             w.dispatchWallpaperVisibility(true);
                         }
-                        // This draw means the difference between unique content and mirroring.
-                        // Run another pass through performLayout to set mHasContent in the
-                        // LogicalDisplay.
-                        mAnimator.setPendingLayoutChanges(w.getDisplayId(),
-                                FINISH_LAYOUT_REDO_ANIM);
-                        if (DEBUG_LAYOUT_REPEATS) {
-                            mService.mWindowPlacerLocked.debugLayoutRepeats(
-                                    "showSurfaceRobustlyLocked " + w,
-                                    mAnimator.getPendingLayoutChanges(w.getDisplayId()));
+                        if (!w.getDisplayContent().getLastHasContent()) {
+                            // This draw means the difference between unique content and mirroring.
+                            // Run another pass through performLayout to set mHasContent in the
+                            // LogicalDisplay.
+                            mAnimator.setPendingLayoutChanges(w.getDisplayId(),
+                                    FINISH_LAYOUT_REDO_ANIM);
+                            if (DEBUG_LAYOUT_REPEATS) {                        
+                                mService.mWindowPlacerLocked.debugLayoutRepeats(
+                                        "showSurfaceRobustlyLocked " + w,
+                                        mAnimator.getPendingLayoutChanges(w.getDisplayId()));
+                            }
                         }
                     } else {
                         w.setOrientationChanging(false);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0ca0835..4c71d65 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2588,12 +2588,32 @@
 
     ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
             throws SecurityException {
+        return getActiveAdminOrCheckPermissionForCallerLocked(who,
+                reqPolicy, /* permission= */ null);
+    }
+
+    /**
+     * Finds an active admin for the caller then checks {@code permission} if admin check failed.
+     *
+     * @return an active admin or {@code null} if there is no active admin but
+     * {@code permission} is granted
+     * @throws SecurityException if caller neither has an active admin nor {@code permission}
+     */
+    @Nullable
+    ActiveAdmin getActiveAdminOrCheckPermissionForCallerLocked(
+            ComponentName who,
+            int reqPolicy,
+            @Nullable String permission) throws SecurityException {
         ensureLocked();
         final int callingUid = mInjector.binderGetCallingUid();
 
         ActiveAdmin result = getActiveAdminWithPolicyForUidLocked(who, reqPolicy, callingUid);
         if (result != null) {
             return result;
+        } else if (permission != null
+                && (mContext.checkCallingPermission(permission)
+                        == PackageManager.PERMISSION_GRANTED)) {
+            return null;
         }
 
         if (who != null) {
@@ -2605,7 +2625,7 @@
 
             if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
                 throw new SecurityException("Admin " + admin.info.getComponent()
-                         + " does not own the device");
+                        + " does not own the device");
             }
             if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
                 throw new SecurityException("Admin " + admin.info.getComponent()
@@ -2621,20 +2641,39 @@
                     + admin.info.getTagForPolicy(reqPolicy));
         } else {
             throw new SecurityException("No active admin owned by uid "
-                    + mInjector.binderGetCallingUid() + " for policy #" + reqPolicy);
+                    + callingUid + " for policy #" + reqPolicy);
         }
     }
 
     ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy, boolean parent)
             throws SecurityException {
+        return getActiveAdminOrCheckPermissionForCallerLocked(
+                who, reqPolicy, parent, /* permission= */ null);
+    }
+
+    /**
+     * Finds an active admin for the caller then checks {@code permission} if admin check failed.
+     *
+     * @return an active admin or {@code null} if there is no active admin but
+     * {@code permission} is granted
+     * @throws SecurityException if caller neither has an active admin nor {@code permission}
+     */
+    @Nullable
+    ActiveAdmin getActiveAdminOrCheckPermissionForCallerLocked(
+            ComponentName who,
+            int reqPolicy,
+            boolean parent,
+            @Nullable String permission) throws SecurityException {
         ensureLocked();
         if (parent) {
             enforceManagedProfile(mInjector.userHandleGetCallingUserId(),
                     "call APIs on the parent profile");
         }
-        ActiveAdmin admin = getActiveAdminForCallerLocked(who, reqPolicy);
+        ActiveAdmin admin = getActiveAdminOrCheckPermissionForCallerLocked(
+                who, reqPolicy, permission);
         return parent ? admin.getParentActiveAdmin() : admin;
     }
+
     /**
      * Find the admin for the component and userId bit of the uid, then check
      * the admin's uid matches the uid.
@@ -4744,10 +4783,15 @@
                 preN = getTargetSdk(admin.info.getPackageName(),
                         userHandle) <= android.os.Build.VERSION_CODES.M;
             } else {
-                // Otherwise, make sure the caller has any active admin with the right policy.
-                admin = getActiveAdminForCallerLocked(null,
-                        DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
-                preN = getTargetSdk(admin.info.getPackageName(),
+                // Otherwise, make sure the caller has any active admin with the right policy or
+                // the required permission.
+                admin = getActiveAdminOrCheckPermissionForCallerLocked(
+                        null,
+                        DeviceAdminInfo.USES_POLICY_RESET_PASSWORD,
+                        android.Manifest.permission.RESET_PASSWORD);
+                // Cannot be preN if admin is null because an exception would have been
+                // thrown before getting here
+                preN = admin == null ? false : getTargetSdk(admin.info.getPackageName(),
                         userHandle) <= android.os.Build.VERSION_CODES.M;
 
                 // As of N, password resetting to empty/null is not allowed anymore.
@@ -4763,9 +4807,9 @@
                 // As of N, password cannot be changed by the admin if it is already set.
                 if (isLockScreenSecureUnchecked(userHandle)) {
                     if (!preN) {
-                        throw new SecurityException("Admin cannot change current password");
+                        throw new SecurityException("Cannot change current password");
                     } else {
-                        Slog.e(LOG_TAG, "Admin cannot change current password");
+                        Slog.e(LOG_TAG, "Cannot change current password");
                         return false;
                     }
                 }
@@ -5136,31 +5180,37 @@
 
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
-            // This API can only be called by an active device admin,
-            // so try to retrieve it to check that the caller is one.
-            final ActiveAdmin admin = getActiveAdminForCallerLocked(
-                    null, DeviceAdminInfo.USES_POLICY_FORCE_LOCK, parent);
-
+            // Make sure the caller has any active admin with the right policy or
+            // the required permission.
+            final ActiveAdmin admin = getActiveAdminOrCheckPermissionForCallerLocked(
+                    null,
+                    DeviceAdminInfo.USES_POLICY_FORCE_LOCK,
+                    parent,
+                    android.Manifest.permission.LOCK_DEVICE);
             final long ident = mInjector.binderClearCallingIdentity();
             try {
-                final ComponentName adminComponent = admin.info.getComponent();
-                // Evict key
-                if ((flags & DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY) != 0) {
-                    enforceManagedProfile(
-                            callingUserId, "set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY");
-                    if (!isProfileOwner(adminComponent, callingUserId)) {
-                        throw new SecurityException("Only profile owner admins can set "
-                                + "FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY");
+                final ComponentName adminComponent = admin == null ?
+                        null : admin.info.getComponent();
+                if (adminComponent != null) {
+                    // For Profile Owners only, callers with only permission not allowed.
+                    if ((flags & DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY) != 0) {
+                        // Evict key
+                        enforceManagedProfile(
+                                callingUserId, "set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY");
+                        if (!isProfileOwner(adminComponent, callingUserId)) {
+                            throw new SecurityException("Only profile owner admins can set "
+                                    + "FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY");
+                        }
+                        if (parent) {
+                            throw new IllegalArgumentException(
+                                    "Cannot set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY for the parent");
+                        }
+                        if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
+                            throw new UnsupportedOperationException(
+                                    "FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY only applies to FBE devices");
+                        }
+                        mUserManager.evictCredentialEncryptionKey(callingUserId);
                     }
-                    if (parent) {
-                        throw new IllegalArgumentException(
-                                "Cannot set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY for the parent");
-                    }
-                    if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
-                        throw new UnsupportedOperationException(
-                                "FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY only applies to FBE devices");
-                    }
-                    mUserManager.evictCredentialEncryptionKey(callingUserId);
                 }
 
                 // Lock all users unless this is a managed profile with a separate challenge
@@ -5179,7 +5229,7 @@
                     mInjector.getTrustManager().setDeviceLockedForUser(userToLock, true);
                 }
 
-                if (SecurityLog.isLoggingEnabled()) {
+                if (SecurityLog.isLoggingEnabled() && adminComponent != null) {
                     final int affectedUserId =
                             parent ? getProfileParentId(callingUserId) : callingUserId;
                     SecurityLog.writeEvent(SecurityLog.TAG_REMOTE_LOCK,
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 2338744..f6e5601 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -69,7 +69,6 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityRecordTests extends ActivityTestsBase {
-    private ActivityTaskManagerService mService;
     private TestActivityStack mStack;
     private TaskRecord mTask;
     private ActivityRecord mActivity;
@@ -79,10 +78,10 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityTaskManagerService();
-        mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+        setupActivityTaskManagerService();
+        mStack = mSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
+        mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
         mActivity = new ActivityBuilder(mService).setTask(mTask).build();
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 1aa80c8..0345a81 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -64,8 +64,6 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStackSupervisorTests extends ActivityTestsBase {
-    private ActivityTaskManagerService mService;
-    private ActivityStackSupervisor mSupervisor;
     private ActivityStack mFullscreenStack;
 
     @Before
@@ -73,8 +71,7 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityTaskManagerService();
-        mSupervisor = mService.mStackSupervisor;
+        setupActivityTaskManagerService();
         mFullscreenStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
     }
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 95f8fd1..ab814ee 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -60,8 +60,6 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStackTests extends ActivityTestsBase {
-    private ActivityTaskManagerService mService;
-    private ActivityStackSupervisor mSupervisor;
     private ActivityDisplay mDefaultDisplay;
     private ActivityStack mStack;
     private TaskRecord mTask;
@@ -71,9 +69,8 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityTaskManagerService();
-        mSupervisor = mService.mStackSupervisor;
-        mDefaultDisplay = mService.mStackSupervisor.getDefaultDisplay();
+        setupActivityTaskManagerService();
+        mDefaultDisplay = mSupervisor.getDefaultDisplay();
         mStack = mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
         mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index d032eb5..749403e 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -32,26 +32,32 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
+import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
 
+import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
 import static com.android.server.am.ActivityManagerService.ANIMATE;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyObject;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityOptions;
 import android.app.IApplicationThread;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.WindowLayout;
@@ -65,28 +71,6 @@
 import android.service.voice.IVoiceInteractionSession;
 import android.view.Gravity;
 
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
-import static com.android.server.am.ActivityManagerService.ANIMATE;
-import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyObject;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.times;
-
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -106,7 +90,6 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStarterTests extends ActivityTestsBase {
-    private ActivityTaskManagerService mService;
     private ActivityStarter mStarter;
     private ActivityStartController mController;
     private ActivityMetricsLogger mActivityMetricsLogger;
@@ -130,7 +113,7 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mService = createActivityTaskManagerService();
+        setupActivityTaskManagerService();
         mController = mock(ActivityStartController.class);
         mActivityMetricsLogger = mock(ActivityMetricsLogger.class);
         clearInvocations(mActivityMetricsLogger);
@@ -323,7 +306,22 @@
         }
     }
 
-    private ActivityStarter prepareStarter(int launchFlags) {
+    private ActivityStarter prepareStarter(@Intent.Flags int launchFlags) {
+        return prepareStarter(launchFlags, true /* mockGetLaunchStack */);
+    }
+
+    /**
+     * Creates a {@link ActivityStarter} with default parameters and necessary mocks.
+     *
+     * @param launchFlags The intent flags to launch activity.
+     * @param mockGetLaunchStack Whether to mock {@link ActivityStackSupervisor#getLaunchStack} for
+     *                           always launching to the testing stack. Set to false when allowing
+     *                           the activity can be launched to any stack that is decided by real
+     *                           implementation.
+     * @return A {@link ActivityStarter} with default setup.
+     */
+    private ActivityStarter prepareStarter(@Intent.Flags int launchFlags,
+            boolean mockGetLaunchStack) {
         // always allow test to start activity.
         doReturn(true).when(mService.mStackSupervisor).checkStartAnyActivityPermission(
                 any(), any(), any(), anyInt(), anyInt(), anyInt(), any(),
@@ -343,11 +341,13 @@
         // return task when created.
         doReturn(task).when(factory).create(any(), anyInt(), any(), any(), any(), any());
 
-        // direct starter to use spy stack.
-        doReturn(stack).when(mService.mStackSupervisor)
-                .getLaunchStack(any(), any(), any(), anyBoolean());
-        doReturn(stack).when(mService.mStackSupervisor)
-                .getLaunchStack(any(), any(), any(), anyBoolean(), anyInt());
+        if (mockGetLaunchStack) {
+            // Direct starter to use spy stack.
+            doReturn(stack).when(mService.mStackSupervisor)
+                    .getLaunchStack(any(), any(), any(), anyBoolean());
+            doReturn(stack).when(mService.mStackSupervisor)
+                    .getLaunchStack(any(), any(), any(), anyBoolean(), anyInt());
+        }
 
         // Set up mock package manager internal and make sure no unmocked methods are called
         PackageManagerInternal mockPackageManager = mock(PackageManagerInternal.class,
@@ -546,4 +546,84 @@
                 eq(ActivityBuilder.getDefaultComponent().getPackageName()), anyInt(), anyBoolean(),
                 any(), eq(false));
     }
+
+    /**
+     * This test ensures that when starting an existing single task activity on secondary display
+     * which is not the top focused display, it should deliver new intent to the activity and not
+     * create a new stack.
+     */
+    @Test
+    public void testDeliverIntentToTopActivityOfNonTopDisplay() {
+        final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK,
+                false /* mockGetLaunchStack */);
+
+        // Create a secondary display at bottom.
+        final TestActivityDisplay secondaryDisplay = spy(addNewActivityDisplayAt(POSITION_BOTTOM));
+        final ActivityStack stack = secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+        // Create an activity record on the top of secondary display.
+        final ComponentName componentName = ComponentName.createRelative(
+                DEFAULT_COMPONENT_PACKAGE_NAME,
+                DEFAULT_COMPONENT_PACKAGE_NAME + ".ReusableActivity");
+        final TaskRecord taskRecord = new TaskBuilder(mSupervisor)
+                .setComponent(componentName)
+                .setStack(stack)
+                .build();
+        final ActivityRecord topActivityOnSecondaryDisplay = new ActivityBuilder(mService)
+                .setComponent(componentName)
+                .setLaunchMode(LAUNCH_SINGLE_TASK)
+                .setTask(taskRecord)
+                .build();
+
+        // Put an activity on default display as the top focused activity.
+        new ActivityBuilder(mService).setCreateTask(true).build();
+
+        // Start activity with the same intent as {@code topActivityOnSecondaryDisplay}
+        // on secondary display.
+        final ActivityOptions options = ActivityOptions.makeBasic()
+                .setLaunchDisplayId(secondaryDisplay.mDisplayId);
+        final int result = starter.setReason("testDeliverIntentToTopActivityOfNonTopDisplay")
+                .setIntent(topActivityOnSecondaryDisplay.intent)
+                .setActivityOptions(options.toBundle())
+                .execute();
+
+        // Ensure result is delivering intent to top.
+        assertEquals(START_DELIVERED_TO_TOP, result);
+
+        // Ensure secondary display only creates one stack.
+        verify(secondaryDisplay, times(1)).createStack(anyInt(), anyInt(), anyBoolean());
+    }
+
+    /**
+     * This test ensures that a reused top activity in the top focused stack is able to be
+     * reparented to another display.
+     */
+    @Test
+    public void testReparentTopFocusedActivityToSecondaryDisplay() {
+        final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK,
+                false /* mockGetLaunchStack */);
+
+        // Create a secondary display at bottom.
+        final TestActivityDisplay secondaryDisplay = addNewActivityDisplayAt(POSITION_BOTTOM);
+        secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+                true /* onTop */);
+
+        // Put an activity on default display as the top focused activity.
+        final ActivityRecord topActivity = new ActivityBuilder(mService)
+                .setCreateTask(true)
+                .setLaunchMode(LAUNCH_SINGLE_TASK)
+                .build();
+
+        // Start activity with the same intent as {@code topActivity} on secondary display.
+        final ActivityOptions options = ActivityOptions.makeBasic()
+                .setLaunchDisplayId(secondaryDisplay.mDisplayId);
+        starter.setReason("testReparentTopFocusedActivityToSecondaryDisplay")
+                .setIntent(topActivity.intent)
+                .setActivityOptions(options.toBundle())
+                .execute();
+
+        // Ensure the activity is moved to secondary display.
+        assertEquals(secondaryDisplay, topActivity.getDisplay());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index bb8e5c5..9d09f5c 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -22,6 +22,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
 
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
@@ -56,11 +57,14 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.UserHandle;
 import android.service.voice.IVoiceInteractionSession;
 import android.testing.DexmakerShareClassLoaderRule;
+import android.view.Display;
+import android.view.DisplayInfo;
 
 import androidx.test.InstrumentationRegistry;
 
@@ -86,6 +90,8 @@
 public class ActivityTestsBase {
     private static boolean sOneTimeSetupDone = false;
 
+    private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
+
     @Rule
     public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
             new DexmakerShareClassLoaderRule();
@@ -93,6 +99,9 @@
     private final Context mContext = InstrumentationRegistry.getContext();
     private HandlerThread mHandlerThread;
 
+    ActivityTaskManagerService mService;
+    ActivityStackSupervisor mSupervisor;
+
     // Default package name
     static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo";
 
@@ -122,6 +131,11 @@
         return atm;
     }
 
+    void setupActivityTaskManagerService() {
+        mService = createActivityTaskManagerService();
+        mSupervisor = mService.mStackSupervisor;
+    }
+
     ActivityManagerService createActivityManagerService() {
         final TestActivityTaskManagerService atm =
                 spy(new TestActivityTaskManagerService(mContext));
@@ -134,6 +148,18 @@
         return am;
     }
 
+    /** Creates a {@link TestActivityDisplay}. */
+    TestActivityDisplay createNewActivityDisplay() {
+        return TestActivityDisplay.create(mSupervisor, sNextDisplayId++);
+    }
+
+    /** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */
+    TestActivityDisplay addNewActivityDisplayAt(int position) {
+        final TestActivityDisplay display = createNewActivityDisplay();
+        mSupervisor.addChild(display, position);
+        return display;
+    }
+
     void setupActivityManagerService(
             TestActivityManagerService am, TestActivityTaskManagerService atm) {
         atm.setActivityManagerService(am);
@@ -173,6 +199,7 @@
         private boolean mCreateTask;
         private ActivityStack mStack;
         private int mActivityFlags;
+        private int mLaunchMode;
 
         ActivityBuilder(ActivityTaskManagerService service) {
             mService = service;
@@ -198,6 +225,11 @@
             return this;
         }
 
+        ActivityBuilder setLaunchMode(int launchMode) {
+            mLaunchMode = launchMode;
+            return this;
+        }
+
         ActivityBuilder setStack(ActivityStack stack) {
             mStack = stack;
             return this;
@@ -233,6 +265,7 @@
             aInfo.applicationInfo.packageName = mComponent.getPackageName();
             aInfo.applicationInfo.uid = mUid;
             aInfo.flags |= mActivityFlags;
+            aInfo.launchMode = mLaunchMode;
 
             final ActivityRecord activity = new ActivityRecord(mService, null /* caller */,
                     0 /* launchedFromPid */, 0, null, intent, null,
@@ -500,7 +533,7 @@
         @Override
         public void initialize() {
             super.initialize();
-            mDisplay = spy(new TestActivityDisplay(this, DEFAULT_DISPLAY));
+            mDisplay = spy(TestActivityDisplay.create(this, DEFAULT_DISPLAY));
             addChild(mDisplay, ActivityDisplay.POSITION_TOP);
         }
 
@@ -516,10 +549,20 @@
     }
 
     protected static class TestActivityDisplay extends ActivityDisplay {
-
         private final ActivityStackSupervisor mSupervisor;
-        TestActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
-            super(supervisor, displayId);
+
+        static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId) {
+            if (displayId == DEFAULT_DISPLAY) {
+                return new TestActivityDisplay(supervisor,
+                        supervisor.mDisplayManager.getDisplay(displayId));
+            }
+            final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
+                    new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
+            return new TestActivityDisplay(supervisor, display);
+        }
+
+        TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
+            super(supervisor, display);
             // Normally this comes from display-properties as exposed by WM. Without that, just
             // hard-code to FULLSCREEN for tests.
             setWindowingMode(WINDOWING_MODE_FULLSCREEN);
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 5195214..70cfad1 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -870,8 +870,8 @@
         @Override
         public void initialize() {
             super.initialize();
-            mDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
-            mOtherDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
+            mDisplay = TestActivityDisplay.create(this, DEFAULT_DISPLAY);
+            mOtherDisplay = TestActivityDisplay.create(this, DEFAULT_DISPLAY + 1);
             addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
             addChild(mDisplay, ActivityDisplay.POSITION_TOP);
         }
diff --git a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
index d56c6a6..aa3046f 100644
--- a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
@@ -51,7 +51,6 @@
 public class RunningTasksTest extends ActivityTestsBase {
 
     private Context mContext = InstrumentationRegistry.getContext();
-    private ActivityTaskManagerService mService;
 
     private RunningTasks mRunningTasks;
 
@@ -60,21 +59,20 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityTaskManagerService();
+        setupActivityTaskManagerService();
         mRunningTasks = new RunningTasks();
     }
 
     @Test
     public void testCollectTasksByLastActiveTime() throws Exception {
         // Create a number of stacks with tasks (of incrementing active time)
-        final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
         final ArrayList<ActivityDisplay> displays = new ArrayList<>();
-        final ActivityDisplay display = new TestActivityDisplay(supervisor, DEFAULT_DISPLAY);
+        final ActivityDisplay display = TestActivityDisplay.create(mSupervisor, DEFAULT_DISPLAY);
         displays.add(display);
 
         final int numStacks = 2;
         for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
-            final ActivityStack stack = new TestActivityStack(display, stackIndex, supervisor,
+            final ActivityStack stack = new TestActivityStack(display, stackIndex, mSupervisor,
                     WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true);
             display.addChild(stack, POSITION_BOTTOM);
         }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 519b3ae..4344285 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -519,8 +519,9 @@
         NotificationChannel channel = new NotificationChannel("id", "name",
                 IMPORTANCE_HIGH);
         NotificationRecord r = generateNotificationRecord(channel);
-        assertTrue(mService.isBlocked(r, mUsageStats));
-        verify(mUsageStats, times(1)).registerSuspendedByAdmin(eq(r));
+
+        // isBlocked is only used for user blocking, not app suspension
+        assertFalse(mService.isBlocked(r, mUsageStats));
     }
 
     @Test
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ffbe7d3..61c38fb 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1070,6 +1070,16 @@
 
     /**
      * Indexes of SPN format strings in wfcSpnFormats and wfcDataSpnFormats.
+     *
+     * <p>Available options are:
+     * <ul>
+     * <li> 0: %s</li>
+     * <li> 1: %s Wi-Fi Calling</li>
+     * <li> 2: WLAN Call</li>
+     * <li> 3: %s WLAN Call</li>
+     * <li> 4: %s Wi-Fi</li>
+     * <li> 5: WiFi Calling | %s</li>
+     * <li> 6: %s VoWifi</li>
      * @hide
      */
     public static final String KEY_WFC_SPN_FORMAT_IDX_INT = "wfc_spn_format_idx_int";
@@ -2272,7 +2282,7 @@
         sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL, false);
         sDefaults.putBoolean(KEY_SKIP_CF_FAIL_TO_DISABLE_DIALOG_BOOL, false);
-        sDefaults.putBoolean(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, false);
+        sDefaults.putBoolean(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, true);
 
         // MMS defaults
         sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index 6bf22a0..8015b07 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -33,6 +33,7 @@
 import com.android.internal.telephony.SmsConstants;
 
 import java.io.UnsupportedEncodingException;
+import java.util.Locale;
 
 /**
  * Parses a GSM or UMTS format SMS-CB message into an {@link SmsCbMessage} object. The class is
@@ -44,16 +45,34 @@
      * Languages in the 0000xxxx DCS group as defined in 3GPP TS 23.038, section 5.
      */
     private static final String[] LANGUAGE_CODES_GROUP_0 = {
-            "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi", "no", "el", "tr", "hu",
-            "pl", null
+            Locale.GERMAN.getLanguage(),        // German
+            Locale.ENGLISH.getLanguage(),       // English
+            Locale.ITALIAN.getLanguage(),       // Italian
+            Locale.FRENCH.getLanguage(),        // French
+            new Locale("es").getLanguage(),     // Spanish
+            new Locale("nl").getLanguage(),     // Dutch
+            new Locale("sv").getLanguage(),     // Swedish
+            new Locale("da").getLanguage(),     // Danish
+            new Locale("pt").getLanguage(),     // Portuguese
+            new Locale("fi").getLanguage(),     // Finnish
+            new Locale("nb").getLanguage(),     // Norwegian
+            new Locale("el").getLanguage(),     // Greek
+            new Locale("tr").getLanguage(),     // Turkish
+            new Locale("hu").getLanguage(),     // Hungarian
+            new Locale("pl").getLanguage(),     // Polish
+            null
     };
 
     /**
      * Languages in the 0010xxxx DCS group as defined in 3GPP TS 23.038, section 5.
      */
     private static final String[] LANGUAGE_CODES_GROUP_2 = {
-            "cs", "he", "ar", "ru", "is", null, null, null, null, null, null, null, null, null,
-            null, null
+            new Locale("cs").getLanguage(),     // Czech
+            new Locale("he").getLanguage(),     // Hebrew
+            new Locale("ar").getLanguage(),     // Arabic
+            new Locale("ru").getLanguage(),     // Russian
+            new Locale("is").getLanguage(),     // Icelandic
+            null, null, null, null, null, null, null, null, null, null, null
     };
 
     private static final char CARRIAGE_RETURN = 0x0d;
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
index 1b63874..6500428 100644
--- a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Cujs.java
@@ -16,24 +16,27 @@
 
 package com.android.tests.sysmem.host;
 
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-
 /**
  * Critical user journeys with which to exercise the system, driven from the
  * host.
  */
 public class Cujs {
-    private ITestDevice mDevice;
+    private Device mDevice;
 
-    public Cujs(ITestDevice device) {
+    public Cujs(Device device) {
         this.mDevice = device;
     }
 
     /**
      * Runs the critical user journeys.
      */
-    public void run() throws DeviceNotAvailableException {
+    public void run() throws TestException {
+        // Do an explicit GC in the system server process as part of the test
+        // case to reduce GC-related sources of noise.
+        // SIGUSR1 = 10 is the magic signal to trigger the GC.
+        int pid = mDevice.getPidForProcess("system_server");
+        mDevice.executeShellCommand("kill -10 " + pid);
+
         // Invoke the Device Cujs instrumentation to run the cujs.
         // TODO: Consider exercising the system in other interesting ways as
         // well.
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Device.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Device.java
new file mode 100644
index 0000000..03503ce
--- /dev/null
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Device.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.sysmem.host;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+
+import java.util.InputMismatchException;
+import java.util.Scanner;
+
+/**
+ * Wrapper around ITestDevice exposing useful device functions.
+ */
+class Device {
+
+    private ITestDevice mDevice;
+
+    Device(ITestDevice device) {
+        mDevice = device;
+    }
+
+    /**
+     * Execute a shell command and return the output as a string.
+     */
+    public String executeShellCommand(String command) throws TestException {
+        try {
+            return mDevice.executeShellCommand(command);
+        } catch (DeviceNotAvailableException e) {
+            throw new TestException(e);
+        }
+    }
+
+    /**
+     * Enable adb root
+     */
+    public void enableAdbRoot() throws TestException {
+        try {
+            mDevice.enableAdbRoot();
+        } catch (DeviceNotAvailableException e) {
+            throw new TestException(e);
+        }
+    }
+
+    /**
+     * Returns the pid for the process with the given name.
+     */
+    public int getPidForProcess(String name) throws TestException {
+        String psout = executeShellCommand("ps -A -o PID,CMD");
+        Scanner sc = new Scanner(psout);
+        try {
+            // ps output is of the form:
+            //  PID CMD
+            //    1 init
+            //    2 kthreadd
+            //    ...
+            // 9693 ps
+            sc.nextLine();
+            while (sc.hasNextLine()) {
+                int pid = sc.nextInt();
+                String cmd = sc.next();
+
+                if (name.equals(cmd)) {
+                    return pid;
+                }
+            }
+        } catch (InputMismatchException e) {
+            throw new TestException("unexpected ps output format: " + psout, e);
+        }
+
+        throw new TestException("failed to get pid for process " + name);
+    }
+}
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java
index cfd598d..48b7f39 100644
--- a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/MemoryTest.java
@@ -16,7 +16,6 @@
 
 package com.android.tests.sysmem.host;
 
-import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData;
@@ -27,8 +26,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.io.IOException;
-
 /**
  * Runs a system memory test.
  */
@@ -44,8 +41,9 @@
     private Cujs mCujs;
 
     @Override
-    public void setDevice(ITestDevice device) {
-        mTestDevice = device;
+    public void setDevice(ITestDevice testDevice) {
+        mTestDevice = testDevice;
+        Device device = new Device(testDevice);
         mMetrics = new Metrics(device, testMetrics, testLogs);
         mCujs = new Cujs(device);
     }
@@ -56,14 +54,13 @@
     }
 
     // Invoke a single iteration of running the cujs.
-    private void runCujs() throws DeviceNotAvailableException {
+    private void runCujs() throws TestException {
         mCujs.run();
         mIterations++;
     }
 
     // Sample desired memory.
-    private void sample()
-            throws DeviceNotAvailableException, IOException, Metrics.MetricsException {
+    private void sample() throws TestException {
         mMetrics.sample(String.format("%03d", mIterations));
     }
 
@@ -71,7 +68,7 @@
      * Runs the memory tests.
      */
     @Test
-    public void run() throws Exception {
+    public void run() throws TestException {
         sample();   // Sample before running cujs
         runCujs();
         sample();   // Sample after first iteration of cujs
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
index 70bc22c..b408a81 100644
--- a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/Metrics.java
@@ -16,8 +16,6 @@
 
 package com.android.tests.sysmem.host;
 
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.result.FileInputStreamSource;
 import com.android.tradefed.result.LogDataType;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData;
@@ -34,24 +32,11 @@
  */
 class Metrics {
 
-    private ITestDevice mDevice;
+    private Device mDevice;
     private TestMetrics mMetrics;
     private TestLogData mLogs;
 
     /**
-     * Exception thrown in case of error sampling metrics.
-     */
-    public static class MetricsException extends Exception {
-        MetricsException(String msg) {
-            super(msg);
-        }
-
-        MetricsException(String msg, Exception cause) {
-            super(msg, cause);
-        }
-    }
-
-    /**
      * Constructs a metrics instance that will output high level metrics and
      * more detailed breakdowns using the given <code>metrics</code> and
      * <code>logs</code> objects.
@@ -60,7 +45,7 @@
      * @param metrics where to log the high level metrics when taking a sample
      * @param logs where to log detailed breakdowns when taking a sample
      */
-    Metrics(ITestDevice device, TestMetrics metrics, TestLogData logs) {
+    Metrics(Device device, TestMetrics metrics, TestLogData logs) {
         this.mDevice = device;
         this.mMetrics = metrics;
         this.mLogs = logs;
@@ -69,43 +54,17 @@
     /**
      * Writes the given <code>text</code> to a log with the given label.
      */
-    private void logText(String label, String text) throws IOException {
-        File file = File.createTempFile(label, "txt");
-        PrintStream ps = new PrintStream(file);
-        ps.print(text);
-        try (FileInputStreamSource dataStream = new FileInputStreamSource(file)) {
-            mLogs.addTestLog(label, LogDataType.TEXT, dataStream);
-        }
-    }
-
-    /**
-     * Returns the pid for the process with the given name.
-     */
-    private int getPidForProcess(String name)
-            throws DeviceNotAvailableException, IOException, MetricsException {
-        String psout = mDevice.executeShellCommand("ps -A -o PID,CMD");
-        Scanner sc = new Scanner(psout);
+    private void logText(String label, String text) throws TestException {
         try {
-            // ps output is of the form:
-            //  PID CMD
-            //    1 init
-            //    2 kthreadd
-            //    ...
-            // 9693 ps
-            sc.nextLine();
-            while (sc.hasNextLine()) {
-                int pid = sc.nextInt();
-                String cmd = sc.next();
-
-                if (name.equals(cmd)) {
-                    return pid;
-                }
+            File file = File.createTempFile(label, "txt");
+            PrintStream ps = new PrintStream(file);
+            ps.print(text);
+            try (FileInputStreamSource dataStream = new FileInputStreamSource(file)) {
+                mLogs.addTestLog(label, LogDataType.TEXT, dataStream);
             }
-        } catch (InputMismatchException e) {
-            throw new MetricsException("unexpected ps output format: " + psout, e);
+        } catch (IOException e) {
+            throw new TestException(e);
         }
-
-        throw new MetricsException("failed to get pid for process " + name);
     }
 
     /**
@@ -116,11 +75,11 @@
      *
      * @param label prefix to use for metrics and logs output for this sample.
      */
-    void sample(String label) throws DeviceNotAvailableException, IOException, MetricsException {
+    void sample(String label) throws TestException {
         // adb root access is required to get showmap
         mDevice.enableAdbRoot();
 
-        int pid = getPidForProcess("system_server");
+        int pid = mDevice.getPidForProcess("system_server");
 
         // Read showmap for system server and add it as a test log
         String showmap = mDevice.executeShellCommand("showmap " + pid);
@@ -146,7 +105,7 @@
             mMetrics.addTestMetric(label + ".system_server.rss", Long.toString(rss));
             mMetrics.addTestMetric(label + ".system_server.pss", Long.toString(pss));
         } catch (InputMismatchException e) {
-            throw new MetricsException("unexpected showmap format", e);
+            throw new TestException("unexpected showmap format", e);
         }
 
         // Run debuggerd -j to get GC stats for system server and add it as a
diff --git a/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/TestException.java b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/TestException.java
new file mode 100644
index 0000000..dc3b68f
--- /dev/null
+++ b/tests/SystemMemoryTest/host/src/com/android/tests/sysmem/host/TestException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.sysmem.host;
+
+/**
+ * Exception thrown in case of unexpected error encountered when executing the
+ * test.
+ */
+class TestException extends Exception {
+    TestException(Exception cause) {
+        super(cause);
+    }
+
+    TestException(String msg) {
+        super(msg);
+    }
+
+    TestException(String msg, Exception cause) {
+        super(msg, cause);
+    }
+}
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 119f56a..13c1047 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -1842,9 +1842,15 @@
     } else {
       // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or
       // equal to the minSdk.
+      const size_t origConstraintSize = options_.split_constraints.size();
       options_.split_constraints =
           AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints);
 
+      if (origConstraintSize != options_.split_constraints.size()) {
+        context_->GetDiagnostics()->Warn(DiagMessage()
+                                         << "requested to split resources prior to min sdk of "
+                                         << context_->GetMinSdkVersion());
+      }
       TableSplitter table_splitter(options_.split_constraints, options_.table_splitter_options);
       if (!table_splitter.VerifySplitConstraints(context_)) {
         return 1;
diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp
index c6c82b0..5862d31 100644
--- a/tools/aapt2/cmd/Util.cpp
+++ b/tools/aapt2/cmd/Util.cpp
@@ -73,6 +73,7 @@
   }
 
   *out_path = parts[0];
+  out_split->name = parts[1];
   for (const StringPiece& config_str : util::Tokenize(parts[1], ',')) {
     ConfigDescription config;
     if (!ConfigDescription::Parse(config_str, &config)) {
@@ -119,12 +120,15 @@
   for (const SplitConstraints& constraints : split_constraints) {
     SplitConstraints constraint;
     for (const ConfigDescription& config : constraints.configs) {
-      if (config.sdkVersion <= min_sdk) {
-        constraint.configs.insert(config.CopyWithoutSdkVersion());
-      } else {
-        constraint.configs.insert(config);
+      const ConfigDescription &configToInsert = (config.sdkVersion <= min_sdk)
+          ? config.CopyWithoutSdkVersion()
+          : config;
+      // only add the config if it actually selects something
+      if (configToInsert != ConfigDescription::DefaultConfig()) {
+        constraint.configs.insert(configToInsert);
       }
     }
+    constraint.name = constraints.name;
     adjusted_constraints.push_back(std::move(constraint));
   }
   return adjusted_constraints;
diff --git a/tools/aapt2/cmd/Util_test.cpp b/tools/aapt2/cmd/Util_test.cpp
index b9fb5b2..158ef29 100644
--- a/tools/aapt2/cmd/Util_test.cpp
+++ b/tools/aapt2/cmd/Util_test.cpp
@@ -22,6 +22,10 @@
 #include "test/Test.h"
 
 namespace aapt {
+#define EXPECT_CONFIG_EQ(constraints, config) \
+    EXPECT_EQ(constraints.configs.size(), 1); \
+    EXPECT_EQ(*constraints.configs.begin(), config); \
+    constraints.configs.clear();
 
 TEST(UtilTest, SplitNamesAreSanitized) {
     AppInfo app_info{"com.pkg"};
@@ -84,4 +88,287 @@
   EXPECT_EQ(compiled_version_code_major->value.data, 0x61);
 }
 
+
+TEST (UtilTest, ParseSplitParameter) {
+  IDiagnostics* diagnostics = test::ContextBuilder().Build().get()->GetDiagnostics();
+  std::string path;
+  SplitConstraints constraints;
+  ConfigDescription expected_configuration;
+
+  // ========== Test IMSI ==========
+  // mcc: 'mcc[0-9]{3}'
+  // mnc: 'mnc[0-9]{1,3}'
+  ASSERT_TRUE(ParseSplitParameter(":mcc310",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setMcc(0x0136)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":mcc310-mnc004",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setMcc(0x0136)
+      .setMnc(0x0004)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":mcc310-mnc000",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setMcc(0x0136)
+      .setMnc(0xFFFF)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  // ========== Test LOCALE ==========
+  // locale: '[a-z]{2,3}(-r[a-z]{2})?'
+  // locale: 'b+[a-z]{2,3}(+[a-z[0-9]]{2})?'
+  ASSERT_TRUE(ParseSplitParameter(":es",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setLanguage(0x6573)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":fr-rCA",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setLanguage(0x6672)
+      .setCountry(0x4341)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":b+es+419",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setLanguage(0x6573)
+      .setCountry(0xA424)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  // ========== Test SCREEN_TYPE ==========
+  // orientation: '(port|land|square)'
+  // touchscreen: '(notouch|stylus|finger)'
+  // density" '(anydpi|nodpi|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|[0-9]*dpi)'
+  ASSERT_TRUE(ParseSplitParameter(":square",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setOrientation(0x03)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":stylus",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setTouchscreen(0x02)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":xxxhdpi",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setDensity(0x0280)
+      .setSdkVersion(0x0004) // version [any density requires donut]
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":land-xhdpi-finger",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setOrientation(0x02)
+      .setTouchscreen(0x03)
+      .setDensity(0x0140)
+      .setSdkVersion(0x0004) // version [any density requires donut]
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  // ========== Test INPUT ==========
+  // keyboard: '(nokeys|qwerty|12key)'
+  // navigation: '(nonav|dpad|trackball|wheel)'
+  // inputFlags: '(keysexposed|keyshidden|keyssoft)'
+  // inputFlags: '(navexposed|navhidden)'
+  ASSERT_TRUE(ParseSplitParameter(":qwerty",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setKeyboard(0x02)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":dpad",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setNavigation(0x02)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":keyssoft-navhidden",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setInputFlags(0x0B)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":keyshidden-nokeys-navexposed-trackball",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setKeyboard(0x01)
+      .setNavigation(0x03)
+      .setInputFlags(0x06)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  // ========== Test SCREEN_SIZE ==========
+  // screenWidth/screenHeight: '[0-9]+x[0-9]+'
+  ASSERT_TRUE(ParseSplitParameter(":1920x1080",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setScreenWidth(0x0780)
+      .setScreenHeight(0x0438)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  // ========== Test VERSION ==========
+  // version 'v[0-9]+'
+
+  // ========== Test SCREEN_CONFIG ==========
+  // screenLayout [direction]: '(ldltr|ldrtl)'
+  // screenLayout [size]: '(small|normal|large|xlarge)'
+  // screenLayout [long]: '(long|notlong)'
+  // uiMode [type]: '(desk|car|television|appliance|watch|vrheadset)'
+  // uiMode [night]: '(night|notnight)'
+  // smallestScreenWidthDp: 'sw[0-9]dp'
+  ASSERT_TRUE(ParseSplitParameter(":ldrtl",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setScreenLayout(0x80)
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":small",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setScreenLayout(0x01)
+      .setSdkVersion(0x0004) // screenLayout (size) requires donut
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":notlong",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setScreenLayout(0x10)
+      .setSdkVersion(0x0004) // screenLayout (long) requires donut
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":ldltr-normal-long",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setScreenLayout(0x62)
+      .setSdkVersion(0x0004) // screenLayout (size|long) requires donut
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":car",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setUiMode(0x03)
+      .setSdkVersion(0x0008) // uiMode requires froyo
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":vrheadset",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setUiMode(0x07)
+      .setSdkVersion(0x001A) // uiMode 'vrheadset' requires oreo
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":television-night",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setUiMode(0x24)
+      .setSdkVersion(0x0008) // uiMode requires froyo
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":sw1920dp",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setSmallestScreenWidthDp(0x0780)
+      .setSdkVersion(0x000D) // smallestScreenWidthDp requires honeycomb mr2
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  // ========== Test SCREEN_SIZE_DP ==========
+  // screenWidthDp: 'w[0-9]dp'
+  // screenHeightDp: 'h[0-9]dp'
+  ASSERT_TRUE(ParseSplitParameter(":w1920dp",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setScreenWidthDp(0x0780)
+      .setSdkVersion(0x000D) // screenWidthDp requires honeycomb mr2
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":h1080dp",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setScreenHeightDp(0x0438)
+      .setSdkVersion(0x000D) // screenHeightDp requires honeycomb mr2
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  // ========== Test SCREEN_CONFIG_2 ==========
+  // screenLayout2: '(round|notround)'
+  // colorMode: '(widecg|nowidecg)'
+  // colorMode: '(highhdr|lowdr)'
+  ASSERT_TRUE(ParseSplitParameter(":round",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setScreenLayout2(0x02)
+      .setSdkVersion(0x0017) // screenLayout2 (round) requires marshmallow
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+
+  ASSERT_TRUE(ParseSplitParameter(":widecg-highdr",
+                                  diagnostics, &path, &constraints));
+  expected_configuration = test::ConfigDescriptionBuilder()
+      .setColorMode(0x0A)
+      .setSdkVersion(0x001A) // colorMode (hdr|colour gamut) requires oreo
+      .Build();
+  EXPECT_CONFIG_EQ(constraints, expected_configuration);
+}
+
+TEST (UtilTest, AdjustSplitConstraintsForMinSdk) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+
+  IDiagnostics* diagnostics = context.get()->GetDiagnostics();
+  std::vector<SplitConstraints> test_constraints;
+  std::string path;
+
+  test_constraints.push_back({});
+  ASSERT_TRUE(ParseSplitParameter(":v7",
+                                  diagnostics, &path, &test_constraints.back()));
+  test_constraints.push_back({});
+  ASSERT_TRUE(ParseSplitParameter(":xhdpi",
+                                  diagnostics, &path, &test_constraints.back()));
+  EXPECT_EQ(test_constraints.size(), 2);
+  EXPECT_EQ(test_constraints[0].name, "v7");
+  EXPECT_EQ(test_constraints[0].configs.size(), 1);
+  EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());
+  EXPECT_EQ(test_constraints[1].name, "xhdpi");
+  EXPECT_EQ(test_constraints[1].configs.size(), 1);
+  EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());
+
+  auto adjusted_contraints = AdjustSplitConstraintsForMinSdk(26, test_constraints);
+  EXPECT_EQ(adjusted_contraints.size(), 2);
+  EXPECT_EQ(adjusted_contraints[0].name, "v7");
+  EXPECT_EQ(adjusted_contraints[0].configs.size(), 0);
+  EXPECT_EQ(adjusted_contraints[1].name, "xhdpi");
+  EXPECT_EQ(adjusted_contraints[1].configs.size(), 1);
+  EXPECT_NE(*adjusted_contraints[1].configs.begin(), ConfigDescription::DefaultConfig());
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index e991743..b5c33062 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -154,6 +154,12 @@
 bool TableSplitter::VerifySplitConstraints(IAaptContext* context) {
   bool error = false;
   for (size_t i = 0; i < split_constraints_.size(); i++) {
+    if (split_constraints_[i].configs.size() == 0) {
+      // For now, treat this as a warning. We may consider aborting processing.
+      context->GetDiagnostics()->Warn(DiagMessage()
+                                       << "no configurations for constraint '"
+                                       << split_constraints_[i].name << "'");
+    }
     for (size_t j = i + 1; j < split_constraints_.size(); j++) {
       for (const ConfigDescription& config : split_constraints_[i].configs) {
         if (split_constraints_[j].configs.find(config) != split_constraints_[j].configs.end()) {
diff --git a/tools/aapt2/split/TableSplitter.h b/tools/aapt2/split/TableSplitter.h
index 6aec257..ed24bc39 100644
--- a/tools/aapt2/split/TableSplitter.h
+++ b/tools/aapt2/split/TableSplitter.h
@@ -30,6 +30,7 @@
 
 struct SplitConstraints {
   std::set<ConfigDescription> configs;
+  std::string name;
 };
 
 struct TableSplitterOptions {
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index fd5262a..be6e510 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -204,6 +204,112 @@
   configuration::PostProcessingConfiguration config_;
 };
 
+class ConfigDescriptionBuilder {
+ public:
+  ConfigDescriptionBuilder() = default;
+
+  ConfigDescriptionBuilder& setMcc(uint16_t mcc) {
+    config_.mcc = mcc;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setMnc(uint16_t mnc) {
+    config_.mnc = mnc;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setLanguage(uint16_t language) {
+    config_.language[0] = language >> 8;
+    config_.language[1] = language & 0xff;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setCountry(uint16_t country) {
+    config_.country[0] = country >> 8;
+    config_.country[1] = country & 0xff;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setOrientation(uint8_t orientation) {
+    config_.orientation = orientation;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setTouchscreen(uint8_t touchscreen) {
+    config_.touchscreen = touchscreen;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setDensity(uint16_t density) {
+    config_.density = density;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setKeyboard(uint8_t keyboard) {
+    config_.keyboard = keyboard;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setNavigation(uint8_t navigation) {
+    config_.navigation = navigation;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setInputFlags(uint8_t inputFlags) {
+    config_.inputFlags = inputFlags;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setInputPad0(uint8_t inputPad0) {
+    config_.inputPad0 = inputPad0;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setScreenWidth(uint16_t screenWidth) {
+    config_.screenWidth = screenWidth;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setScreenHeight(uint16_t screenHeight) {
+    config_.screenHeight = screenHeight;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setSdkVersion(uint16_t sdkVersion) {
+    config_.sdkVersion = sdkVersion;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setMinorVersion(uint16_t minorVersion) {
+    config_.minorVersion = minorVersion;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setScreenLayout(uint8_t screenLayout) {
+    config_.screenLayout = screenLayout;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setUiMode(uint8_t uiMode) {
+    config_.uiMode = uiMode;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setSmallestScreenWidthDp(uint16_t smallestScreenWidthDp) {
+    config_.smallestScreenWidthDp = smallestScreenWidthDp;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setScreenWidthDp(uint16_t screenWidthDp) {
+    config_.screenWidthDp = screenWidthDp;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setScreenHeightDp(uint16_t screenHeightDp) {
+    config_.screenHeightDp = screenHeightDp;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setScreenLayout2(uint8_t screenLayout2) {
+    config_.screenLayout2 = screenLayout2;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setColorMode(uint8_t colorMode) {
+    config_.colorMode = colorMode;
+    return *this;
+  }
+  ConfigDescriptionBuilder& setScreenConfigPad2(uint16_t screenConfigPad2) {
+    config_.screenConfigPad2 = screenConfigPad2;
+    return *this;
+  }
+  ConfigDescription Build() {
+    return config_;
+  }
+
+ private:
+  ConfigDescription config_;
+};
+
 }  // namespace test
 }  // namespace aapt