Merge "Add setupDialog method to ZenDurationDialog"
diff --git a/Android.bp b/Android.bp
index 6815a0d..29b6bc7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1173,6 +1173,8 @@
     srcs_lib_whitelist_dirs: frameworks_base_subdirs,
     srcs_lib_whitelist_pkgs: packages_to_document,
     libs: [
+        "conscrypt",
+        "bouncycastle",
         "voip-common",
         "android.test.mock",
         "android-support-annotations",
@@ -1569,7 +1571,7 @@
     metalava_annotations_enabled: true,
     metalava_previous_api: ":public-api-for-metalava-annotations",
     metalava_merge_annotations_dirs: [
-        "tools/metalava/manual",
+        "metalava-manual",
     ],
 }
 
diff --git a/api/current.txt b/api/current.txt
index c236186..b18b917 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35621,11 +35621,11 @@
 
   protected static abstract interface ContactsContract.ContactOptionsColumns {
     field public static final java.lang.String CUSTOM_RINGTONE = "custom_ringtone";
-    field public static final java.lang.String LAST_TIME_CONTACTED = "last_time_contacted";
+    field public static final deprecated java.lang.String LAST_TIME_CONTACTED = "last_time_contacted";
     field public static final java.lang.String PINNED = "pinned";
     field public static final java.lang.String SEND_TO_VOICEMAIL = "send_to_voicemail";
     field public static final java.lang.String STARRED = "starred";
-    field public static final java.lang.String TIMES_CONTACTED = "times_contacted";
+    field public static final deprecated java.lang.String TIMES_CONTACTED = "times_contacted";
   }
 
   protected static abstract interface ContactsContract.ContactStatusColumns {
@@ -35647,7 +35647,7 @@
     method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri, boolean);
     method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri);
     field public static final android.net.Uri CONTENT_FILTER_URI;
-    field public static final android.net.Uri CONTENT_FREQUENT_URI;
+    field public static final deprecated android.net.Uri CONTENT_FREQUENT_URI;
     field public static final android.net.Uri CONTENT_GROUP_URI;
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact";
     field public static final android.net.Uri CONTENT_LOOKUP_URI;
@@ -35755,7 +35755,7 @@
   protected static abstract interface ContactsContract.DataColumnsWithJoins implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.DataUsageStatColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns {
   }
 
-  public static final class ContactsContract.DataUsageFeedback {
+  public static final deprecated class ContactsContract.DataUsageFeedback {
     ctor public ContactsContract.DataUsageFeedback();
     field public static final android.net.Uri DELETE_USAGE_URI;
     field public static final android.net.Uri FEEDBACK_URI;
@@ -35766,8 +35766,8 @@
   }
 
   protected static abstract interface ContactsContract.DataUsageStatColumns {
-    field public static final java.lang.String LAST_TIME_USED = "last_time_used";
-    field public static final java.lang.String TIMES_USED = "times_used";
+    field public static final deprecated java.lang.String LAST_TIME_USED = "last_time_used";
+    field public static final deprecated java.lang.String TIMES_USED = "times_used";
   }
 
   public static final class ContactsContract.DeletedContacts implements android.provider.ContactsContract.DeletedContactsColumns {
diff --git a/cmds/incident_helper/src/ih_util.cpp b/cmds/incident_helper/src/ih_util.cpp
index 4c4d1b9..012310c 100644
--- a/cmds/incident_helper/src/ih_util.cpp
+++ b/cmds/incident_helper/src/ih_util.cpp
@@ -97,7 +97,7 @@
 
     size_t lastIndex = 0;
     int i = 0;
-    while (headerNames[i] != NULL) {
+    while (headerNames[i] != nullptr) {
         std::string s = headerNames[i];
         lastIndex = line.find(s, lastIndex);
         if (lastIndex == std::string::npos) {
@@ -237,18 +237,18 @@
 Reader::Reader(const int fd)
 {
     mFile = fdopen(fd, "r");
-    mStatus = mFile == NULL ? "Invalid fd " + std::to_string(fd) : "";
+    mStatus = mFile == nullptr ? "Invalid fd " + std::to_string(fd) : "";
 }
 
 Reader::~Reader()
 {
-    if (mFile != NULL) fclose(mFile);
+    if (mFile != nullptr) fclose(mFile);
 }
 
 bool Reader::readLine(std::string* line) {
-    if (mFile == NULL) return false;
+    if (mFile == nullptr) return false;
 
-    char* buf = NULL;
+    char* buf = nullptr;
     size_t len = 0;
     ssize_t read = getline(&buf, &len, mFile);
     if (read != -1) {
diff --git a/cmds/incident_helper/src/main.cpp b/cmds/incident_helper/src/main.cpp
index 5b6ac7af..809a771 100644
--- a/cmds/incident_helper/src/main.cpp
+++ b/cmds/incident_helper/src/main.cpp
@@ -98,7 +98,7 @@
 
     fprintf(stderr, "Pasring section %d...\n", sectionID);
     TextParserBase* parser = selectParser(sectionID);
-    if (parser != NULL) {
+    if (parser != nullptr) {
         fprintf(stderr, "Running parser: %s\n", parser->name.string());
         status_t err = parser->Parse(STDIN_FILENO, STDOUT_FILENO);
         if (err != NO_ERROR) {
diff --git a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
index eed68b9..21ced9c 100644
--- a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
+++ b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
@@ -109,7 +109,7 @@
             nextToUsage = false;
 
             // NAME is not in the list since we need to modify the end of the CMD index.
-            const char* headerNames[] = { "PID", "TID", "USER", "PR", "NI", "CPU", "S", "VIRT", "RES", "PCY", "CMD", NULL };
+            const char* headerNames[] = { "PID", "TID", "USER", "PR", "NI", "CPU", "S", "VIRT", "RES", "PCY", "CMD", nullptr };
             if (!getColumnIndices(columnIndices, headerNames, line)) {
                 return -1;
             }
diff --git a/cmds/incident_helper/src/parsers/PsParser.cpp b/cmds/incident_helper/src/parsers/PsParser.cpp
index 8d64064..d3cb4be 100644
--- a/cmds/incident_helper/src/parsers/PsParser.cpp
+++ b/cmds/incident_helper/src/parsers/PsParser.cpp
@@ -48,7 +48,7 @@
         if (nline++ == 0) {
             header = parseHeader(line, DEFAULT_WHITESPACE);
 
-            const char* headerNames[] = { "LABEL", "USER", "PID", "TID", "PPID", "VSZ", "RSS", "WCHAN", "ADDR", "S", "PRI", "NI", "RTPRIO", "SCH", "PCY", "TIME", "CMD", NULL };
+            const char* headerNames[] = { "LABEL", "USER", "PID", "TID", "PPID", "VSZ", "RSS", "WCHAN", "ADDR", "S", "PRI", "NI", "RTPRIO", "SCH", "PCY", "TIME", "CMD", nullptr };
             if (!getColumnIndices(columnIndices, headerNames, line)) {
                 return -1;
             }
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 203a8e9b..d7a926f 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -1727,6 +1727,17 @@
     optional uint64 timestamp_millis = 1 [(stateFieldOption).option = EXCLUSIVE];
 }
 
+/**
+ * An atom for generic metrics logging. Available from Android Q.
+ */
+message GenericAtom {
+    // The uid of the application that sent this custom atom.
+    optional int32 uid = 1 [(is_uid) = true];
+
+    // An event_id indicates the type of event.
+    optional int32 event_id = 2;
+}
+
 //////////////////////////////////////////////////////////////////////
 // Pulled atoms below this line //
 //////////////////////////////////////////////////////////////////////
@@ -2156,14 +2167,3 @@
     // Total number of exceptions.
     optional int64 exception_count = 2;
 }
-
-/**
- * An atom for generic metrics logging. Available from Android Q.
- */
-message GenericAtom {
-    // The uid of the application that sent this custom atom.
-    optional int32 uid = 1 [(is_uid) = true];
-
-    // An event_id indicates the type of event.
-    optional int32 event_id = 2;
-}
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index ee4e20a..c30f2f5 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -4349,17 +4349,6 @@
 Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V
 Landroid/service/wallpaper/WallpaperService;->MSG_WINDOW_RESIZED:I
 Landroid/speech/IRecognitionListener;->onEvent(ILandroid/os/Bundle;)V
-Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String;
-Landroid/speech/tts/TextToSpeech;->mConnectingServiceConnection:Landroid/speech/tts/TextToSpeech$Connection;
-Landroid/speech/tts/TextToSpeech;->mCurrentEngine:Ljava/lang/String;
-Landroid/speech/tts/TextToSpeech;->mInitListener:Landroid/speech/tts/TextToSpeech$OnInitListener;
-Landroid/speech/tts/TtsEngines;-><init>(Landroid/content/Context;)V
-Landroid/speech/tts/TtsEngines;->getEngines()Ljava/util/List;
-Landroid/speech/tts/TtsEngines;->getLocalePrefForEngine(Ljava/lang/String;)Ljava/util/Locale;
-Landroid/speech/tts/TtsEngines;->getSettingsIntent(Ljava/lang/String;)Landroid/content/Intent;
-Landroid/speech/tts/TtsEngines;->normalizeTTSLocale(Ljava/util/Locale;)Ljava/util/Locale;
-Landroid/speech/tts/TtsEngines;->parseLocaleString(Ljava/lang/String;)Ljava/util/Locale;
-Landroid/speech/tts/TtsEngines;->updateLocalePrefForEngine(Ljava/lang/String;Ljava/util/Locale;)V
 Landroid/system/Int32Ref;->value:I
 Landroid/system/OsConstants;-><init>()V
 Landroid/system/OsConstants;->AF_NETLINK:I
@@ -4837,7 +4826,6 @@
 Landroid/text/SpannableStringBuilder;->sendToSpanWatchers(III)V
 Landroid/text/SpannableStringBuilder;->substring(II)Ljava/lang/String;
 Landroid/text/SpannableStringInternal;-><init>(Ljava/lang/CharSequence;II)V
-Landroid/text/SpannableStringInternal;->charAt(I)C
 Landroid/text/SpannableStringInternal;->checkRange(Ljava/lang/String;II)V
 Landroid/text/SpannableStringInternal;->COLUMNS:I
 Landroid/text/SpannableStringInternal;->copySpans(Landroid/text/SpannableStringInternal;II)V
@@ -4845,14 +4833,12 @@
 Landroid/text/SpannableStringInternal;->EMPTY:[Ljava/lang/Object;
 Landroid/text/SpannableStringInternal;->END:I
 Landroid/text/SpannableStringInternal;->FLAGS:I
-Landroid/text/SpannableStringInternal;->getChars(II[CI)V
 Landroid/text/SpannableStringInternal;->getSpanEnd(Ljava/lang/Object;)I
 Landroid/text/SpannableStringInternal;->getSpanFlags(Ljava/lang/Object;)I
 Landroid/text/SpannableStringInternal;->getSpans(IILjava/lang/Class;)[Ljava/lang/Object;
 Landroid/text/SpannableStringInternal;->getSpanStart(Ljava/lang/Object;)I
 Landroid/text/SpannableStringInternal;->isIndexFollowsNextLine(I)Z
 Landroid/text/SpannableStringInternal;->isOutOfCopyRange(IIII)Z
-Landroid/text/SpannableStringInternal;->length()I
 Landroid/text/SpannableStringInternal;->mSpanCount:I
 Landroid/text/SpannableStringInternal;->mSpanData:[I
 Landroid/text/SpannableStringInternal;->mSpans:[Ljava/lang/Object;
diff --git a/core/java/android/app/JobSchedulerImpl.java b/core/java/android/app/JobSchedulerImpl.java
index 4ac44f7..5494e2a 100644
--- a/core/java/android/app/JobSchedulerImpl.java
+++ b/core/java/android/app/JobSchedulerImpl.java
@@ -17,16 +17,15 @@
 // in android.app so ContextImpl has package access
 package android.app;
 
+import android.app.job.IJobScheduler;
 import android.app.job.JobInfo;
 import android.app.job.JobScheduler;
-import android.app.job.IJobScheduler;
+import android.app.job.JobSnapshot;
 import android.app.job.JobWorkItem;
-import android.content.Intent;
 import android.os.RemoteException;
 
 import java.util.List;
 
-
 /**
  * Concrete implementation of the JobScheduler interface
  * @hide 
@@ -98,4 +97,22 @@
             return null;
         }
     }
+
+    @Override
+    public List<JobInfo> getStartedJobs() {
+        try {
+            return mBinder.getStartedJobs();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public List<JobSnapshot> getAllJobSnapshots() {
+        try {
+            return mBinder.getAllJobSnapshots();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
 }
diff --git a/core/java/android/app/job/IJobScheduler.aidl b/core/java/android/app/job/IJobScheduler.aidl
index e94da0c..53b33c2 100644
--- a/core/java/android/app/job/IJobScheduler.aidl
+++ b/core/java/android/app/job/IJobScheduler.aidl
@@ -17,6 +17,7 @@
 package android.app.job;
 
 import android.app.job.JobInfo;
+import android.app.job.JobSnapshot;
 import android.app.job.JobWorkItem;
 
  /**
@@ -31,4 +32,6 @@
     void cancelAll();
     List<JobInfo> getAllPendingJobs();
     JobInfo getPendingJob(int jobId);
+    List<JobInfo> getStartedJobs();
+    List<JobSnapshot> getAllJobSnapshots();
 }
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index 0deb2e1..08b1c2b 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -172,4 +172,20 @@
      *     if the supplied job ID does not correspond to any job.
      */
     public abstract @Nullable JobInfo getPendingJob(int jobId);
-}
+
+    /**
+     * <b>For internal system callers only!</b>
+     * Returns a list of all currently-executing jobs.
+     * @hide
+     */
+    public abstract List<JobInfo> getStartedJobs();
+
+    /**
+     * <b>For internal system callers only!</b>
+     * Returns a snapshot of the state of all jobs known to the system.
+     *
+     * <p class="note">This is a slow operation, so it should be called sparingly.
+     * @hide
+     */
+    public abstract List<JobSnapshot> getAllJobSnapshots();
+}
\ No newline at end of file
diff --git a/core/java/android/app/job/JobSnapshot.aidl b/core/java/android/app/job/JobSnapshot.aidl
new file mode 100644
index 0000000..d40f4e3
--- /dev/null
+++ b/core/java/android/app/job/JobSnapshot.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.job;
+
+parcelable JobSnapshot;
diff --git a/core/java/android/app/job/JobSnapshot.java b/core/java/android/app/job/JobSnapshot.java
new file mode 100644
index 0000000..d6cc70d
--- /dev/null
+++ b/core/java/android/app/job/JobSnapshot.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.job;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Current-state snapshot of a scheduled job.  These snapshots are not used in apps;
+ * they exist only within the system process across the local call surface where JobStatus
+ * is not directly accessible at build time.
+ *
+ * Constraints that the underlying job does not require are always reported as
+ * being currently satisfied.
+ * @hide
+ */
+public class JobSnapshot implements Parcelable {
+    private final JobInfo mJob;
+    private final int mSatisfiedConstraints;
+    private final boolean mIsRunnable;
+
+    public JobSnapshot(JobInfo info, int satisfiedMask, boolean runnable) {
+        mJob = info;
+        mSatisfiedConstraints = satisfiedMask;
+        mIsRunnable = runnable;
+    }
+
+    public JobSnapshot(Parcel in) {
+        mJob = JobInfo.CREATOR.createFromParcel(in);
+        mSatisfiedConstraints = in.readInt();
+        mIsRunnable = in.readBoolean();
+    }
+
+    private boolean satisfied(int flag) {
+        return (mSatisfiedConstraints & flag) != 0;
+    }
+
+    /**
+     * Is this job actually runnable at this moment?
+     */
+    public boolean isRunnable() {
+        return mIsRunnable;
+    }
+
+    /**
+     * @see JobInfo.Builder#setRequiresCharging(boolean)
+     */
+    public boolean isChargingSatisfied() {
+        return !mJob.isRequireCharging()
+                || satisfied(JobInfo.CONSTRAINT_FLAG_CHARGING);
+    }
+
+    /**
+     * @see JobInfo.Builder#setRequiresBatteryNotLow(boolean)
+     */
+    public boolean isBatteryNotLowSatisfied() {
+        return !mJob.isRequireBatteryNotLow()
+                || satisfied(JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW);
+    }
+
+    /**
+     * @see JobInfo.Builder#setRequiresDeviceIdle(boolean)
+     */
+    public boolean isRequireDeviceIdleSatisfied() {
+        return !mJob.isRequireDeviceIdle()
+                || satisfied(JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW);
+    }
+
+    public boolean isRequireStorageNotLowSatisfied() {
+        return !mJob.isRequireStorageNotLow()
+                || satisfied(JobInfo.CONSTRAINT_FLAG_STORAGE_NOT_LOW);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        mJob.writeToParcel(out, flags);
+        out.writeInt(mSatisfiedConstraints);
+        out.writeBoolean(mIsRunnable);
+    }
+
+    public static final Creator<JobSnapshot> CREATOR = new Creator<JobSnapshot>() {
+        @Override
+        public JobSnapshot createFromParcel(Parcel in) {
+            return new JobSnapshot(in);
+        }
+
+        @Override
+        public JobSnapshot[] newArray(int size) {
+            return new JobSnapshot[size];
+        }
+    };
+}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 9a5d502..dc1f805 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -126,51 +126,122 @@
     public native static boolean queryUserAccess(int uid, int netId);
 
     /**
-     * Convert a IPv4 address from an integer to an InetAddress.
-     * @param hostAddress an int corresponding to the IPv4 address in network byte order
+     * @see #intToInet4AddressHTL(int)
+     * @deprecated Use either {@link #intToInet4AddressHTH(int)}
+     *             or {@link #intToInet4AddressHTL(int)}
      */
+    @Deprecated
     public static InetAddress intToInetAddress(int hostAddress) {
-        byte[] addressBytes = { (byte)(0xff & hostAddress),
-                                (byte)(0xff & (hostAddress >> 8)),
-                                (byte)(0xff & (hostAddress >> 16)),
-                                (byte)(0xff & (hostAddress >> 24)) };
+        return intToInet4AddressHTL(hostAddress);
+    }
+
+    /**
+     * Convert a IPv4 address from an integer to an InetAddress (0x04030201 -> 1.2.3.4)
+     *
+     * <p>This method uses the higher-order int bytes as the lower-order IPv4 address bytes,
+     * which is an unusual convention. Consider {@link #intToInet4AddressHTH(int)} instead.
+     * @param hostAddress an int coding for an IPv4 address, where higher-order int byte is
+     *                    lower-order IPv4 address byte
+     */
+    public static InetAddress intToInet4AddressHTL(int hostAddress) {
+        return intToInet4AddressHTH(Integer.reverseBytes(hostAddress));
+    }
+
+    /**
+     * Convert a IPv4 address from an integer to an InetAddress (0x01020304 -> 1.2.3.4)
+     * @param hostAddress an int coding for an IPv4 address
+     */
+    public static InetAddress intToInet4AddressHTH(int hostAddress) {
+        byte[] addressBytes = { (byte) (0xff & (hostAddress >> 24)),
+                (byte) (0xff & (hostAddress >> 16)),
+                (byte) (0xff & (hostAddress >> 8)),
+                (byte) (0xff & hostAddress) };
 
         try {
-           return InetAddress.getByAddress(addressBytes);
+            return InetAddress.getByAddress(addressBytes);
         } catch (UnknownHostException e) {
-           throw new AssertionError();
+            throw new AssertionError();
         }
     }
 
     /**
-     * Convert a IPv4 address from an InetAddress to an integer
-     * @param inetAddr is an InetAddress corresponding to the IPv4 address
-     * @return the IP address as an integer in network byte order
+     * @see #inet4AddressToIntHTL(Inet4Address)
+     * @deprecated Use either {@link #inet4AddressToIntHTH(Inet4Address)}
+     *             or {@link #inet4AddressToIntHTL(Inet4Address)}
      */
+    @Deprecated
     public static int inetAddressToInt(Inet4Address inetAddr)
             throws IllegalArgumentException {
-        byte [] addr = inetAddr.getAddress();
-        return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
-                ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
+        return inet4AddressToIntHTL(inetAddr);
     }
 
     /**
-     * Convert a network prefix length to an IPv4 netmask integer
-     * @param prefixLength
-     * @return the IPv4 netmask as an integer in network byte order
+     * Convert an IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x01020304)
+     *
+     * <p>This conversion can help order IP addresses: considering the ordering
+     * 192.0.2.1 < 192.0.2.2 < ..., resulting ints will follow that ordering if read as unsigned
+     * integers with {@link Integer#toUnsignedLong}.
+     * @param inetAddr is an InetAddress corresponding to the IPv4 address
+     * @return the IP address as integer
      */
+    public static int inet4AddressToIntHTH(Inet4Address inetAddr)
+            throws IllegalArgumentException {
+        byte [] addr = inetAddr.getAddress();
+        return ((addr[0] & 0xff) << 24) | ((addr[1] & 0xff) << 16)
+                | ((addr[2] & 0xff) << 8) | (addr[3] & 0xff);
+    }
+
+    /**
+     * Convert a IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x04030201)
+     *
+     * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes,
+     * which is an unusual convention. Consider {@link #inet4AddressToIntHTH(Inet4Address)} instead.
+     * @param inetAddr is an InetAddress corresponding to the IPv4 address
+     * @return the IP address as integer
+     */
+    public static int inet4AddressToIntHTL(Inet4Address inetAddr) {
+        return Integer.reverseBytes(inet4AddressToIntHTH(inetAddr));
+    }
+
+    /**
+     * @see #prefixLengthToV4NetmaskIntHTL(int)
+     * @deprecated Use either {@link #prefixLengthToV4NetmaskIntHTH(int)}
+     *             or {@link #prefixLengthToV4NetmaskIntHTL(int)}
+     */
+    @Deprecated
     public static int prefixLengthToNetmaskInt(int prefixLength)
             throws IllegalArgumentException {
+        return prefixLengthToV4NetmaskIntHTL(prefixLength);
+    }
+
+    /**
+     * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0xffff8000)
+     * @return the IPv4 netmask as an integer
+     */
+    public static int prefixLengthToV4NetmaskIntHTH(int prefixLength)
+            throws IllegalArgumentException {
         if (prefixLength < 0 || prefixLength > 32) {
             throw new IllegalArgumentException("Invalid prefix length (0 <= prefix <= 32)");
         }
-        int value = 0xffffffff << (32 - prefixLength);
-        return Integer.reverseBytes(value);
+        // (int)a << b is equivalent to a << (b & 0x1f): can't shift by 32 (-1 << 32 == -1)
+        return prefixLength == 0 ? 0 : 0xffffffff << (32 - prefixLength);
+    }
+
+    /**
+     * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0x0080ffff).
+     *
+     * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes,
+     * which is an unusual convention. Consider {@link #prefixLengthToV4NetmaskIntHTH(int)} instead.
+     * @return the IPv4 netmask as an integer
+     */
+    public static int prefixLengthToV4NetmaskIntHTL(int prefixLength)
+            throws IllegalArgumentException {
+        return Integer.reverseBytes(prefixLengthToV4NetmaskIntHTH(prefixLength));
     }
 
     /**
      * Convert a IPv4 netmask integer to a prefix length
-     * @param netmask as an integer in network byte order
+     * @param netmask as an integer (0xff000000 for a /8 subnet)
      * @return the network prefix length
      */
     public static int netmaskIntToPrefixLength(int netmask) {
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 3cd37bf..cea480f 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -6,3 +6,13 @@
 lorenzo@google.com
 satk@google.com
 silberst@google.com
+
+per-file SSL*=flooey@google.com
+per-file SSL*=narayan@google.com
+per-file SSL*=tobiast@google.com
+per-file Uri*=flooey@google.com
+per-file Uri*=narayan@google.com
+per-file Uri*=tobiast@google.com
+per-file Url*=flooey@google.com
+per-file Url*=narayan@google.com
+per-file Url*=tobiast@google.com
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 1f53587..d7eb477 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -73,10 +73,14 @@
  * Updating Your Security Provider to Protect Against SSL Exploits</a>
  * for further information.</p>
  *
- * <p>One way to verify the server's identity is to use
+ * <p>The recommended way to verify the server's identity is to use
  * {@link HttpsURLConnection#getDefaultHostnameVerifier()} to get a
  * {@link HostnameVerifier} to verify the certificate hostname.
  *
+ * <p><b>Warning</b>: Some methods on this class return connected sockets and some return
+ * unconnected sockets.  For the methods that return connected sockets, setting
+ * connection- or handshake-related properties on those sockets will have no effect.
+ *
  * <p>On development devices, "setprop socket.relaxsslcheck yes" bypasses all
  * SSL certificate and hostname checks for testing purposes.  This setting
  * requires root access.
@@ -442,8 +446,10 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This method verifies the peer's certificate hostname after connecting
-     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
+     * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's
+     * certificate hostname after connecting; if this instance was created with
+     * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i>
+     * instead.
      */
     @Override
     public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException {
@@ -459,7 +465,7 @@
     }
 
     /**
-     * Creates a new socket which is not connected to any remote host.
+     * Creates a new socket which is <i>not connected</i> to any remote host.
      * You must use {@link Socket#connect} to connect the socket.
      *
      * <p class="caution"><b>Warning:</b> Hostname verification is not performed
@@ -479,6 +485,8 @@
     /**
      * {@inheritDoc}
      *
+     * <p>This method returns a socket that is <i>not connected</i>.
+     *
      * <p class="caution"><b>Warning:</b> Hostname verification is not performed
      * with this method.  You MUST verify the server's identity after connecting
      * the socket to avoid man-in-the-middle attacks.</p>
@@ -498,6 +506,8 @@
     /**
      * {@inheritDoc}
      *
+     * <p>This method returns a socket that is <i>not connected</i>.
+     *
      * <p class="caution"><b>Warning:</b> Hostname verification is not performed
      * with this method.  You MUST verify the server's identity after connecting
      * the socket to avoid man-in-the-middle attacks.</p>
@@ -515,8 +525,10 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This method verifies the peer's certificate hostname after connecting
-     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
+     * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's
+     * certificate hostname after connecting; if this instance was created with
+     * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i>
+     * instead.
      */
     @Override
     public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
@@ -536,8 +548,10 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This method verifies the peer's certificate hostname after connecting
-     * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
+     * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's
+     * certificate hostname after connecting; if this instance was created with
+     * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i>
+     * instead.
      */
     @Override
     public Socket createSocket(String host, int port) throws IOException {
diff --git a/core/java/android/net/http/OWNERS b/core/java/android/net/http/OWNERS
new file mode 100644
index 0000000..6b8c9ed
--- /dev/null
+++ b/core/java/android/net/http/OWNERS
@@ -0,0 +1,3 @@
+flooey@google.com
+narayan@google.com
+tobiast@google.com
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 1ad0929..12c2305 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -37,6 +37,7 @@
     public static final int PROBE_HTTPS     = 2;
     public static final int PROBE_PAC       = 3;
     public static final int PROBE_FALLBACK  = 4;
+    public static final int PROBE_PRIVDNS   = 5;
 
     public static final int DNS_FAILURE = 0;
     public static final int DNS_SUCCESS = 1;
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index f7409d0..14a4509 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -187,8 +187,7 @@
     /**
      * A boolean parameter for {@link Contacts#CONTENT_STREQUENT_URI} and
      * {@link Contacts#CONTENT_STREQUENT_FILTER_URI}, which requires the ContactsProvider to
-     * return only phone-related results. For example, frequently contacted person list should
-     * include persons contacted via phone (not email, sms, etc.)
+     * return only phone-related results.
      */
     public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only";
 
@@ -870,13 +869,23 @@
         /**
          * The number of times a contact has been contacted
          * <P>Type: INTEGER</P>
+         *
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}. This column
+         * always contains 0.
          */
+        @Deprecated
         public static final String TIMES_CONTACTED = "times_contacted";
 
         /**
          * The last time a contact was contacted.
          * <P>Type: INTEGER</P>
+         *
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}. This column
+         * always contains 0.
          */
+        @Deprecated
         public static final String LAST_TIME_CONTACTED = "last_time_contacted";
 
         /** @hide Raw value. */
@@ -1313,8 +1322,7 @@
      * of the newly inserted raw contact.</dd>
      * <dt><b>Update</b></dt>
      * <dd>Only certain columns of Contact are modifiable:
-     * {@link #TIMES_CONTACTED}, {@link #LAST_TIME_CONTACTED}, {@link #STARRED},
-     * {@link #CUSTOM_RINGTONE}, {@link #SEND_TO_VOICEMAIL}. Changing any of
+     * {@link #STARRED}, {@link #CUSTOM_RINGTONE}, {@link #SEND_TO_VOICEMAIL}. Changing any of
      * these columns on the Contact also changes them on all constituent raw
      * contacts.</dd>
      * <dt><b>Delete</b></dt>
@@ -1415,27 +1423,6 @@
      * </tr>
      * <tr>
      * <td>int</td>
-     * <td>{@link #TIMES_CONTACTED}</td>
-     * <td>read/write</td>
-     * <td>The number of times the contact has been contacted. See
-     * {@link #markAsContacted}. When raw contacts are aggregated, this field is
-     * computed automatically as the maximum number of times contacted among all
-     * constituent raw contacts. Setting this field automatically changes the
-     * corresponding field on all constituent raw contacts.</td>
-     * </tr>
-     * <tr>
-     * <td>long</td>
-     * <td>{@link #LAST_TIME_CONTACTED}</td>
-     * <td>read/write</td>
-     * <td>The timestamp of the last time the contact was contacted. See
-     * {@link #markAsContacted}. Setting this field also automatically
-     * increments {@link #TIMES_CONTACTED}. When raw contacts are aggregated,
-     * this field is computed automatically as the latest time contacted of all
-     * constituent raw contacts. Setting this field automatically changes the
-     * corresponding field on all constituent raw contacts.</td>
-     * </tr>
-     * <tr>
-     * <td>int</td>
      * <td>{@link #STARRED}</td>
      * <td>read/write</td>
      * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise.
@@ -1696,16 +1683,12 @@
          * @param resolver the ContentResolver to use
          * @param contactId the person who was contacted
          *
-         * @deprecated The class DataUsageStatUpdater of the Android support library should
-         *     be used instead.
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}. This method
+         * is no-op.
          */
         @Deprecated
         public static void markAsContacted(ContentResolver resolver, long contactId) {
-            Uri uri = ContentUris.withAppendedId(CONTENT_URI, contactId);
-            ContentValues values = new ContentValues();
-            // TIMES_CONTACTED will be incremented when LAST_TIME_CONTACTED is modified.
-            values.put(LR_LAST_TIME_CONTACTED, System.currentTimeMillis());
-            resolver.update(uri, values, null, null);
         }
 
         /**
@@ -1727,15 +1710,21 @@
 
         /**
          * The content:// style URI for this table joined with useful data from
-         * {@link ContactsContract.Data}, filtered to include only starred contacts
-         * and the most frequently contacted contacts.
+         * {@link ContactsContract.Data}, filtered to include only starred contacts.
+         * Frequent contacts are no longer included in the result as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}.
          */
         public static final Uri CONTENT_STREQUENT_URI = Uri.withAppendedPath(
                 CONTENT_URI, "strequent");
 
         /**
          * The content:// style URI for showing a list of frequently contacted people.
+         *
+         * @deprecated Frequent contacts are no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}.
+         * This URI always returns an empty cursor.
          */
+        @Deprecated
         public static final Uri CONTENT_FREQUENT_URI = Uri.withAppendedPath(
                 CONTENT_URI, "frequent");
 
@@ -2631,27 +2620,6 @@
      * </tr>
      * <tr>
      * <td>int</td>
-     * <td>{@link #TIMES_CONTACTED}</td>
-     * <td>read/write</td>
-     * <td>The number of times the contact has been contacted. To have an effect
-     * on the corresponding value of the aggregate contact, this field
-     * should be set at the time the raw contact is inserted.
-     * After that, this value is typically updated via
-     * {@link ContactsContract.Contacts#markAsContacted}.</td>
-     * </tr>
-     * <tr>
-     * <td>long</td>
-     * <td>{@link #LAST_TIME_CONTACTED}</td>
-     * <td>read/write</td>
-     * <td>The timestamp of the last time the contact was contacted. To have an effect
-     * on the corresponding value of the aggregate contact, this field
-     * should be set at the time the raw contact is inserted.
-     * After that, this value is typically updated via
-     * {@link ContactsContract.Contacts#markAsContacted}.
-     * </td>
-     * </tr>
-     * <tr>
-     * <td>int</td>
      * <td>{@link #STARRED}</td>
      * <td>read/write</td>
      * <td>An indicator for favorite contacts: '1' if favorite, '0' otherwise.
@@ -4286,10 +4254,22 @@
      * Columns in the Data_Usage_Stat table
      */
     protected interface DataUsageStatColumns {
-        /** The last time (in milliseconds) this {@link Data} was used. */
+        /**
+         * The last time (in milliseconds) this {@link Data} was used.
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}.
+         * This column always contains 0.
+         */
+        @Deprecated
         public static final String LAST_TIME_USED = "last_time_used";
 
-        /** The number of times the referenced {@link Data} has been used. */
+        /**
+         * The number of times the referenced {@link Data} has been used.
+         * @deprecated Contacts affinity information is no longer supported as of
+         * Android version {@link android.os.Build.VERSION_CODES#Q}.
+         * This column always contains 0.
+         */
+        @Deprecated
         public static final String TIMES_USED = "times_used";
 
         /** @hide Raw value. */
@@ -4765,18 +4745,6 @@
      * </tr>
      * <tr>
      * <td>int</td>
-     * <td>{@link #TIMES_CONTACTED}</td>
-     * <td>read-only</td>
-     * <td>See {@link ContactsContract.Contacts}.</td>
-     * </tr>
-     * <tr>
-     * <td>long</td>
-     * <td>{@link #LAST_TIME_CONTACTED}</td>
-     * <td>read-only</td>
-     * <td>See {@link ContactsContract.Contacts}.</td>
-     * </tr>
-     * <tr>
-     * <td>int</td>
      * <td>{@link #STARRED}</td>
      * <td>read-only</td>
      * <td>See {@link ContactsContract.Contacts}.</td>
@@ -5221,18 +5189,6 @@
      * </tr>
      * <tr>
      * <td>int</td>
-     * <td>{@link #TIMES_CONTACTED}</td>
-     * <td>read-only</td>
-     * <td>See {@link ContactsContract.Contacts}.</td>
-     * </tr>
-     * <tr>
-     * <td>long</td>
-     * <td>{@link #LAST_TIME_CONTACTED}</td>
-     * <td>read-only</td>
-     * <td>See {@link ContactsContract.Contacts}.</td>
-     * </tr>
-     * <tr>
-     * <td>int</td>
      * <td>{@link #STARRED}</td>
      * <td>read-only</td>
      * <td>See {@link ContactsContract.Contacts}.</td>
@@ -8305,7 +8261,12 @@
      * boolean successful = resolver.delete(DataUsageFeedback.DELETE_USAGE_URI, null, null) > 0;
      * </pre>
      * </p>
+     *
+     * @deprecated Contacts affinity information is no longer supported as of
+     * Android version {@link android.os.Build.VERSION_CODES#Q}.
+     * Both update and delete calls are always ignored.
      */
+    @Deprecated
     public static final class DataUsageFeedback {
 
         /**
@@ -8925,10 +8886,6 @@
          * +<phone>", etc. If you must show the prefix text in the Contacts App, please use a
          * different DATA# column, and update your contacts.xml to point to this new column. </em>
          * </li>
-         * <li>Everytime the user sends a message to a contact, your app may choose to update the
-         * {@link ContactOptionsColumns#TIMES_CONTACTED} entry through DataUsageFeedback class.
-         * Doing this will allow Voice Assistant to bias speech recognition to contacts frequently
-         * contacted, this is particularly useful for contact names that are hard to pronounce.</li>
          * </ul>
          * If the app chooses not to integrate with the Contacts Provider (in particular, when
          * either METADATA_ACCOUNT_TYPE or METADATA_MIMETYPE field is missing), Voice Assistant
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 6f1bd78..83f14d1 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -20,6 +20,7 @@
 import android.annotation.RawRes;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -668,8 +669,10 @@
     }
 
     private final Context mContext;
+    @UnsupportedAppUsage
     private Connection mConnectingServiceConnection;
     private Connection mServiceConnection;
+    @UnsupportedAppUsage
     private OnInitListener mInitListener;
     // Written from an unspecified application thread, read from
     // a binder thread.
@@ -686,6 +689,7 @@
     private final Map<CharSequence, Uri> mUtterances;
     private final Bundle mParams = new Bundle();
     private final TtsEngines mEnginesHelper;
+    @UnsupportedAppUsage
     private volatile String mCurrentEngine = null;
 
     /**
@@ -1425,6 +1429,7 @@
      * @return the engine currently in use by this TextToSpeech instance.
      * @hide
      */
+    @UnsupportedAppUsage
     public String getCurrentEngine() {
         return mCurrentEngine;
     }
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index a8c3453..a7b280b 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -30,6 +30,7 @@
 
 import static android.provider.Settings.Secure.getString;
 
+import android.annotation.UnsupportedAppUsage;
 import android.provider.Settings;
 import android.speech.tts.TextToSpeech.Engine;
 import android.speech.tts.TextToSpeech.EngineInfo;
@@ -101,6 +102,7 @@
         sNormalizeCountry = Collections.unmodifiableMap(normalizeCountry);
     }
 
+    @UnsupportedAppUsage
     public TtsEngines(Context ctx) {
         mContext = ctx;
     }
@@ -155,6 +157,7 @@
      *
      * @return A list of engine info objects. The list can be empty, but never {@code null}.
      */
+    @UnsupportedAppUsage
     public List<EngineInfo> getEngines() {
         PackageManager pm = mContext.getPackageManager();
         Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE);
@@ -194,6 +197,7 @@
     /**
      * @return an intent that can launch the settings activity for a given tts engine.
      */
+    @UnsupportedAppUsage
     public Intent getSettingsIntent(String engine) {
         PackageManager pm = mContext.getPackageManager();
         Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE);
@@ -327,6 +331,7 @@
      * @param engineName the engine to return the locale for.
      * @return the locale preference for this engine. Will be non null.
      */
+    @UnsupportedAppUsage
     public Locale getLocalePrefForEngine(String engineName) {
         return getLocalePrefForEngine(engineName,
                 getString(mContext.getContentResolver(), Settings.Secure.TTS_DEFAULT_LOCALE));
@@ -376,6 +381,7 @@
      * country codes ({@link Locale#getISO3Language()} and {@link Locale#getISO3Country()}),
      * if it fails to do so, we return null.
      */
+    @UnsupportedAppUsage
     public Locale parseLocaleString(String localeString) {
         String language = "", country = "", variant = "";
         if (!TextUtils.isEmpty(localeString)) {
@@ -436,6 +442,7 @@
      * This method tries to convert three-letter language and country codes into their two-letter
      * equivalents. If it fails to do so, it keeps the value from the TTS locale.
      */
+    @UnsupportedAppUsage
     public static Locale normalizeTTSLocale(Locale ttsLocale) {
         String language = ttsLocale.getLanguage();
         if (!TextUtils.isEmpty(language)) {
@@ -514,6 +521,7 @@
      * the passed locale is null, an empty string will be serialized; that empty string, when
      * read back, will evaluate to {@link Locale#getDefault()}.
      */
+    @UnsupportedAppUsage
     public synchronized void updateLocalePrefForEngine(String engineName, Locale newLocale) {
         final String prefList = Settings.Secure.getString(mContext.getContentResolver(),
                 Settings.Secure.TTS_DEFAULT_LOCALE);
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index abb9321..ae9c5c4 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -16,6 +16,10 @@
 
 package com.android.internal.app;
 
+import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
+
+import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
@@ -23,8 +27,11 @@
 import android.app.AppGlobals;
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -32,12 +39,11 @@
 import android.os.UserManager;
 import android.util.Slog;
 import android.widget.Toast;
-
 import com.android.internal.annotations.VisibleForTesting;
-
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
-
-import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
+import java.util.Set;
 
 /**
  * This is used in conjunction with
@@ -45,7 +51,6 @@
  * be passed in and out of a managed profile.
  */
 public class IntentForwarderActivity extends Activity  {
-
     public static String TAG = "IntentForwarderActivity";
 
     public static String FORWARD_INTENT_TO_PARENT
@@ -54,6 +59,9 @@
     public static String FORWARD_INTENT_TO_MANAGED_PROFILE
             = "com.android.internal.app.ForwardIntentToManagedProfile";
 
+    private static final Set<String> ALLOWED_TEXT_MESSAGE_SCHEME
+            = new HashSet<>(Arrays.asList("sms", "smsto", "mms", "mmsto"));
+
     private Injector mInjector;
 
     @Override
@@ -94,19 +102,8 @@
                 newIntent.prepareToLeaveUser(callingUserId);
             }
 
-            final android.content.pm.ResolveInfo ri =
-                    mInjector.getPackageManager().resolveActivityAsUser(
-                            newIntent,
-                            MATCH_DEFAULT_ONLY,
-                            targetUserId);
-
-            // Don't show the disclosure if next activity is ResolverActivity or ChooserActivity
-            // as those will already have shown work / personal as neccesary etc.
-            final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null ||
-                    !"android".equals(ri.activityInfo.packageName) ||
-                    !(ResolverActivity.class.getName().equals(ri.activityInfo.name)
-                            || ChooserActivity.class.getName().equals(ri.activityInfo.name));
-
+            final ResolveInfo ri = mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY,
+                    targetUserId);
             try {
                 startActivityAsCaller(newIntent, null, false, targetUserId);
             } catch (RuntimeException e) {
@@ -125,8 +122,8 @@
                         + ActivityThread.currentProcessName(), e);
             }
 
-            if (shouldShowDisclosure) {
-                Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show();
+            if (shouldShowDisclosure(ri, intentReceived)) {
+                mInjector.showToast(userMessageId, Toast.LENGTH_LONG);
             }
         } else {
             Slog.wtf(TAG, "the intent: " + intentReceived + " cannot be forwarded from user "
@@ -135,6 +132,35 @@
         finish();
     }
 
+    private boolean shouldShowDisclosure(@Nullable ResolveInfo ri, Intent intent) {
+        if (ri == null || ri.activityInfo == null) {
+            return true;
+        }
+        if (ri.activityInfo.applicationInfo.isSystemApp()
+                && (isDialerIntent(intent) || isTextMessageIntent(intent))) {
+            return false;
+        }
+        return !isTargetResolverOrChooserActivity(ri.activityInfo);
+    }
+
+    private boolean isTextMessageIntent(Intent intent) {
+        return Intent.ACTION_SENDTO.equals(intent.getAction()) && intent.getData() != null
+            && ALLOWED_TEXT_MESSAGE_SCHEME.contains(intent.getData().getScheme());
+    }
+
+    private boolean isDialerIntent(Intent intent) {
+        return Intent.ACTION_DIAL.equals(intent.getAction())
+            || Intent.ACTION_CALL.equals(intent.getAction());
+    }
+
+    private boolean isTargetResolverOrChooserActivity(ActivityInfo activityInfo) {
+        if (!"android".equals(activityInfo.packageName)) {
+            return false;
+        }
+        return ResolverActivity.class.getName().equals(activityInfo.name)
+            || ChooserActivity.class.getName().equals(activityInfo.name);
+    }
+
     /**
      * Check whether the intent can be forwarded to target user. Return the intent used for
      * forwarding if it can be forwarded, {@code null} otherwise.
@@ -242,6 +268,16 @@
         public PackageManager getPackageManager() {
             return IntentForwarderActivity.this.getPackageManager();
         }
+
+        @Override
+        public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
+            return getPackageManager().resolveActivityAsUser(intent, flags, userId);
+        }
+
+        @Override
+        public void showToast(int messageId, int duration) {
+            Toast.makeText(IntentForwarderActivity.this, getString(messageId), duration).show();
+        }
     }
 
     public interface Injector {
@@ -250,5 +286,9 @@
         UserManager getUserManager();
 
         PackageManager getPackageManager();
+
+        ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId);
+
+        void showToast(@StringRes int messageId, int duration);
     }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index bc0d51f..f314872 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1064,9 +1064,9 @@
 
         /**
          * Reset the observer's state, returns true if the timer/counter is inactive
-         * so can be completely dropped.
+         * so it can be destroyed.
          * @param detachIfReset detach if true, no-op if false.
-         * @return Returns true if the timer/counter is inactive.
+         * @return Returns true if the timer/counter is inactive and can be destroyed.
          */
         boolean reset(boolean detachIfReset);
         /**
@@ -1128,11 +1128,7 @@
          *                   If false, use ArrayList for mObservers list.
         */
         public TimeBase(boolean isLongList) {
-            if (isLongList) {
-                mObservers = new HashSet<TimeBaseObs>();
-            } else  {
-                mObservers = new ArrayList<TimeBaseObs>();
-            }
+            mObservers = isLongList ? new HashSet<>() : new ArrayList<>();
         }
 
         public TimeBase() {
@@ -1229,11 +1225,6 @@
             return mRunning;
         }
 
-        /**
-         * Normally we do not use Iterator in framework code to avoid alloc/dealloc
-         * Iterator object, here is an exception because mObservers' type is Collection
-         * instead of list.
-         */
         public boolean setRunning(boolean running, long uptime, long realtime) {
             if (mRunning != running) {
                 mRunning = running;
@@ -1242,6 +1233,9 @@
                     mRealtimeStart = realtime;
                     long batteryUptime = mUnpluggedUptime = getUptime(uptime);
                     long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
+                    // Normally we do not use Iterator in framework code to avoid alloc/dealloc
+                    // Iterator object, here is an exception because mObservers' type is Collection
+                    // instead of list.
                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
                     while (iter.hasNext()) {
                         iter.next().onTimeStarted(realtime, batteryUptime, batteryRealtime);
@@ -1251,6 +1245,9 @@
                     mPastRealtime += realtime - mRealtimeStart;
                     long batteryUptime = getUptime(uptime);
                     long batteryRealtime = getRealtime(realtime);
+                    // Normally we do not use Iterator in framework code to avoid alloc/dealloc
+                    // Iterator object, here is an exception because mObservers' type is Collection
+                    // instead of list.
                     final Iterator<TimeBaseObs> iter = mObservers.iterator();
                     while (iter.hasNext()) {
                         iter.next().onTimeStopped(realtime, batteryUptime, batteryRealtime);
@@ -6624,8 +6621,8 @@
         return true;
     }
 
-
-    private static boolean resetIfNotNull(ControllerActivityCounterImpl counter, boolean detachIfReset) {
+    private static boolean resetIfNotNull(ControllerActivityCounterImpl counter,
+            boolean detachIfReset) {
         if (counter != null) {
             counter.reset(detachIfReset);
         }
@@ -6981,6 +6978,7 @@
             }
             if (mProcStateTimeMs[procState] == null
                     || mProcStateTimeMs[procState].getSize() != cpuTimesMs.length) {
+                detachIfNotNull(mProcStateTimeMs[procState]);
                 mProcStateTimeMs[procState] = new LongSamplingCounterArray(
                         mBsi.mOnBatteryTimeBase);
             }
@@ -7675,6 +7673,7 @@
 
 
         void initUserActivityLocked() {
+            detachIfNotNull(mUserActivityCounters);
             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
                 mUserActivityCounters[i] = new Counter(mBsi.mOnBatteryTimeBase);
@@ -9887,7 +9886,6 @@
             }
             t = new DualTimer(mBsi.mClocks, this, BatteryStats.SENSOR, timers,
                     mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
-            detachIfNotNull(se.mTimer);
             se.mTimer = t;
             return t;
         }
@@ -14187,8 +14185,8 @@
             }
             for (int ip = 0; ip < NP; ip++) {
                 String pkgName = in.readString();
+                detachIfNotNull(u.mPackageStats.get(pkgName));
                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
-                p.detach();
                 final int NWA = in.readInt();
                 if (NWA > 10000) {
                     throw new ParcelFormatException("File corrupt: too many wakeup alarms " + NWA);
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index eb369e1..4aa30f6 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -37,7 +37,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BinderInternal.CallSession;
-import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
@@ -45,15 +44,12 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Queue;
 import java.util.Random;
-import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.function.Function;
 import java.util.function.ToDoubleFunction;
 
 /**
@@ -63,7 +59,7 @@
 public class BinderCallsStats implements BinderInternal.Observer {
     public static final boolean ENABLED_DEFAULT = false;
     public static final boolean DETAILED_TRACKING_DEFAULT = true;
-    public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 10;
+    public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 100;
 
     private static final String TAG = "BinderCallsStats";
     private static final int CALL_SESSIONS_POOL_SIZE = 100;
@@ -71,7 +67,10 @@
     private static final int MAX_EXCEPTION_COUNT_SIZE = 50;
     private static final String EXCEPTION_COUNT_OVERFLOW_NAME = "overflow";
 
+    // Whether to collect all the data: cpu + exceptions + reply/request sizes.
     private boolean mDetailedTracking = DETAILED_TRACKING_DEFAULT;
+    // Sampling period to control how often to track CPU usage. 1 means all calls, 100 means ~1 out
+    // of 100 requests.
     private int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT;
     @GuardedBy("mLock")
     private final SparseArray<UidEntry> mUidEntries = new SparseArray<>();
@@ -181,7 +180,7 @@
         s.exceptionThrown = false;
         s.cpuTimeStarted = -1;
         s.timeStarted = -1;
-        if (mDetailedTracking || shouldRecordDetailedData()) {
+        if (shouldRecordDetailedData()) {
             s.cpuTimeStarted = getThreadTimeMicro();
             s.timeStarted = getElapsedRealtimeMicro();
         }
@@ -228,14 +227,14 @@
 
             final UidEntry uidEntry = getUidEntry(callingUid);
             uidEntry.callCount++;
-            final CallStat callStat = uidEntry.getOrCreate(
-                    s.binderClass, s.transactionCode, mScreenInteractive);
-            callStat.callCount++;
 
             if (recordCall) {
                 uidEntry.cpuTimeMicros += duration;
                 uidEntry.recordedCallCount++;
 
+                final CallStat callStat = uidEntry.getOrCreate(
+                        s.binderClass, s.transactionCode, mScreenInteractive);
+                callStat.callCount++;
                 callStat.recordedCallCount++;
                 callStat.cpuTimeMicros += duration;
                 callStat.maxCpuTimeMicros = Math.max(callStat.maxCpuTimeMicros, duration);
@@ -249,6 +248,14 @@
                     callStat.maxReplySizeBytes =
                             Math.max(callStat.maxReplySizeBytes, parcelReplySize);
                 }
+            } else {
+                // Only record the total call count if we already track data for this key.
+                // It helps to keep the memory usage down when sampling is enabled.
+                final CallStat callStat = uidEntry.get(
+                        s.binderClass, s.transactionCode, mScreenInteractive);
+                if (callStat != null) {
+                    callStat.callCount++;
+                }
             }
         }
     }
@@ -463,7 +470,7 @@
             pw.println(String.format("  %6d %s", entry.second, entry.first));
         }
 
-        if (!mDetailedTracking && mPeriodicSamplingInterval != 1) {
+        if (mPeriodicSamplingInterval != 1) {
             pw.println("");
             pw.println("/!\\ Displayed data is sampled. See sampling interval at the top.");
         }
@@ -492,6 +499,9 @@
         return mRandom.nextInt() % mPeriodicSamplingInterval == 0;
     }
 
+    /**
+     * Sets to true to collect all the data.
+     */
     public void setDetailedTracking(boolean enabled) {
         synchronized (mLock) {
             if (enabled != mDetailedTracking) {
@@ -550,7 +560,8 @@
         // Number of calls for which we collected data for. We do not record data for all the calls
         // when sampling is on.
         public long recordedCallCount;
-        // Real number of total calls.
+        // Roughly the real number of total calls. We only track only track the API call count once
+        // at least one non-sampled count happened.
         public long callCount;
         // Total CPU of all for all the recorded calls.
         // Approximate total CPU usage can be computed by
@@ -624,13 +635,19 @@
         private Map<CallStatKey, CallStat> mCallStats = new ArrayMap<>();
         private CallStatKey mTempKey = new CallStatKey();
 
-        CallStat getOrCreate(Class<? extends Binder> binderClass, int transactionCode,
+        @Nullable
+        CallStat get(Class<? extends Binder> binderClass, int transactionCode,
                 boolean screenInteractive) {
             // Use a global temporary key to avoid creating new objects for every lookup.
             mTempKey.binderClass = binderClass;
             mTempKey.transactionCode = transactionCode;
             mTempKey.screenInteractive = screenInteractive;
-            CallStat mapCallStat = mCallStats.get(mTempKey);
+            return mCallStats.get(mTempKey);
+        }
+
+        CallStat getOrCreate(Class<? extends Binder> binderClass, int transactionCode,
+                boolean screenInteractive) {
+            CallStat mapCallStat = get(binderClass, transactionCode, screenInteractive);
             // Only create CallStat if it's a new entry, otherwise update existing instance
             if (mapCallStat == null) {
                 mapCallStat = new CallStat(binderClass, transactionCode, screenInteractive);
diff --git a/core/res/res/anim/keyguard_occlude_open_enter.xml b/core/res/res/anim/keyguard_occlude_open_enter.xml
new file mode 100644
index 0000000..e742616
--- /dev/null
+++ b/core/res/res/anim/keyguard_occlude_open_enter.xml
@@ -0,0 +1,30 @@
+<?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
+  -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false">
+    <translate
+        android:fromYDelta="90%"
+        android:toYDelta="0%"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="400"/>
+    <alpha
+        android:fromAlpha="0.0"
+        android:toAlpha="1.0"
+        android:interpolator="@interpolator/fast_out_slow_in"
+        android:duration="300"/>
+</set>
diff --git a/core/res/res/values-mcc214/config.xml b/core/res/res/values-mcc214/config.xml
new file mode 100644
index 0000000..9410848
--- /dev/null
+++ b/core/res/res/values-mcc214/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <!-- String array containing numbers that shouldn't be logged
+       016 present here for Spain's gender violence number -->
+  <string-array translatable="false" name="unloggable_phone_numbers">
+    <item>016</item>
+  </string-array>
+</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 474c62d..fddb904 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2729,6 +2729,9 @@
          empty string is passed in -->
     <string name="config_ims_package"/>
 
+    <!-- String array containing numbers that shouldn't be logged. Country-specific. -->
+    <string-array name="unloggable_phone_numbers" />
+
     <!-- Flag specifying whether or not IMS will use the dynamic ImsResolver -->
     <bool name="config_dynamic_bind_ims">false</bool>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e47ea71..140bb7d8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2156,6 +2156,7 @@
   <java-symbol type="anim" name="push_down_out" />
   <java-symbol type="anim" name="push_up_in" />
   <java-symbol type="anim" name="push_up_out" />
+  <java-symbol type="anim" name="keyguard_occlude_open_enter" />
   <java-symbol type="anim" name="lock_screen_behind_enter" />
   <java-symbol type="anim" name="lock_screen_behind_enter_wallpaper" />
   <java-symbol type="anim" name="lock_screen_behind_enter_fade_in" />
@@ -2235,6 +2236,7 @@
   <java-symbol type="drawable" name="decor_maximize_button_light" />
   <java-symbol type="color" name="decor_button_dark_color" />
   <java-symbol type="color" name="decor_button_light_color" />
+  <java-symbol type="array" name="unloggable_phone_numbers" />
 
   <!-- From TelephonyProvider -->
   <java-symbol type="xml" name="apns" />
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index b18fa74..c165b6b 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -16,33 +16,6 @@
 
 package com.android.internal.app;
 
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
@@ -51,11 +24,42 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
 @RunWith(AndroidJUnit4.class)
 public class IntentForwarderActivityTest {
+
     private static final ComponentName FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME =
             new ComponentName(
                     "android",
@@ -77,22 +81,26 @@
 
     private static IntentForwarderActivity.Injector sInjector;
     private static ComponentName sComponentName;
+    private static String sActivityName;
+    private static String sPackageName;
 
     @Mock private IPackageManager mIPm;
     @Mock private PackageManager mPm;
     @Mock private UserManager mUserManager;
+    @Mock private ApplicationInfo mApplicationInfo;
 
     @Rule
     public ActivityTestRule<IntentForwarderWrapperActivity> mActivityRule =
             new ActivityTestRule<>(IntentForwarderWrapperActivity.class, true, false);
 
     private Context mContext;
+    public static final String PHONE_NUMBER = "123-456-789";
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mContext = InstrumentationRegistry.getTargetContext();
-        sInjector = new TestInjector();
+        sInjector = spy(new TestInjector());
     }
 
     @Test
@@ -252,6 +260,149 @@
         assertEquals(MANAGED_PROFILE_INFO.id, activity.mUserIdActivityLaunchedIn);
     }
 
+    @Test
+    public void shouldSkipDisclosure_notWhitelisted() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_SEND)
+            .setType(TYPE_PLAIN_TEXT);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_withResolverActivity() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        sActivityName = ResolverActivity.class.getName();
+        sPackageName = "android";
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_SEND)
+            .setType(TYPE_PLAIN_TEXT);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_callIntent_call() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_CALL);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_callIntent_dial() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_DIAL);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_callIntent_notCallOrDial() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_ALARM_CHANGED);
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_sms() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_SENDTO)
+            .setData(Uri.fromParts("sms", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_smsto() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_SENDTO)
+            .setData(Uri.fromParts("smsto", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_mms() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_SENDTO)
+            .setData(Uri.fromParts("mms", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_mmsto() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_SENDTO)
+            .setData(Uri.fromParts("mmsto", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector, never()).showToast(anyInt(), anyInt());
+    }
+
+    @Test
+    public void shouldSkipDisclosure_textMessageIntent_invalidUri() throws RemoteException {
+        setupShouldSkipDisclosureTest();
+        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+            .setAction(Intent.ACTION_SENDTO)
+            .setData(Uri.fromParts("invalid", PHONE_NUMBER, null));
+
+        mActivityRule.launchActivity(intent);
+
+        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+        verify(sInjector).showToast(anyInt(), anyInt());
+    }
+
+    private void setupShouldSkipDisclosureTest() throws RemoteException {
+        sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
+        sActivityName = "MyTestActivity";
+        sPackageName = "test.package.name";
+        when(mApplicationInfo.isSystemApp()).thenReturn(true);
+        // Managed profile exists.
+        List<UserInfo> profiles = new ArrayList<>();
+        profiles.add(CURRENT_USER_INFO);
+        profiles.add(MANAGED_PROFILE_INFO);
+        when(mUserManager.getProfiles(anyInt())).thenReturn(profiles);
+        // Intent can be forwarded.
+        when(mIPm.canForwardTo(
+            any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true);
+    }
 
     public static class IntentForwarderWrapperActivity extends IntentForwarderActivity {
         private Intent mStartActivityIntent;
@@ -276,7 +427,7 @@
         }
     }
 
-    class TestInjector implements IntentForwarderActivity.Injector {
+    public class TestInjector implements IntentForwarderActivity.Injector {
 
         @Override
         public IPackageManager getIPackageManager() {
@@ -292,5 +443,21 @@
         public PackageManager getPackageManager() {
             return mPm;
         }
+
+        @Override
+        public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
+            ActivityInfo activityInfo = new ActivityInfo();
+            activityInfo.packageName = sPackageName;
+            activityInfo.name = sActivityName;
+            activityInfo.applicationInfo = mApplicationInfo;
+
+            ResolveInfo resolveInfo = new ResolveInfo();
+            resolveInfo.activityInfo = activityInfo;
+
+            return resolveInfo;
+        }
+
+        @Override
+        public void showToast(int messageId, int duration) {}
     }
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 2f83190..ace6b2d 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -16,7 +16,8 @@
 
 package com.android.internal.os;
 
-import android.content.Context;
+import static org.junit.Assert.assertEquals;
+
 import android.content.Intent;
 import android.os.BatteryManager;
 import android.os.Binder;
@@ -33,17 +34,15 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Random;
 
-import static org.junit.Assert.assertEquals;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 @Presubmit
@@ -91,7 +90,7 @@
         assertEquals(1, uidEntry.recordedCallCount);
         // Still sampled even for another API.
         callStatsList = new ArrayList(uidEntry.getCallStatsList());
-        assertEquals(2, callStatsList.size());
+        assertEquals(1, callStatsList.size());
     }
 
     @Test
@@ -222,20 +221,13 @@
         assertEquals(10, uidEntry.cpuTimeMicros);
 
         List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
-        assertEquals(2, callStatsList.size());
+        assertEquals(1, callStatsList.size());
 
         BinderCallsStats.CallStat callStats = callStatsList.get(0);
         assertEquals(1, callStats.callCount);
         assertEquals(1, callStats.recordedCallCount);
         assertEquals(10, callStats.cpuTimeMicros);
         assertEquals(10, callStats.maxCpuTimeMicros);
-
-        // Only call count should is tracked, rest is sampled.
-        callStats = callStatsList.get(1);
-        assertEquals(1, callStats.callCount);
-        assertEquals(0, callStats.recordedCallCount);
-        assertEquals(0, callStats.cpuTimeMicros);
-        assertEquals(0, callStats.maxCpuTimeMicros);
     }
 
     private static class BinderWithGetTransactionName extends Binder {
@@ -587,6 +579,7 @@
                     };
                 }
             });
+            setSamplingInterval(1);
         }
 
         @Override
diff --git a/data/keyboards/Vendor_054c_Product_0268.kl b/data/keyboards/Vendor_054c_Product_0268.kl
index 7c60137..522db3c 100644
--- a/data/keyboards/Vendor_054c_Product_0268.kl
+++ b/data/keyboards/Vendor_054c_Product_0268.kl
@@ -35,7 +35,7 @@
 key 0x122    BUTTON_THUMBR
 
 # PS key
-key 0x2d0    HOME
+key 0x2d0    BUTTON_MODE
 
 # Left Analog Stick
 axis 0x00    X
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 19af447..3ebbf7e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -37,6 +37,8 @@
 import androidx.annotation.VisibleForTesting;
 import android.util.Log;
 import com.android.internal.R;
+import com.android.internal.util.CollectionUtils;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -87,12 +89,12 @@
     private HfpClientProfile mHfpClientProfile;
     private MapProfile mMapProfile;
     private MapClientProfile mMapClientProfile;
-    private final HidProfile mHidProfile;
+    private HidProfile mHidProfile;
     private HidDeviceProfile mHidDeviceProfile;
     private OppProfile mOppProfile;
-    private final PanProfile mPanProfile;
+    private PanProfile mPanProfile;
     private PbapClientProfile mPbapClientProfile;
-    private final PbapServerProfile mPbapProfile;
+    private PbapServerProfile mPbapProfile;
     private final boolean mUsePbapPce;
     private final boolean mUseMapClient;
     private HearingAidProfile mHearingAidProfile;
@@ -118,177 +120,106 @@
         // pass this reference to adapter and event manager (circular dependency)
         mLocalAdapter.setProfileManager(this);
 
-        ParcelUuid[] uuids = adapter.getUuids();
-
-        // uuids may be null if Bluetooth is turned off
-        if (uuids != null) {
-            updateLocalProfiles(uuids);
-        }
-
-        // Always add HID host, HID device, and PAN profiles
-        mHidProfile = new HidProfile(context, mLocalAdapter, mDeviceManager, this);
-        addProfile(mHidProfile, HidProfile.NAME,
-                BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
-
-        mPanProfile = new PanProfile(context, mLocalAdapter);
-        addPanProfile(mPanProfile, PanProfile.NAME,
-                BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
-
-        mHidDeviceProfile = new HidDeviceProfile(context, mLocalAdapter, mDeviceManager, this);
-        addProfile(mHidDeviceProfile, HidDeviceProfile.NAME,
-                BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED);
-
-        if(DEBUG) Log.d(TAG, "Adding local MAP profile");
-        if (mUseMapClient) {
-            mMapClientProfile = new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
-            addProfile(mMapClientProfile, MapClientProfile.NAME,
-                BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
-        } else {
-            mMapProfile = new MapProfile(mContext, mLocalAdapter, mDeviceManager, this);
-            addProfile(mMapProfile, MapProfile.NAME,
-                    BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
-        }
-
-        //Create PBAP server profile
-        if(DEBUG) Log.d(TAG, "Adding local PBAP profile");
-
-        mPbapProfile = new PbapServerProfile(context);
-        addProfile(mPbapProfile, PbapServerProfile.NAME,
-             BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED);
-
-        List<Integer> supportedList = mLocalAdapter.getSupportedProfiles();
-        if (supportedList.contains(BluetoothProfile.HEARING_AID)) {
-            mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager,
-                                                       this);
-            addProfile(mHearingAidProfile, HearingAidProfile.NAME,
-                       BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
-        }
+        updateLocalProfiles();
         if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete");
     }
 
     /**
-     * Initialize or update the local profile objects. If a UUID was previously
-     * present but has been removed, we print a warning but don't remove the
-     * profile object as it might be referenced elsewhere, or the UUID might
-     * come back and we don't want multiple copies of the profile objects.
-     * @param uuids
+     * create profile instance according to bluetooth supported profile list
      */
-    void updateLocalProfiles(ParcelUuid[] uuids) {
-        // A2DP SRC
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource)) {
-            if (mA2dpProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local A2DP SRC profile");
-                mA2dpProfile = new A2dpProfile(mContext, mLocalAdapter, mDeviceManager, this);
-                addProfile(mA2dpProfile, A2dpProfile.NAME,
-                        BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-            }
-        } else if (mA2dpProfile != null) {
-            Log.w(TAG, "Warning: A2DP profile was previously added but the UUID is now missing.");
+    void updateLocalProfiles() {
+        List<Integer> supportedList = mLocalAdapter.getSupportedProfiles();
+        if (CollectionUtils.isEmpty(supportedList)) {
+            if(DEBUG) Log.d(TAG, "supportedList is null");
+            return;
         }
-
-        // A2DP SINK
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
-            if (mA2dpSinkProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local A2DP Sink profile");
-                mA2dpSinkProfile = new A2dpSinkProfile(mContext, mLocalAdapter, mDeviceManager, this);
-                addProfile(mA2dpSinkProfile, A2dpSinkProfile.NAME,
-                        BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
-            }
-        } else if (mA2dpSinkProfile != null) {
-            Log.w(TAG, "Warning: A2DP Sink profile was previously added but the UUID is now missing.");
+        if (mA2dpProfile == null && supportedList.contains(BluetoothProfile.A2DP)) {
+            if(DEBUG) Log.d(TAG, "Adding local A2DP profile");
+            mA2dpProfile = new A2dpProfile(mContext, mLocalAdapter, mDeviceManager, this);
+            addProfile(mA2dpProfile, A2dpProfile.NAME,
+                    BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
         }
-
-        // Headset / Handsfree
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) ||
-            BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) {
-            if (mHeadsetProfile == null) {
-                if (DEBUG) Log.d(TAG, "Adding local HEADSET profile");
-                mHeadsetProfile = new HeadsetProfile(mContext, mLocalAdapter,
-                        mDeviceManager, this);
-                addHeadsetProfile(mHeadsetProfile, HeadsetProfile.NAME,
-                        BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
-                        BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
-                        BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
-            }
-        } else if (mHeadsetProfile != null) {
-            Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing.");
+        if (mA2dpSinkProfile == null && supportedList.contains(BluetoothProfile.A2DP_SINK)) {
+            if(DEBUG) Log.d(TAG, "Adding local A2DP SINK profile");
+            mA2dpSinkProfile = new A2dpSinkProfile(mContext, mLocalAdapter, mDeviceManager, this);
+            addProfile(mA2dpSinkProfile, A2dpSinkProfile.NAME,
+                    BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
         }
-
-        // Headset HF
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) {
-            if (mHfpClientProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
-                mHfpClientProfile =
-                    new HfpClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
-                addHeadsetProfile(mHfpClientProfile, HfpClientProfile.NAME,
-                        BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED,
-                        BluetoothHeadsetClient.ACTION_AUDIO_STATE_CHANGED,
-                        BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED);
-            }
-        } else if (mHfpClientProfile != null) {
-            Log.w(TAG,
-                "Warning: Hfp Client profile was previously added but the UUID is now missing.");
-        } else {
-            Log.d(TAG, "Handsfree Uuid not found.");
+        if (mHeadsetProfile == null && supportedList.contains(BluetoothProfile.HEADSET)) {
+            if (DEBUG) Log.d(TAG, "Adding local HEADSET profile");
+            mHeadsetProfile = new HeadsetProfile(mContext, mLocalAdapter, mDeviceManager, this);
+            addHeadsetProfile(mHeadsetProfile, HeadsetProfile.NAME,
+                    BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
+                    BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
+                    BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
         }
-
-        // Message Access Profile Client
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.MNS)) {
-            if (mMapClientProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local Map Client profile");
+        if (mHfpClientProfile == null && supportedList.contains(BluetoothProfile.HEADSET_CLIENT)) {
+            if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
+            mHfpClientProfile = new HfpClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
+            addHeadsetProfile(mHfpClientProfile, HfpClientProfile.NAME,
+                    BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED,
+                    BluetoothHeadsetClient.ACTION_AUDIO_STATE_CHANGED,
+                    BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED);
+        }
+        if (mUseMapClient) {
+            if (mMapClientProfile == null && supportedList.contains(BluetoothProfile.MAP_CLIENT)) {
+                if(DEBUG) Log.d(TAG, "Adding local MAP CLIENT profile");
                 mMapClientProfile =
-                        new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
+                        new MapClientProfile(mContext, mLocalAdapter, mDeviceManager,this);
                 addProfile(mMapClientProfile, MapClientProfile.NAME,
                         BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
             }
-        } else if (mMapClientProfile != null) {
-            Log.w(TAG,
-                    "Warning: MAP Client profile was previously added but the UUID is now missing.");
-        } else {
-            Log.d(TAG, "MAP Client Uuid not found.");
+        } else if (mMapProfile == null && supportedList.contains(BluetoothProfile.MAP)) {
+            if(DEBUG) Log.d(TAG, "Adding local MAP profile");
+            mMapProfile = new MapProfile(mContext, mLocalAdapter, mDeviceManager, this);
+            addProfile(mMapProfile, MapProfile.NAME, BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
         }
-
-        // OPP
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
-            if (mOppProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local OPP profile");
-                mOppProfile = new OppProfile();
-                // Note: no event handler for OPP, only name map.
-                mProfileNameMap.put(OppProfile.NAME, mOppProfile);
-            }
-        } else if (mOppProfile != null) {
-            Log.w(TAG, "Warning: OPP profile was previously added but the UUID is now missing.");
+        if (mOppProfile == null && supportedList.contains(BluetoothProfile.OPP)) {
+            if(DEBUG) Log.d(TAG, "Adding local OPP profile");
+            mOppProfile = new OppProfile();
+            // Note: no event handler for OPP, only name map.
+            mProfileNameMap.put(OppProfile.NAME, mOppProfile);
         }
-
-        //PBAP Client
-        if (mUsePbapPce) {
-            if (mPbapClientProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local PBAP Client profile");
-                mPbapClientProfile = new PbapClientProfile(mContext, mLocalAdapter, mDeviceManager,
-                        this);
-                addProfile(mPbapClientProfile, PbapClientProfile.NAME,
-                        BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
-            }
-        } else if (mPbapClientProfile != null) {
-            Log.w(TAG,
-                "Warning: PBAP Client profile was previously added but the UUID is now missing.");
+        if (mHearingAidProfile == null && supportedList.contains(BluetoothProfile.HEARING_AID)) {
+            if(DEBUG) Log.d(TAG, "Adding local Hearing Aid profile");
+            mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager,
+                    this);
+            addProfile(mHearingAidProfile, HearingAidProfile.NAME,
+                    BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
         }
-
-        //Hearing Aid Client
-        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HearingAid)) {
-            if (mHearingAidProfile == null) {
-                if(DEBUG) Log.d(TAG, "Adding local Hearing Aid profile");
-                mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, this);
-                addProfile(mHearingAidProfile, HearingAidProfile.NAME,
-                        BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
-            }
-        } else if (mHearingAidProfile != null) {
-            Log.w(TAG, "Warning: Hearing Aid profile was previously added but the UUID is now missing.");
+        if (mHidProfile == null && supportedList.contains(BluetoothProfile.HID_HOST)) {
+            if(DEBUG) Log.d(TAG, "Adding local HID_HOST profile");
+            mHidProfile = new HidProfile(mContext, mLocalAdapter, mDeviceManager, this);
+            addProfile(mHidProfile, HidProfile.NAME,
+                    BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
         }
-
+        if (mHidDeviceProfile == null && supportedList.contains(BluetoothProfile.HID_DEVICE)) {
+            if(DEBUG) Log.d(TAG, "Adding local HID_DEVICE profile");
+            mHidDeviceProfile = new HidDeviceProfile(mContext, mLocalAdapter, mDeviceManager, this);
+            addProfile(mHidDeviceProfile, HidDeviceProfile.NAME,
+                    BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED);
+        }
+        if (mPanProfile == null && supportedList.contains(BluetoothProfile.PAN)) {
+            if(DEBUG) Log.d(TAG, "Adding local PAN profile");
+            mPanProfile = new PanProfile(mContext, mLocalAdapter);
+            addPanProfile(mPanProfile, PanProfile.NAME,
+                    BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
+        }
+        if (mPbapProfile == null && supportedList.contains(BluetoothProfile.PBAP)) {
+            if(DEBUG) Log.d(TAG, "Adding local PBAP profile");
+            mPbapProfile = new PbapServerProfile(mContext);
+            addProfile(mPbapProfile, PbapServerProfile.NAME,
+                    BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED);
+        }
+        if (mUsePbapPce && mPbapClientProfile == null && supportedList.contains(
+                BluetoothProfile.PBAP_CLIENT)) {
+            if(DEBUG) Log.d(TAG, "Adding local PBAP Client profile");
+            mPbapClientProfile = new PbapClientProfile(mContext, mLocalAdapter, mDeviceManager,
+                    this);
+            addProfile(mPbapClientProfile, PbapClientProfile.NAME,
+                    BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
+        }
         mEventManager.registerProfileIntentReceiver();
-
-        // There is no local SDP record for HID and Settings app doesn't control PBAP Server.
     }
 
     private void addHeadsetProfile(LocalBluetoothProfile profile, String profileName,
@@ -322,10 +253,7 @@
 
     // Called from LocalBluetoothAdapter when state changes to ON
     void setBluetoothStateOn() {
-        ParcelUuid[] uuids = mLocalAdapter.getUuids();
-        if (uuids != null) {
-            updateLocalProfiles(uuids);
-        }
+        updateLocalProfiles();
         mEventManager.readPairedDevices();
     }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index 77fb272..af66f7a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -20,6 +20,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -80,6 +81,10 @@
      */
     @Test
     public void constructor_initiateHidAndHidDeviceProfile() {
+        when(mAdapter.getSupportedProfiles()).thenReturn(
+                generateList(new int[] {BluetoothProfile.HID_HOST}));
+        when(mAdapter.getSupportedProfiles()).thenReturn(
+                generateList(new int[] {BluetoothProfile.HID_HOST, BluetoothProfile.HID_DEVICE}));
         mProfileManager =
                 new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
 
@@ -94,12 +99,12 @@
     public void updateLocalProfiles_addA2dpToLocalProfiles() {
         mProfileManager =
                 new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
         assertThat(mProfileManager.getA2dpProfile()).isNull();
         assertThat(mProfileManager.getHeadsetProfile()).isNull();
 
-        ParcelUuid[] uuids = mAdapter.getUuids();
-        mProfileManager.updateLocalProfiles(uuids);
+        when(mAdapter.getSupportedProfiles()).thenReturn(generateList(
+                new int[] {BluetoothProfile.A2DP}));
+        mProfileManager.updateLocalProfiles();
 
         assertThat(mProfileManager.getA2dpProfile()).isNotNull();
         assertThat(mProfileManager.getHeadsetProfile()).isNull();
@@ -110,6 +115,8 @@
      */
     @Test
     public void updateProfiles_addHidProfileForRemoteDevice() {
+        when(mAdapter.getSupportedProfiles()).thenReturn(generateList(
+                new int[] {BluetoothProfile.HID_HOST}));
         mProfileManager =
                 new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
         ParcelUuid[] uuids = new ParcelUuid[]{BluetoothUuid.Hid};
@@ -131,7 +138,8 @@
      */
     @Test
     public void stateChangedHandler_receiveA2dpConnectionStateChanged_shouldDispatchCallback() {
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
+        when(mAdapter.getSupportedProfiles()).thenReturn(generateList(
+                new int[] {BluetoothProfile.A2DP}));
         mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
                 mEventManager);
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
@@ -154,7 +162,8 @@
      */
     @Test
     public void stateChangedHandler_receiveHeadsetConnectionStateChanged_shouldDispatchCallback() {
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.Handsfree_AG});
+        when(mAdapter.getSupportedProfiles()).thenReturn(generateList(
+                new int[] {BluetoothProfile.HEADSET}));
         mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
                 mEventManager);
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
@@ -203,7 +212,8 @@
      */
     @Test
     public void stateChangedHandler_receivePanConnectionStateChanged_shouldNotDispatchCallback() {
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
+        when(mAdapter.getSupportedProfiles()).thenReturn(
+                generateList(new int[] {BluetoothProfile.PAN}));
         mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
                 mEventManager);
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
@@ -225,8 +235,32 @@
      * handler and refresh CachedBluetoothDevice
      */
     @Test
-    public void stateChangedHandler_receivePanConnectionStateChangedWithoutUuid_shouldNotRefresh() {
-        when(mAdapter.getUuids()).thenReturn(null);
+    public void stateChangedHandler_receivePanConnectionStateChangedWithoutProfile_shouldNotRefresh
+    () {
+        when(mAdapter.getSupportedProfiles()).thenReturn(null);
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
+                mEventManager);
+        // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
+        // LocalBluetoothProfileManager created.
+        mEventManager.setReceiverHandler(null);
+        mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
+        mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
+        mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
+        mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
+
+        mContext.sendBroadcast(mIntent);
+
+        verify(mCachedBluetoothDevice, never()).refresh();
+    }
+
+    /**
+     * Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuids will dispatch to
+     * handler and refresh CachedBluetoothDevice
+     */
+    @Test
+    public void stateChangedHandler_receivePanConnectionStateChangedWithProfile_shouldRefresh() {
+        when(mAdapter.getSupportedProfiles()).thenReturn(generateList(
+                new int[] {BluetoothProfile.PAN}));
         mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
                 mEventManager);
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
@@ -242,25 +276,14 @@
         verify(mCachedBluetoothDevice).refresh();
     }
 
-    /**
-     * Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuids will dispatch to
-     * handler and refresh CachedBluetoothDevice
-     */
-    @Test
-    public void stateChangedHandler_receivePanConnectionStateChangedWithUuids_shouldRefresh() {
-        when(mAdapter.getUuids()).thenReturn(new ParcelUuid[]{BluetoothUuid.AudioSource});
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
-                mEventManager);
-        // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
-        // LocalBluetoothProfileManager created.
-        mEventManager.setReceiverHandler(null);
-        mIntent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
-        mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
-        mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
-        mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
-
-        mContext.sendBroadcast(mIntent);
-
-        verify(mCachedBluetoothDevice).refresh();
+    private List<Integer> generateList(int[] profile) {
+        if (profile == null) {
+            return null;
+        }
+        final List<Integer> profileList = new ArrayList<>(profile.length);
+        for(int i = 0; i < profile.length; i++) {
+            profileList.add(profile[i]);
+        }
+        return profileList;
     }
 }
diff --git a/packages/SystemUI/res-keyguard/values/attrs.xml b/packages/SystemUI/res-keyguard/values/attrs.xml
index e2ce210..293b683 100644
--- a/packages/SystemUI/res-keyguard/values/attrs.xml
+++ b/packages/SystemUI/res-keyguard/values/attrs.xml
@@ -38,9 +38,5 @@
         <attr name="android:textColor" format="color" />
     </declare-styleable>
 
-    <declare-styleable name="CarrierText">
-        <attr name="allCaps" format="boolean" />
-    </declare-styleable>
-
     <attr name="passwordStyle" format="reference" />
 </resources>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index 8e491dc..5b9816d 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -18,7 +18,7 @@
 <!-- Extends RelativeLayout -->
 <com.android.systemui.statusbar.phone.KeyguardStatusBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_header"
     android:layout_width="match_parent"
     android:layout_height="@dimen/status_bar_header_height_keyguard"
@@ -73,6 +73,8 @@
         android:textDirection="locale"
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:textColor="?attr/wallpaperTextColorSecondary"
-        android:singleLine="true" />
+        android:singleLine="true"
+        systemui:showMissingSim="true"
+        systemui:showAirplaneMode="true" />
 
 </com.android.systemui.statusbar.phone.KeyguardStatusBarView>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 49ee952..f50ef82 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -146,5 +146,12 @@
     <!-- Used to style charging animation AVD animation -->
     <attr name="chargingAnimColor" format="color" />
 
+    <!-- Used display CarrierText in Keyguard or QS Footer -->
+    <declare-styleable name="CarrierText">
+        <attr name="allCaps" format="boolean" />
+        <attr name="showMissingSim" format="boolean" />
+        <attr name="showAirplaneMode" format="boolean" />
+    </declare-styleable>
+
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings_car.xml b/packages/SystemUI/res/values/strings_car.xml
index 61d734f..2890cf2 100644
--- a/packages/SystemUI/res/values/strings_car.xml
+++ b/packages/SystemUI/res/values/strings_car.xml
@@ -19,7 +19,9 @@
 <resources>
     <!-- Name of Guest Profile. [CHAR LIMIT=30] -->
     <string name="car_guest">Guest</string>
-    <!-- Name of Add User Profile. [CHAR LIMIT=30] -->
+    <!-- Title for button that starts a guest session. [CHAR LIMIT=30] -->
+    <string name="start_guest_session">Guest</string>
+    <!-- Title for button that  adds a new user. [CHAR LIMIT=30] -->
     <string name="car_add_user">Add User</string>
     <!-- Default name of the new user created. [CHAR LIMIT=30] -->
     <string name="car_new_user">New User</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/DockedStackListenerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/DockedStackListenerCompat.java
new file mode 100644
index 0000000..bb319e6
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/DockedStackListenerCompat.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.system;
+
+import android.view.IDockedStackListener;
+
+/**
+ * An interface to track docked stack changes.
+ */
+public class DockedStackListenerCompat {
+
+    IDockedStackListener.Stub mListener = new IDockedStackListener.Stub() {
+        @Override
+        public void onDividerVisibilityChanged(boolean visible) {}
+
+        @Override
+        public void onDockedStackExistsChanged(boolean exists) {
+            DockedStackListenerCompat.this.onDockedStackExistsChanged(exists);
+        }
+
+        @Override
+        public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
+                boolean isHomeStackResizable) {
+            DockedStackListenerCompat.this.onDockedStackMinimizedChanged(minimized, animDuration,
+                    isHomeStackResizable);
+        }
+
+        @Override
+        public void onAdjustedForImeChanged(boolean adjustedForIme, long animDuration) {}
+
+        @Override
+        public void onDockSideChanged(final int newDockSide) {
+            DockedStackListenerCompat.this.onDockSideChanged(newDockSide);
+        }
+    };
+
+    public void onDockedStackExistsChanged(boolean exists) {
+        // To be overridden
+    }
+
+    public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
+            boolean isHomeStackResizable) {
+        // To be overridden
+    }
+
+    public void onDockSideChanged(final int newDockSide) {
+        // To be overridden
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index ed2f831..d83b36d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -166,4 +166,16 @@
         }
         return NAV_BAR_POS_INVALID;
     }
+
+    /**
+     * Registers a docked stack listener with the system.
+     */
+    public void registerDockedStackListener(DockedStackListenerCompat listener) {
+        try {
+            WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(
+                    listener.mListener);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to register docked stack listener");
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index 66475e2..a0a3687 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -43,11 +43,6 @@
 import android.telephony.TelephonyManager;
 
 public class CarrierText extends TextView {
-    /** Do not show missing sim message. */
-    public static final int FLAG_HIDE_MISSING_SIM = 1 << 0;
-    /** Do not show airplane mode message. */
-    public static final int FLAG_HIDE_AIRPLANE_MODE = 1 << 1;
-
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "CarrierText";
 
@@ -55,17 +50,23 @@
 
     private final boolean mIsEmergencyCallCapable;
 
+    private boolean mTelephonyCapable;
+
+    private boolean mShowMissingSim;
+
+    private boolean mShowAirplaneMode;
+
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
     private WifiManager mWifiManager;
 
     private boolean[] mSimErrorState = new boolean[TelephonyManager.getDefault().getPhoneCount()];
 
-    private int mFlags;
-
-    private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+    private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
         @Override
         public void onRefreshCarrierInfo() {
+            if (DEBUG) Log.d(TAG, "onRefreshCarrierInfo(), mTelephonyCapable: "
+                    + Boolean.toString(mTelephonyCapable));
             updateCarrierText();
         }
 
@@ -77,9 +78,18 @@
             setSelected(true);
         };
 
+        @Override
+        public void onTelephonyCapable(boolean capable) {
+            if (DEBUG) Log.d(TAG, "onTelephonyCapable() mTelephonyCapable: "
+                    + Boolean.toString(capable));
+            mTelephonyCapable = capable;
+            updateCarrierText();
+        }
+
         public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simState) {
             if (slotId < 0) {
-                Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId);
+                Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId
+                        + " mTelephonyCapable: " + Boolean.toString(mTelephonyCapable));
                 return;
             }
 
@@ -91,13 +101,9 @@
                 mSimErrorState[slotId] = false;
                 updateCarrierText();
             }
-        };
+        }
     };
 
-    public void setDisplayFlags(int flags) {
-        mFlags = flags;
-    }
-
     /**
      * The status of this lock screen. Primarily used for widgets on LockScreen.
      */
@@ -110,7 +116,8 @@
         SimLocked, // SIM card is currently locked
         SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
         SimNotReady, // SIM is not ready yet. May never be on devices w/o a SIM.
-        SimIoError; // SIM card is faulty
+        SimIoError, // SIM card is faulty
+        SimUnknown // SIM card is unknown
     }
 
     public CarrierText(Context context) {
@@ -126,6 +133,8 @@
                 attrs, R.styleable.CarrierText, 0, 0);
         try {
             useAllCaps = a.getBoolean(R.styleable.CarrierText_allCaps, false);
+            mShowAirplaneMode = a.getBoolean(R.styleable.CarrierText_showAirplaneMode, false);
+            mShowMissingSim = a.getBoolean(R.styleable.CarrierText_showMissingSim, false);
         } finally {
             a.recycle();
         }
@@ -249,12 +258,12 @@
     }
 
     private String getMissingSimMessage() {
-        return (mFlags & FLAG_HIDE_MISSING_SIM) == 0
+        return mShowMissingSim && mTelephonyCapable
                 ? getContext().getString(R.string.keyguard_missing_sim_message_short) : "";
     }
 
     private String getAirplaneModeMessage() {
-        return (mFlags & FLAG_HIDE_AIRPLANE_MODE) == 0
+        return mShowAirplaneMode
                 ? getContext().getString(R.string.airplane_mode) : "";
     }
 
@@ -360,6 +369,9 @@
                         getContext().getText(R.string.keyguard_sim_error_message_short),
                         text);
                 break;
+            case SimUnknown:
+                carrierText = null;
+                break;
         }
 
         return carrierText;
@@ -408,11 +420,11 @@
             case PERM_DISABLED:
                 return StatusMode.SimPermDisabled;
             case UNKNOWN:
-                return StatusMode.SimMissing;
+                return StatusMode.SimUnknown;
             case CARD_IO_ERROR:
                 return StatusMode.SimIoError;
         }
-        return StatusMode.SimMissing;
+        return StatusMode.SimUnknown;
     }
 
     private static CharSequence concatenate(CharSequence plmn, CharSequence spn) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fa7e814..dfd6a18 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -84,6 +84,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.Preconditions;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.settingslib.WirelessUtils;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
@@ -148,6 +149,7 @@
     private static final int MSG_ASSISTANT_STACK_CHANGED = 335;
     private static final int MSG_BIOMETRIC_AUTHENTICATION_CONTINUE = 336;
     private static final int MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED = 337;
+    private static final int MSG_TELEPHONY_CAPABLE = 338;
 
     /** Biometric authentication state: Not listening. */
     private static final int BIOMETRIC_STATE_STOPPED = 0;
@@ -204,6 +206,8 @@
     private boolean mHasLockscreenWallpaper;
     private boolean mAssistantVisible;
     private boolean mKeyguardOccluded;
+    @VisibleForTesting
+    protected boolean mTelephonyCapable;
 
     // Device provisioning state
     private boolean mDeviceProvisioned;
@@ -344,6 +348,9 @@
                 case MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED:
                     updateLogoutEnabled();
                     break;
+                case MSG_TELEPHONY_CAPABLE:
+                    updateTelephonyCapable((boolean)msg.obj);
+                    break;
                 default:
                     super.handleMessage(msg);
                     break;
@@ -962,14 +969,18 @@
                                 maxChargingMicroWatt));
                 mHandler.sendMessage(msg);
             } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
+                SimData args = SimData.fromIntent(intent);
                 // ACTION_SIM_STATE_CHANGED is rebroadcast after unlocking the device to
                 // keep compatibility with apps that aren't direct boot aware.
                 // SysUI should just ignore this broadcast because it was already received
                 // and processed previously.
                 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
+                    // Guarantee mTelephonyCapable state after SysUI crash and restart
+                    if (args.simState == State.ABSENT) {
+                        mHandler.obtainMessage(MSG_TELEPHONY_CAPABLE, true).sendToTarget();
+                    }
                     return;
                 }
-                SimData args = SimData.fromIntent(intent);
                 if (DEBUG_SIM_STATES) {
                     Log.v(TAG, "action " + action
                         + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE)
@@ -1467,6 +1478,16 @@
         mUserManager = context.getSystemService(UserManager.class);
         mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
         mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
+        updateAirplaneModeState();
+    }
+
+    private void updateAirplaneModeState() {
+        // ACTION_AIRPLANE_MODE_CHANGED do not broadcast if device set AirplaneMode ON and boot
+        if (!WirelessUtils.isAirplaneModeOn(mContext)
+                || mHandler.hasMessages(MSG_AIRPLANE_MODE_CHANGED)) {
+            return;
+        }
+        mHandler.sendEmptyMessage(MSG_AIRPLANE_MODE_CHANGED);
     }
 
     private void updateBiometricListeningState() {
@@ -1823,6 +1844,23 @@
     }
 
     /**
+     * Handle Telephony status during Boot for CarrierText display policy
+     */
+    @VisibleForTesting
+    void updateTelephonyCapable(boolean capable){
+        if (capable == mTelephonyCapable) {
+            return;
+        }
+        mTelephonyCapable = capable;
+        for (WeakReference<KeyguardUpdateMonitorCallback> ref : mCallbacks) {
+            KeyguardUpdateMonitorCallback cb = ref.get();
+            if (cb != null) {
+                cb.onTelephonyCapable(mTelephonyCapable);
+            }
+        }
+    }
+
+    /**
      * Handle {@link #MSG_SIM_STATE_CHANGE}
      */
     @VisibleForTesting
@@ -1835,6 +1873,10 @@
 
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             Log.w(TAG, "invalid subId in handleSimStateChange()");
+            /* Only handle No SIM(ABSENT) due to handleServiceStateChange() handle other case */
+            if (state == State.ABSENT) {
+                updateTelephonyCapable(true);
+            }
             return;
         }
 
@@ -1863,7 +1905,8 @@
     /**
      * Handle {@link #MSG_SERVICE_STATE_CHANGE}
      */
-    private void handleServiceStateChange(int subId, ServiceState serviceState) {
+    @VisibleForTesting
+    void handleServiceStateChange(int subId, ServiceState serviceState) {
         if (DEBUG) {
             Log.d(TAG,
                     "handleServiceStateChange(subId=" + subId + ", serviceState=" + serviceState);
@@ -1872,6 +1915,8 @@
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             Log.w(TAG, "invalid subId in handleServiceStateChange()");
             return;
+        } else {
+            updateTelephonyCapable(true);
         }
 
         mServiceStates.put(subId, serviceState);
@@ -2035,6 +2080,7 @@
         callback.onRefreshCarrierInfo();
         callback.onClockVisibilityChanged();
         callback.onKeyguardVisibilityChangedRaw(mKeyguardIsVisible);
+        callback.onTelephonyCapable(mTelephonyCapable);
         for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
             final SimData state = data.getValue();
             callback.onSimStateChanged(state.subId, state.slotId, state.simState);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 8135ac5..f818d05 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -117,6 +117,12 @@
     public void onUserSwitchComplete(int userId) { }
 
     /**
+     * Called when the Telephony capable
+     * @param capable
+     */
+    public void onTelephonyCapable(boolean capable) { }
+
+    /**
      * Called when the SIM state changes.
      * @param slotId
      * @param simState
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 520e40a..68d77eb 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -43,9 +43,12 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.SystemProperties;
 import android.provider.Settings.Secure;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 import android.view.Gravity;
@@ -60,6 +63,7 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import com.android.internal.util.Preconditions;
 import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
@@ -79,6 +83,9 @@
  * for antialiasing and emulation purposes.
  */
 public class ScreenDecorations extends SystemUI implements Tunable {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "ScreenDecorations";
+
     public static final String SIZE = "sysui_rounded_size";
     public static final String PADDING = "sysui_rounded_content_padding";
     private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
@@ -99,9 +106,23 @@
     private DisplayCutoutView mCutoutBottom;
     private SecureSetting mColorInversionSetting;
     private boolean mPendingRotationChange;
+    private Handler mHandler;
 
     @Override
     public void start() {
+        mHandler = startHandlerThread();
+        mHandler.post(this::startOnScreenDecorationsThread);
+        setupStatusBarPaddingIfNeeded();
+    }
+
+    @VisibleForTesting
+    Handler startHandlerThread() {
+        HandlerThread thread = new HandlerThread("ScreenDecorations");
+        thread.start();
+        return thread.getThreadHandler();
+    }
+
+    private void startOnScreenDecorationsThread() {
         mWindowManager = mContext.getSystemService(WindowManager.class);
         mRoundedDefault = mContext.getResources().getDimensionPixelSize(
                 R.dimen.rounded_corner_radius);
@@ -113,12 +134,6 @@
             setupDecorations();
         }
 
-        int padding = mContext.getResources().getDimensionPixelSize(
-                R.dimen.rounded_corner_content_padding);
-        if (padding != 0) {
-            setupPadding(padding);
-        }
-
         mDisplayListener = new DisplayManager.DisplayListener() {
             @Override
             public void onDisplayAdded(int displayId) {
@@ -132,8 +147,8 @@
 
             @Override
             public void onDisplayChanged(int displayId) {
-                if ((hasRoundedCorners() || shouldDrawCutout()) &&
-                        mRotation != RotationUtils.getExactRotation(mContext)) {
+                final int newRotation = RotationUtils.getExactRotation(mContext);
+                if (mOverlay != null && mBottomOverlay != null && mRotation != newRotation) {
                     // We cannot immediately update the orientation. Otherwise
                     // WindowManager is still deferring layout until it has finished dispatching
                     // the config changes, which may cause divergence between what we draw
@@ -142,10 +157,15 @@
                     // - we are trying to redraw. This because WM resized our window and told us to.
                     // - the config change has been dispatched, so WM is no longer deferring layout.
                     mPendingRotationChange = true;
+                    if (DEBUG) {
+                        Log.i(TAG, "Rotation changed, deferring " + newRotation + ", staying at "
+                                + mRotation);
+                    }
+
                     mOverlay.getViewTreeObserver().addOnPreDrawListener(
-                            new RestartingPreDrawListener(mOverlay));
+                            new RestartingPreDrawListener(mOverlay, newRotation));
                     mBottomOverlay.getViewTreeObserver().addOnPreDrawListener(
-                            new RestartingPreDrawListener(mBottomOverlay));
+                            new RestartingPreDrawListener(mBottomOverlay, newRotation));
                 }
                 updateOrientation();
             }
@@ -154,7 +174,7 @@
         mRotation = -1;
         mDisplayManager = (DisplayManager) mContext.getSystemService(
                 Context.DISPLAY_SERVICE);
-        mDisplayManager.registerDisplayListener(mDisplayListener, null);
+        mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
     }
 
     private void setupDecorations() {
@@ -184,10 +204,11 @@
         mWindowManager.getDefaultDisplay().getMetrics(metrics);
         mDensity = metrics.density;
 
-        Dependency.get(TunerService.class).addTunable(this, SIZE);
+        Dependency.get(Dependency.MAIN_HANDLER).post(
+                () -> Dependency.get(TunerService.class).addTunable(this, SIZE));
 
         // Watch color inversion and invert the overlay as needed.
-        mColorInversionSetting = new SecureSetting(mContext, Dependency.get(Dependency.MAIN_HANDLER),
+        mColorInversionSetting = new SecureSetting(mContext, mHandler,
                 Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
             @Override
             protected void handleValueChanged(int value, boolean observedChange) {
@@ -199,7 +220,7 @@
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_USER_SWITCHED);
-        mContext.registerReceiver(mIntentReceiver, filter);
+        mContext.registerReceiver(mIntentReceiver, filter, null /* permission */, mHandler);
 
         mOverlay.addOnLayoutChangeListener(new OnLayoutChangeListener() {
             @Override
@@ -217,6 +238,11 @@
                         .start();
             }
         });
+
+        mOverlay.getViewTreeObserver().addOnPreDrawListener(
+                new ValidatingPreDrawListener(mOverlay));
+        mBottomOverlay.getViewTreeObserver().addOnPreDrawListener(
+                new ValidatingPreDrawListener(mBottomOverlay));
     }
 
     private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -246,14 +272,28 @@
 
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
-        mPendingRotationChange = false;
-        updateOrientation();
-        if (shouldDrawCutout() && mOverlay == null) {
-            setupDecorations();
-        }
+        mHandler.post(() -> {
+            int oldRotation = mRotation;
+            mPendingRotationChange = false;
+            updateOrientation();
+            if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
+            if (shouldDrawCutout() && mOverlay == null) {
+                setupDecorations();
+            }
+            if (mOverlay != null) {
+                // Updating the layout params ensures that ViewRootImpl will call relayoutWindow(),
+                // which ensures that the forced seamless rotation will end, even if we updated
+                // the rotation before window manager was ready (and was still waiting for sending
+                // the updated rotation).
+                updateLayoutParams();
+            }
+        });
     }
 
-    protected void updateOrientation() {
+    private void updateOrientation() {
+        Preconditions.checkState(mHandler.getLooper().getThread() == Thread.currentThread(),
+                "must call on " + mHandler.getLooper().getThread()
+                        + ", but was " + Thread.currentThread());
         if (mPendingRotationChange) {
             return;
         }
@@ -333,7 +373,19 @@
                 com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout);
     }
 
-    private void setupPadding(int padding) {
+
+    private void setupStatusBarPaddingIfNeeded() {
+        // TODO: This should be moved to a more appropriate place, as it is not related to the
+        // screen decorations overlay.
+        int padding = mContext.getResources().getDimensionPixelSize(
+                R.dimen.rounded_corner_content_padding);
+        if (padding != 0) {
+            setupStatusBarPadding(padding);
+        }
+
+    }
+
+    private void setupStatusBarPadding(int padding) {
         // Add some padding to all the content near the edge of the screen.
         StatusBar sb = getComponent(StatusBar.class);
         View statusBar = (sb != null ? sb.getStatusBarWindow() : null);
@@ -402,30 +454,32 @@
 
     @Override
     public void onTuningChanged(String key, String newValue) {
-        if (mOverlay == null) return;
-        if (SIZE.equals(key)) {
-            int size = mRoundedDefault;
-            int sizeTop = mRoundedDefaultTop;
-            int sizeBottom = mRoundedDefaultBottom;
-            if (newValue != null) {
-                try {
-                    size = (int) (Integer.parseInt(newValue) * mDensity);
-                } catch (Exception e) {
+        mHandler.post(() -> {
+            if (mOverlay == null) return;
+            if (SIZE.equals(key)) {
+                int size = mRoundedDefault;
+                int sizeTop = mRoundedDefaultTop;
+                int sizeBottom = mRoundedDefaultBottom;
+                if (newValue != null) {
+                    try {
+                        size = (int) (Integer.parseInt(newValue) * mDensity);
+                    } catch (Exception e) {
+                    }
                 }
-            }
 
-            if (sizeTop == 0) {
-                sizeTop = size;
-            }
-            if (sizeBottom == 0) {
-                sizeBottom = size;
-            }
+                if (sizeTop == 0) {
+                    sizeTop = size;
+                }
+                if (sizeBottom == 0) {
+                    sizeBottom = size;
+                }
 
-            setSize(mOverlay.findViewById(R.id.left), sizeTop);
-            setSize(mOverlay.findViewById(R.id.right), sizeTop);
-            setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom);
-            setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom);
-        }
+                setSize(mOverlay.findViewById(R.id.left), sizeTop);
+                setSize(mOverlay.findViewById(R.id.right), sizeTop);
+                setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom);
+                setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom);
+            }
+        });
     }
 
     private void setSize(View view, int pixelSize) {
@@ -484,6 +538,11 @@
             mVisibilityChangedListener = visibilityChangedListener;
             mDecorations = decorations;
             setId(R.id.display_cutout);
+            if (DEBUG) {
+                getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
+                        (mInitialStart ? "OverlayTop" : "OverlayBottom")
+                                + " drawn in rot " + mRotation));
+            }
         }
 
         public void setColor(int color) {
@@ -719,20 +778,66 @@
     private class RestartingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
 
         private final View mView;
+        private final int mTargetRotation;
 
-        private RestartingPreDrawListener(View view) {
+        private RestartingPreDrawListener(View view, int targetRotation) {
+            mView = view;
+            mTargetRotation = targetRotation;
+        }
+
+        @Override
+        public boolean onPreDraw() {
+            mView.getViewTreeObserver().removeOnPreDrawListener(this);
+
+            if (mTargetRotation == mRotation) {
+                if (DEBUG) {
+                    Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom")
+                            + " already in target rot "
+                            + mTargetRotation + ", allow draw without restarting it");
+                }
+                return true;
+            }
+
+            mPendingRotationChange = false;
+            // This changes the window attributes - we need to restart the traversal for them to
+            // take effect.
+            updateOrientation();
+            if (DEBUG) {
+                Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom")
+                        + " restarting listener fired, restarting draw for rot " + mRotation);
+            }
+            mView.invalidate();
+            return false;
+        }
+    }
+
+    /**
+     * A pre-draw listener, that validates that the rotation we draw in matches the displays
+     * rotation before continuing the draw.
+     *
+     * This is to prevent a race condition, where we have not received the display changed event
+     * yet, and would thus draw in an old orientation.
+     */
+    private class ValidatingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
+
+        private final View mView;
+
+        public ValidatingPreDrawListener(View view) {
             mView = view;
         }
 
         @Override
         public boolean onPreDraw() {
-            mPendingRotationChange = false;
-            mView.getViewTreeObserver().removeOnPreDrawListener(this);
-            // This changes the window attributes - we need to restart the traversal for them to
-            // take effect.
-            updateOrientation();
-            mView.invalidate();
-            return false;
+            final int displayRotation = RotationUtils.getExactRotation(mContext);
+            if (displayRotation != mRotation && !mPendingRotationChange) {
+                if (DEBUG) {
+                    Log.i(TAG, "Drawing rot " + mRotation + ", but display is at rot "
+                            + displayRotation + ". Restarting draw");
+                }
+                mView.invalidate();
+                return false;
+            }
+            return true;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index a6b065f..f147fb3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -123,8 +123,6 @@
         mMobileSignal = findViewById(R.id.mobile_signal);
         mMobileRoaming = findViewById(R.id.mobile_roaming);
         mCarrierText = findViewById(R.id.qs_carrier_text);
-        mCarrierText.setDisplayFlags(
-                CarrierText.FLAG_HIDE_AIRPLANE_MODE | CarrierText.FLAG_HIDE_MISSING_SIM);
 
         mMultiUserSwitch = findViewById(R.id.multi_user_switch);
         mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 25a55bd..af0ed284 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -101,7 +101,8 @@
             hideUserGrid();
         }
 
-        if (record.mIsForeground) {
+        if (record.mIsForeground || (record.mIsStartGuestSession
+                && mUserManagerHelper.foregroundUserIsGuestUser())) {
             dismissKeyguard();
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 257fa75..23724c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -109,14 +109,12 @@
             userRecords.add(record);
         }
 
-        // Add guest user record if the foreground user is not a guest
-        if (!mUserManagerHelper.foregroundUserIsGuestUser()) {
-            userRecords.add(addGuestUserRecord());
-        }
+        // Add button for starting guest session.
+        userRecords.add(createStartGuestUserRecord());
 
         // Add add user record if the foreground user can add users
         if (mUserManagerHelper.foregroundUserCanAddUsers()) {
-            userRecords.add(addUserRecord());
+            userRecords.add(createAddUserRecord());
         }
 
         return userRecords;
@@ -125,17 +123,17 @@
     /**
      * Create guest user record
      */
-    private UserRecord addGuestUserRecord() {
+    private UserRecord createStartGuestUserRecord() {
         UserInfo userInfo = new UserInfo();
-        userInfo.name = mContext.getString(R.string.car_guest);
-        return new UserRecord(userInfo, true /* isStartGuestSession */,
-                false /* isAddUser */, false /* isForeground */);
+        userInfo.name = mContext.getString(R.string.start_guest_session);
+        return new UserRecord(userInfo, true /* isStartGuestSession */, false /* isAddUser */,
+                false /* isForeground */);
     }
 
     /**
      * Create add user record
      */
-    private UserRecord addUserRecord() {
+    private UserRecord createAddUserRecord() {
         UserInfo userInfo = new UserInfo();
         userInfo.name = mContext.getString(R.string.car_add_user);
         return new UserRecord(userInfo, false /* isStartGuestSession */,
@@ -210,8 +208,6 @@
                     return;
                 }
 
-
-                // If the user selects Guest, start the guest session.
                 if (userRecord.mIsStartGuestSession) {
                     notifyUserSelected(userRecord);
                     mUserManagerHelper.startNewGuestSession(mGuestName);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 042e4ff..b80cd30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -103,9 +103,9 @@
     private float mDarkAmount;
 
     /**
-     * If keyguard will require a password or just fade away.
+     * If keyguard will just fade away or will require a password.
      */
-    private boolean mCurrentlySecure;
+    private boolean mFadeAway;
 
     /**
      * Dozing and receiving a notification (AOD notification.)
@@ -135,7 +135,7 @@
 
     public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
             float panelExpansion, int parentHeight,
-            int keyguardStatusHeight, float dark, boolean secure, boolean pulsing,
+            int keyguardStatusHeight, float dark, boolean fadeAway, boolean pulsing,
             int bouncerTop) {
         mMinTopMargin = minTopMargin + mContainerTopPadding;
         mMaxShadeBottom = maxShadeBottom;
@@ -144,7 +144,7 @@
         mHeight = parentHeight;
         mKeyguardStatusHeight = keyguardStatusHeight;
         mDarkAmount = dark;
-        mCurrentlySecure = secure;
+        mFadeAway = fadeAway;
         mPulsing = pulsing;
         mBouncerTop = bouncerTop;
     }
@@ -198,7 +198,7 @@
 
         float clockYRegular = getExpandedClockPosition();
         boolean hasEnoughSpace = mMinTopMargin + mKeyguardStatusHeight < mBouncerTop;
-        float clockYTarget = mCurrentlySecure && hasEnoughSpace ?
+        float clockYTarget = !mFadeAway && hasEnoughSpace ?
                 mMinTopMargin : -mKeyguardStatusHeight;
 
         // Move clock up while collapsing the shade
@@ -218,11 +218,11 @@
      */
     private float getClockAlpha(int y) {
         float alphaKeyguard;
-        if (mCurrentlySecure) {
-            alphaKeyguard = 1;
-        } else {
+        if (mFadeAway) {
             alphaKeyguard = Math.max(0, y / Math.max(1f, getExpandedClockPosition()));
             alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
+        } else {
+            alphaKeyguard = 1;
         }
         return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index be8bf02..7db5802 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -524,7 +524,8 @@
                     totalHeight,
                     mKeyguardStatusView.getHeight(),
                     mInterpolatedDarkAmount,
-                    mStatusBar.isKeyguardCurrentlySecure(),
+                    !mStatusBar.isKeyguardCurrentlySecure()
+                            || mStatusBar.isKeyguardOccludeAnimationRunning(),
                     mPulsing,
                     mBouncerTop);
             mClockPositionAlgorithm.run(mClockPositionResult);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 4c91a9d..dd4ea3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -322,6 +322,8 @@
     public static final int FADE_KEYGUARD_START_DELAY = 100;
     public static final int FADE_KEYGUARD_DURATION = 300;
     public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
+    public static final int FADE_BACKDROP_DURATION = 300;
+    public static final int FADE_BACKDROP_DURATION_FAST = 240;
 
     /** If true, the system is in the half-boot-to-decryption-screen state.
      * Prudently disable QS and notifications.  */
@@ -543,6 +545,7 @@
     private boolean mIsOccluded;
     private boolean mWereIconsJustHidden;
     private boolean mBouncerWasShowingWhenHidden;
+    private boolean mKeyguardOccludeAnimationRunning;
 
     // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over,
     // this animation is tied to the scrim for historic reasons.
@@ -1641,7 +1644,7 @@
 
         boolean wakeAndUnlock = mBiometricUnlockController != null
             && mBiometricUnlockController.isWakeAndUnlock();
-        if (mLaunchTransitionFadingAway || wakeAndUnlock) {
+        if (mLaunchTransitionFadingAway && !mIsOccluded || wakeAndUnlock) {
             mBackdrop.setVisibility(View.INVISIBLE);
             Trace.endSection();
             return;
@@ -1760,7 +1763,8 @@
                 boolean cannotAnimateDoze = mDozing && !ScrimState.AOD.getAnimateChange();
                 if (mBiometricUnlockController.getMode()
                         == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
-                        || hideBecauseOccluded || cannotAnimateDoze) {
+                        || hideBecauseOccluded  && !mKeyguardOccludeAnimationRunning
+                        || cannotAnimateDoze) {
 
                     // We are unlocking directly - no animation!
                     mBackdrop.setVisibility(View.GONE);
@@ -1771,7 +1775,9 @@
                     mBackdrop.animate()
                             .alpha(SRC_MIN_ALPHA)
                             .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
-                            .setDuration(300)
+                            .setDuration(
+                                    mKeyguardOccludeAnimationRunning
+                                            ? FADE_BACKDROP_DURATION_FAST : FADE_BACKDROP_DURATION)
                             .setStartDelay(0)
                             .withEndAction(() -> {
                                 mBackdrop.setVisibility(View.GONE);
@@ -3668,6 +3674,27 @@
     }
 
     /**
+    * Is keyguard being occluded by a newly launched activity.
+    */
+    public boolean isKeyguardOccludeAnimationRunning() {
+        return mKeyguardOccludeAnimationRunning;
+    }
+
+    /**
+     * Plays the animation when new activity is launched over keyguard.
+     */
+    public void animateKeyguardOccluding() {
+        mKeyguardOccludeAnimationRunning = true;
+        addPostCollapseAction(() -> {
+            mStatusBarKeyguardViewManager.reset(true /* hideBouncerWhenShowing */);
+            mKeyguardOccludeAnimationRunning = false;
+        });
+        mStatusBarKeyguardViewManager.animateCollapsePanels(1.0f /* speedfactor */);
+        updateScrimController();
+        updateMediaMetaData(false /* metaDataChanged */, true /* allowEnterAnimation */);
+    }
+
+    /**
      * Plays the animation when an activity that was occluding Keyguard goes away.
      */
     public void animateKeyguardUnoccluding() {
@@ -4012,7 +4039,7 @@
 
     private void showBouncerIfKeyguard() {
         if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
-                && !mKeyguardViewMediator.isHiding()) {
+                && !mKeyguardViewMediator.isHiding() && !mKeyguardOccludeAnimationRunning) {
             showBouncer(true /* scrimmed */);
         }
     }
@@ -4512,6 +4539,11 @@
 
         @Override
         public void onStartedGoingToSleep() {
+            // in case we start going to sleep while new animation is launching over keyguard, make
+            // sure to finish it
+            if (mKeyguardOccludeAnimationRunning) {
+                runPostCollapseRunnables();
+            }
             notifyHeadsUpGoingToSleep();
             dismissVolumeDialog();
         }
@@ -4753,7 +4785,7 @@
                     ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
             mScrimController.transitionTo(state);
         } else if (isInLaunchTransition() || mLaunchCameraOnScreenTurningOn
-                || launchingAffordanceWithPreview) {
+                || launchingAffordanceWithPreview || mKeyguardOccludeAnimationRunning) {
             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
         } else if (mBrightnessMirrorVisible) {
             mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index c4424d8..97088bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -365,6 +365,11 @@
                             }
                         });
                 return;
+            } else if (animate) {
+                mOccluded = true;
+                mStatusBar.animateKeyguardOccluding();
+                mStatusBarWindowManager.setKeyguardOccluded(mOccluded);
+                return;
             }
         } else if (!occluded && mOccluded && mShowing) {
             StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index a38328a..f83fb43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -144,7 +144,8 @@
                 state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE;
         final boolean keyguardOrAod = state.keyguardShowing
                 || (state.dozing && mDozeParameters.getAlwaysOn());
-        if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) {
+        if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper
+                && !state.keyguardOccluded) {
             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
         } else {
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 1be8322..e604877 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -49,6 +49,7 @@
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS" />
 
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index d46a9747..2055519 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -16,14 +16,22 @@
 
 package com.android.keyguard;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.truth.Truth.*;
+
 import android.content.Context;
 import android.content.Intent;
+import android.os.Bundle;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.SysuiTestCase;
 
@@ -70,6 +78,184 @@
                 keyguardUpdateMonitor.hasSimStateJustChanged());
     }
 
+    @Test
+    public void testTelephonyCapable_BootInitState() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimState_Absent() {
+        Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_ABSENT);
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent,null, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isTrue();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimInvalid_ServiceState_InService() {
+        // SERVICE_STATE - IN_SERVICE, but SIM_STATE is invalid TelephonyCapable should be False
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_IN_SERVICE);
+        state.fillInNotifierBundle(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimValid_ServiceState_PowerOff() {
+        // Simulate AirplaneMode case, SERVICE_STATE - POWER_OFF, check TelephonyCapable False
+        // Only receive ServiceState callback IN_SERVICE -> OUT_OF_SERVICE -> POWER_OFF
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_LOADED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_POWER_OFF);
+        state.fillInNotifierBundle(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, true));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isTrue();
+    }
+
+    /* Normal SIM inserted flow
+     * ServiceState:    ---OutOfServie----->PowerOff->OutOfServie--->InService
+     * SimState:        ----NOT_READY---->READY----------------------LOADED>>>
+     * Subscription:    --------null---->null--->"Chunghwa Telecom"-------->>>
+     * System:          -------------------------------BOOT_COMPLETED------>>>
+     * TelephonyCapable:(F)-(F)-(F)-(F)-(F)-(F)-(F)-(F)-(F)-(F)------(T)-(T)>>
+     */
+    @Test
+    public void testTelephonyCapable_BootInitState_ServiceState_OutOfService() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_OUT_OF_SERVICE);
+        state.fillInNotifierBundle(data);
+        intent.putExtras(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_BootInitState_SimState_NotReady() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_OUT_OF_SERVICE);
+        state.fillInNotifierBundle(data);
+        Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_NOT_READY);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_BootInitState_SimState_Ready() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_OUT_OF_SERVICE);
+        state.fillInNotifierBundle(data);
+        Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_READY);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_BootInitState_ServiceState_PowerOff() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_POWER_OFF);
+        state.fillInNotifierBundle(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, false));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimValid_ServiceState_InService() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_IN_SERVICE);
+        state.fillInNotifierBundle(data);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intent, data, true));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isTrue();
+    }
+
+    @Test
+    public void testTelephonyCapable_SimValid_SimState_Loaded() {
+        TestableKeyguardUpdateMonitor keyguardUpdateMonitor =
+                new TestableKeyguardUpdateMonitor(getContext());
+        Bundle data = new Bundle();
+        ServiceState state = new ServiceState();
+        state.setState(ServiceState.STATE_IN_SERVICE);
+        state.fillInNotifierBundle(data);
+        Intent intentSimState = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        intentSimState.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_LOADED);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intentSimState, data, true));
+        mTestableLooper.processAllMessages();
+        // Even SimState Loaded, still need ACTION_SERVICE_STATE_CHANGED turn on mTelephonyCapable
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isFalse();
+
+        Intent intentServiceState =  new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        intentSimState.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE
+                , IccCardConstants.INTENT_VALUE_ICC_LOADED);
+        keyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
+                , putPhoneInfo(intentServiceState, data, true));
+        mTestableLooper.processAllMessages();
+        assertThat(keyguardUpdateMonitor.mTelephonyCapable).isTrue();
+    }
+
+    private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
+        int subscription = simInited
+                ? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE;
+        if (data != null) intent.putExtras(data);
+        intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
+        intent.putExtra("subscription", subscription);
+        intent.putExtra("slot", 0/* SLOT 1 */);
+        return intent;
+    }
+
     private class TestableKeyguardUpdateMonitor extends KeyguardUpdateMonitor {
         AtomicBoolean mSimStateChanged = new AtomicBoolean(false);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index f1bf31d..644c0b3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -34,8 +34,10 @@
 
 import android.app.Fragment;
 import android.content.res.Configuration;
+import android.os.Handler;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.Display;
 import android.view.View;
@@ -60,6 +62,7 @@
 @SmallTest
 public class ScreenDecorationsTest extends SysuiTestCase {
 
+    private TestableLooper mTestableLooper;
     private ScreenDecorations mScreenDecorations;
     private StatusBar mStatusBar;
     private WindowManager mWindowManager;
@@ -71,6 +74,10 @@
 
     @Before
     public void setup() {
+        mTestableLooper = TestableLooper.get(this);
+        mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
+                new Handler(mTestableLooper.getLooper()));
+
         mStatusBar = mock(StatusBar.class);
         mWindowManager = mock(WindowManager.class);
         mView = spy(new StatusBarWindowView(mContext, null));
@@ -88,7 +95,31 @@
 
         mTunerService = mDependency.injectMockDependency(TunerService.class);
 
-        mScreenDecorations = new ScreenDecorations();
+
+        mScreenDecorations = new ScreenDecorations() {
+            @Override
+            public void start() {
+                super.start();
+                mTestableLooper.processAllMessages();
+            }
+
+            @Override
+            Handler startHandlerThread() {
+                return new Handler(mTestableLooper.getLooper());
+            }
+
+            @Override
+            protected void onConfigurationChanged(Configuration newConfig) {
+                super.onConfigurationChanged(newConfig);
+                mTestableLooper.processAllMessages();
+            }
+
+            @Override
+            public void onTuningChanged(String key, String newValue) {
+                super.onTuningChanged(key, newValue);
+                mTestableLooper.processAllMessages();
+            }
+        };
         mScreenDecorations.mContext = mContext;
         mScreenDecorations.mComponents = mContext.getComponents();
 
diff --git a/services/art-profile b/services/art-profile
index 24964f3..cbc00ea 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -9258,24 +9258,24 @@
 PLcom/android/server/backup/internal/BackupState;-><init>(Ljava/lang/String;I)V
 PLcom/android/server/backup/internal/BackupState;->values()[Lcom/android/server/backup/internal/BackupState;
 PLcom/android/server/backup/internal/Operation;-><init>(ILcom/android/server/backup/BackupRestoreTask;I)V
-PLcom/android/server/backup/internal/KeyValueBackupTask;-><init>(Lcom/android/server/backup/BackupManagerService;Lcom/android/server/backup/transport/TransportClient;Ljava/lang/String;Ljava/util/List;Lcom/android/server/backup/DataChangedJournal;Landroid/app/backup/IBackupObserver;Landroid/app/backup/IBackupManagerMonitor;Lcom/android/server/backup/internal/OnTaskFinishedListener;Ljava/util/List;ZZ)V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->backupPm()V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->beginBackup()V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->clearAgentState()V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->execute()V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->executeNextState(Lcom/android/server/backup/internal/BackupState;)V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->finalizeBackup()V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->invokeAgentForBackup(Ljava/lang/String;Landroid/app/IBackupAgent;)I
-PLcom/android/server/backup/internal/KeyValueBackupTask;->invokeNextAgent()V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->operationComplete(J)V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->registerTask()V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->revertAndEndBackup()V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->unregisterTask()V
-PLcom/android/server/backup/internal/KeyValueBackupTask;->writeWidgetPayloadIfAppropriate(Ljava/io/FileDescriptor;Ljava/lang/String;)V
 PLcom/android/server/backup/internal/ProvisionedObserver;-><init>(Lcom/android/server/backup/BackupManagerService;Landroid/os/Handler;)V
 PLcom/android/server/backup/internal/RunBackupReceiver;-><init>(Lcom/android/server/backup/BackupManagerService;)V
 PLcom/android/server/backup/internal/RunBackupReceiver;->onReceive(Landroid/content/Context;Landroid/content/Intent;)V
 PLcom/android/server/backup/internal/RunInitializeReceiver;-><init>(Lcom/android/server/backup/BackupManagerService;)V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;-><init>(Lcom/android/server/backup/BackupManagerService;Lcom/android/server/backup/transport/TransportClient;Ljava/lang/String;Ljava/util/List;Lcom/android/server/backup/DataChangedJournal;Landroid/app/backup/IBackupObserver;Landroid/app/backup/IBackupManagerMonitor;Lcom/android/server/backup/internal/OnTaskFinishedListener;Ljava/util/List;ZZ)V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->backupPm()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->beginBackup()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->clearAgentState()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->execute()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->executeNextState(Lcom/android/server/backup/internal/BackupState;)V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->finalizeBackup()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->invokeAgentForBackup(Ljava/lang/String;Landroid/app/IBackupAgent;)I
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->invokeNextAgent()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->operationComplete(J)V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->registerTask()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->revertAndEndBackup()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->unregisterTask()V
+PLcom/android/server/backup/keyvalue/KeyValueBackupTask;->writeWidgetPayloadIfAppropriate(Ljava/io/FileDescriptor;Ljava/lang/String;)V
 PLcom/android/server/backup/transport/-$$Lambda$TransportClient$ciIUj0x0CRg93UETUpy2FB5aqCQ;-><init>(Lcom/android/server/backup/transport/TransportClient;Lcom/android/server/backup/transport/TransportConnectionListener;Lcom/android/internal/backup/IBackupTransport;)V
 PLcom/android/server/backup/transport/-$$Lambda$TransportClient$ciIUj0x0CRg93UETUpy2FB5aqCQ;->run()V
 PLcom/android/server/backup/transport/-$$Lambda$TransportClient$uc3fygwQjQIS_JT7mlt-yMBfJcE;-><init>(Ljava/util/concurrent/CompletableFuture;)V
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index ec27da9..c26ac17 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -104,7 +104,7 @@
 import com.android.server.backup.fullbackup.FullBackupEntry;
 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
 import com.android.server.backup.internal.BackupHandler;
-import com.android.server.backup.internal.BackupRequest;
+import com.android.server.backup.keyvalue.BackupRequest;
 import com.android.server.backup.internal.ClearDataObserver;
 import com.android.server.backup.internal.OnTaskFinishedListener;
 import com.android.server.backup.internal.Operation;
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index 6e96fe0..2722729 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -41,6 +41,8 @@
 import com.android.server.backup.TransportManager;
 import com.android.server.backup.fullbackup.PerformAdbBackupTask;
 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
+import com.android.server.backup.keyvalue.BackupRequest;
+import com.android.server.backup.keyvalue.KeyValueBackupTask;
 import com.android.server.backup.params.AdbBackupParams;
 import com.android.server.backup.params.AdbParams;
 import com.android.server.backup.params.AdbRestoreParams;
diff --git a/services/backup/java/com/android/server/backup/internal/BackupState.java b/services/backup/java/com/android/server/backup/internal/BackupState.java
deleted file mode 100644
index 320b555..0000000
--- a/services/backup/java/com/android/server/backup/internal/BackupState.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.android.server.backup.internal;
-
-/**
- * Current state of the backup.
- */
-enum BackupState {
-    INITIAL,
-    BACKUP_PM,
-    RUNNING_QUEUE,
-    CANCELLED,
-    FINAL
-}
diff --git a/services/backup/java/com/android/server/backup/internal/BackupRequest.java b/services/backup/java/com/android/server/backup/keyvalue/BackupRequest.java
similarity index 96%
rename from services/backup/java/com/android/server/backup/internal/BackupRequest.java
rename to services/backup/java/com/android/server/backup/keyvalue/BackupRequest.java
index 01e4385..67b2f72 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupRequest.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/BackupRequest.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.server.backup.internal;
+package com.android.server.backup.keyvalue;
 
 import java.util.Objects;
 
diff --git a/services/backup/java/com/android/server/backup/internal/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
similarity index 99%
rename from services/backup/java/com/android/server/backup/internal/KeyValueBackupTask.java
rename to services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 54b8d1f..113e2b6 100644
--- a/services/backup/java/com/android/server/backup/internal/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.server.backup.internal;
+package com.android.server.backup.keyvalue;
 
 import static com.android.server.backup.BackupManagerService.DEBUG_BACKUP_TRACE;
 import static com.android.server.backup.BackupManagerService.KEY_WIDGET_STATE;
@@ -62,6 +62,8 @@
 import com.android.server.backup.DataChangedJournal;
 import com.android.server.backup.KeyValueBackupJob;
 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
+import com.android.server.backup.internal.OnTaskFinishedListener;
+import com.android.server.backup.internal.Operation;
 import com.android.server.backup.remote.RemoteCall;
 import com.android.server.backup.remote.RemoteCallable;
 import com.android.server.backup.remote.RemoteResult;
@@ -1351,4 +1353,12 @@
         mPendingCall = null;
         return result;
     }
+
+    private enum BackupState {
+        INITIAL,
+        BACKUP_PM,
+        RUNNING_QUEUE,
+        CANCELLED,
+        FINAL
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 9b9a380..59beef2 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -21,7 +21,10 @@
 import static android.net.CaptivePortal.APP_RETURN_WANTED_AS_IS;
 import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;
 import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL;
+import static android.net.metrics.ValidationProbeEvent.DNS_FAILURE;
+import static android.net.metrics.ValidationProbeEvent.DNS_SUCCESS;
 import static android.net.metrics.ValidationProbeEvent.PROBE_FALLBACK;
+import static android.net.metrics.ValidationProbeEvent.PROBE_PRIVDNS;
 
 import android.annotation.Nullable;
 import android.app.PendingIntent;
@@ -799,8 +802,10 @@
                 final InetAddress[] ips = ResolvUtil.blockingResolveAllLocally(
                         mNetwork, mPrivateDnsProviderHostname, 0 /* aiFlags */);
                 mPrivateDnsConfig = new PrivateDnsConfig(mPrivateDnsProviderHostname, ips);
+                validationLog("Strict mode hostname resolved: " + mPrivateDnsConfig);
             } catch (UnknownHostException uhe) {
                 mPrivateDnsConfig = null;
+                validationLog("Strict mode hostname resolution failed: " + uhe.getMessage());
             }
         }
 
@@ -829,10 +834,21 @@
             final String ONE_TIME_HOSTNAME_SUFFIX = "-dnsotls-ds.metric.gstatic.com";
             final String host = UUID.randomUUID().toString().substring(0, 8) +
                     ONE_TIME_HOSTNAME_SUFFIX;
+            final Stopwatch watch = new Stopwatch().start();
             try {
                 final InetAddress[] ips = mNetworkAgentInfo.network().getAllByName(host);
-                return (ips != null && ips.length > 0);
-            } catch (UnknownHostException uhe) {}
+                final long time = watch.stop();
+                final String strIps = Arrays.toString(ips);
+                final boolean success = (ips != null && ips.length > 0);
+                validationLog(PROBE_PRIVDNS, host, String.format("%dms: %s", time, strIps));
+                logValidationProbe(time, PROBE_PRIVDNS, success ? DNS_SUCCESS : DNS_FAILURE);
+                return success;
+            } catch (UnknownHostException uhe) {
+                final long time = watch.stop();
+                validationLog(PROBE_PRIVDNS, host,
+                        String.format("%dms - Error: %s", time, uhe.getMessage()));
+                logValidationProbe(time, PROBE_PRIVDNS, DNS_FAILURE);
+            }
             return false;
         }
     }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 0b7c5b9..260633a 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -32,6 +32,7 @@
 import android.app.job.JobProtoEnums;
 import android.app.job.JobScheduler;
 import android.app.job.JobService;
+import android.app.job.JobSnapshot;
 import android.app.job.JobWorkItem;
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
@@ -2724,6 +2725,55 @@
                 (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
                         this, in, out, err, args, callback, resultReceiver);
         }
+
+        /**
+         * <b>For internal system user only!</b>
+         * Returns a list of all currently-executing jobs.
+         */
+        @Override
+        public List<JobInfo> getStartedJobs() {
+            final int uid = Binder.getCallingUid();
+            if (uid != Process.SYSTEM_UID) {
+                throw new SecurityException(
+                    "getStartedJobs() is system internal use only.");
+            }
+
+            final ArrayList<JobInfo> runningJobs;
+
+            synchronized (mLock) {
+                runningJobs = new ArrayList<>(mActiveServices.size());
+                for (JobServiceContext jsc : mActiveServices) {
+                    final JobStatus job = jsc.getRunningJobLocked();
+                    if (job != null) {
+                        runningJobs.add(job.getJob());
+                    }
+                }
+            }
+
+            return runningJobs;
+        }
+
+        /**
+         * <b>For internal system user only!</b>
+         * Returns a snapshot of the state of all jobs known to the system.
+         *
+         * <p class="note">This is a slow operation, so it should be called sparingly.
+         */
+        @Override
+        public List<JobSnapshot> getAllJobSnapshots() {
+            final int uid = Binder.getCallingUid();
+            if (uid != Process.SYSTEM_UID) {
+                throw new SecurityException(
+                    "getAllJobSnapshots() is system internal use only.");
+            }
+            synchronized (mLock) {
+                final ArrayList<JobSnapshot> snapshots = new ArrayList<>(mJobs.size());
+                mJobs.forEachJob((job) -> snapshots.add(
+                        new JobSnapshot(job.getJob(), job.getSatisfiedConstraintFlags(),
+                                isReadyToBeExecutedLocked(job))));
+                return snapshots;
+            }
+        }
     };
 
     // Shell command infrastructure: run the given job immediately
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index a1e066e..3f8941d 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -694,6 +694,10 @@
         mInternalFlags |= flags;
     }
 
+    public int getSatisfiedConstraintFlags() {
+        return satisfiedConstraints;
+    }
+
     public void maybeAddForegroundExemption(Predicate<Integer> uidForegroundChecker) {
         // Jobs with time constraints shouldn't be exempted.
         if (job.hasEarlyConstraint() || job.hasLateConstraint()) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index a8b92a6..966684a6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2445,13 +2445,11 @@
                 attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
                 break;
             case TYPE_STATUS_BAR:
-
                 // If the Keyguard is in a hidden state (occluded by another window), we force to
-                // remove the wallpaper and keyguard flag so that any change in-flight after setting
-                // the keyguard as occluded wouldn't set these flags again.
+                // remove the keyguard flag so that any change in-flight after setting
+                // the keyguard as occluded wouldn't set the flag again.
                 // See {@link #processKeyguardSetHiddenResultLw}.
                 if (mKeyguardOccluded) {
-                    attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
                     attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
                 }
                 break;
@@ -5511,17 +5509,13 @@
             mKeyguardDelegate.setOccluded(false, true /* animate */);
             if (mStatusBar != null) {
                 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
-                if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
-                    mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
-                }
             }
             return true;
         } else if (isOccluded && changed && showing) {
             mKeyguardOccluded = true;
-            mKeyguardDelegate.setOccluded(true, false /* animate */);
+            mKeyguardDelegate.setOccluded(true, !mShowingDream /* animate */);
             if (mStatusBar != null) {
                 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
-                mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
             }
             return true;
         } else if (changed) {
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
index 39e28c7..3199ed4 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceShellCommand.java
@@ -66,6 +66,12 @@
     private int setWebViewImplementation() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         String shellChosenPackage = getNextArg();
+        if (shellChosenPackage == null) {
+            pw.println("Failed to switch, no PACKAGE provided.");
+            pw.println("");
+            helpSetWebViewImplementation();
+            return 1;
+        }
         String newPackage = mInterface.changeProviderAndSetting(shellChosenPackage);
         if (shellChosenPackage.equals(newPackage)) {
             pw.println("Success");
@@ -85,6 +91,12 @@
         return 0;
     }
 
+    public void helpSetWebViewImplementation() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("  set-webview-implementation PACKAGE");
+        pw.println("    Set the WebView implementation to the specified package.");
+    }
+
     @Override
     public void onHelp() {
         PrintWriter pw = getOutPrintWriter();
@@ -99,8 +111,7 @@
         pw.println("  disable-redundant-packages");
         pw.println("    Disallow installing and enabling fallback packages when a more-preferred");
         pw.println("    package is available.");
-        pw.println("  set-webview-implementation PACKAGE");
-        pw.println("    Set the WebView implementation to the specified package.");
+        helpSetWebViewImplementation();
         pw.println("  enable-multiprocess");
         pw.println("    Enable multi-process mode for WebView");
         pw.println("  disable-multiprocess");
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index d73606f..7ee35e7 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -1557,7 +1557,7 @@
         if (isKeyguardGoingAwayTransit(transit) && enter) {
             a = loadKeyguardExitAnimation(transit);
         } else if (transit == TRANSIT_KEYGUARD_OCCLUDE) {
-            a = null;
+            a = loadAnimationRes(lp, com.android.internal.R.anim.keyguard_occlude_open_enter);
         } else if (transit == TRANSIT_KEYGUARD_UNOCCLUDE && !enter) {
             a = loadAnimationRes(lp, com.android.internal.R.anim.wallpaper_open_exit);
         } else if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
diff --git a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java
index ad745a2..f5e6e72 100644
--- a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java
+++ b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java
@@ -21,9 +21,13 @@
 
 import android.graphics.Matrix;
 import android.view.DisplayInfo;
+import android.view.Surface.Rotation;
 
 import com.android.server.wm.utils.CoordinateTransforms;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
 /**
  * Helper class for forced seamless rotation.
  *
@@ -37,8 +41,13 @@
 
     private final Matrix mTransform = new Matrix();
     private final float[] mFloat9 = new float[9];
+    private final int mOldRotation;
+    private final int mNewRotation;
 
     public ForcedSeamlessRotator(int oldRotation, int newRotation, DisplayInfo info) {
+        mOldRotation = oldRotation;
+        mNewRotation = newRotation;
+
         final boolean flipped = info.rotation == ROTATION_90 || info.rotation == ROTATION_270;
         final int h = flipped ? info.logicalWidth : info.logicalHeight;
         final int w = flipped ? info.logicalHeight : info.logicalWidth;
@@ -58,6 +67,16 @@
     }
 
     /**
+     * Returns the rotation of the display before it started rotating.
+     *
+     * @return the old rotation of the display
+     */
+    @Rotation
+    public int getOldRotation() {
+        return mOldRotation;
+    }
+
+    /**
      * Removes the transform to the window token's surface that undoes the effect of the global
      * display rotation.
      *
@@ -77,4 +96,16 @@
                     win.getFrameNumber());
         }
     }
+
+    public void dump(PrintWriter pw) {
+        pw.print("{old="); pw.print(mOldRotation); pw.print(", new="); pw.print(mNewRotation);
+        pw.print("}");
+    }
+
+    @Override
+    public String toString() {
+        StringWriter sw = new StringWriter();
+        dump(new PrintWriter(sw));
+        return "ForcedSeamlessRotator" + sw.toString();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 3a0cc28..b5566a7 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -315,12 +315,9 @@
     @VisibleForTesting
     AnimationAdapter addAnimation(Task task, boolean isRecentTaskInvisible) {
         if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "addAnimation(" + task.getName() + ")");
-        // TODO: Refactor this to use the task's animator
-        final SurfaceAnimator anim = new SurfaceAnimator(task, null /* animationFinishedCallback */,
-                mService);
         final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task,
                 isRecentTaskInvisible);
-        anim.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
+        task.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
         task.commitPendingTransaction();
         mPendingAnimations.add(taskAdapter);
         return taskAdapter;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d53610b..0015693 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1901,6 +1901,7 @@
             // TODO(b/111504081): Consolidate seamless rotation logic.
             if (win.mPendingForcedSeamlessRotate != null && !mWaitingForConfig) {
                 win.mPendingForcedSeamlessRotate.finish(win.mToken, win);
+                win.mFinishForcedSeamlessRotateFrameNumber = win.getFrameNumber();
                 win.mPendingForcedSeamlessRotate = null;
             }
 
@@ -6925,10 +6926,8 @@
 
     @Override
     public void registerDockedStackListener(IDockedStackListener listener) {
-        if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
-                "registerDockedStackListener()")) {
-            return;
-        }
+        mAtmInternal.enforceCallerIsRecentsOrHasPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
+                "registerDockedStackListener()");
         synchronized (mWindowMap) {
             // TODO(multi-display): The listener is registered on the default display only.
             getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9f394ac..58fb7a0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -122,6 +122,7 @@
 import static com.android.server.wm.WindowStateProto.CONTENT_INSETS;
 import static com.android.server.wm.WindowStateProto.DESTROYING;
 import static com.android.server.wm.WindowStateProto.DISPLAY_ID;
+import static com.android.server.wm.WindowStateProto.FINISHED_FORCED_SEAMLESS_ROTATION_FRAME;
 import static com.android.server.wm.WindowStateProto.GIVEN_CONTENT_INSETS;
 import static com.android.server.wm.WindowStateProto.HAS_SURFACE;
 import static com.android.server.wm.WindowStateProto.IDENTIFIER;
@@ -130,6 +131,7 @@
 import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
 import static com.android.server.wm.WindowStateProto.OUTSETS;
 import static com.android.server.wm.WindowStateProto.OVERSCAN_INSETS;
+import static com.android.server.wm.WindowStateProto.PENDING_FORCED_SEAMLESS_ROTATION;
 import static com.android.server.wm.WindowStateProto.REMOVED;
 import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT;
 import static com.android.server.wm.WindowStateProto.REQUESTED_HEIGHT;
@@ -281,6 +283,7 @@
      */
     final boolean mForceSeamlesslyRotate;
     ForcedSeamlessRotator mPendingForcedSeamlessRotate;
+    long mFinishForcedSeamlessRotateFrameNumber;
 
     private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
 
@@ -631,6 +634,10 @@
 
     void forceSeamlesslyRotateIfAllowed(int oldRotation, int rotation) {
         if (mForceSeamlesslyRotate) {
+            if (mPendingForcedSeamlessRotate != null) {
+                oldRotation = mPendingForcedSeamlessRotate.getOldRotation();
+            }
+
             mPendingForcedSeamlessRotate = new ForcedSeamlessRotator(
                     oldRotation, rotation, getDisplayInfo());
             mPendingForcedSeamlessRotate.unrotate(this.mToken);
@@ -3294,6 +3301,11 @@
         proto.write(REMOVED, mRemoved);
         proto.write(IS_ON_SCREEN, isOnScreen());
         proto.write(IS_VISIBLE, isVisible());
+        if (mForceSeamlesslyRotate) {
+            proto.write(PENDING_FORCED_SEAMLESS_ROTATION, mPendingForcedSeamlessRotate != null);
+            proto.write(FINISHED_FORCED_SEAMLESS_ROTATION_FRAME,
+                    mFinishForcedSeamlessRotateFrameNumber);
+        }
         proto.end(token);
     }
 
@@ -3449,6 +3461,16 @@
             pw.print(prefix); pw.print("mLastFreezeDuration=");
                     TimeUtils.formatDuration(mLastFreezeDuration, pw); pw.println();
         }
+        if (mForceSeamlesslyRotate) {
+            pw.print(prefix); pw.print("forceSeamlesslyRotate: pending=");
+            if (mPendingForcedSeamlessRotate != null) {
+                mPendingForcedSeamlessRotate.dump(pw);
+            } else {
+                pw.print("null");
+            }
+            pw.print(" finishedFrameNumber="); pw.print(mFinishForcedSeamlessRotateFrameNumber);
+            pw.println();
+        }
         if (mHScale != 1 || mVScale != 1) {
             pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
                     pw.print(" mVScale="); pw.println(mVScale);
diff --git a/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp b/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp
index 81d46f3..777d344 100644
--- a/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp
+++ b/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp
@@ -106,7 +106,7 @@
         mQueueCond.notify_one();
     }
 
-    if (mThread.get_id() == std::thread::id()) {
+    if (mThread.get_id() == std::this_thread::get_id()) {
         // you can't self-join a thread, but it's ok when calling from our sub-task
         ALOGD("About to stop native callback thread %p", this);
         mThread.detach();
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index ea9967b..2e0ae02 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -45,7 +45,7 @@
 import android.os.PowerSaveState;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import com.android.server.backup.internal.BackupRequest;
+import com.android.server.backup.keyvalue.BackupRequest;
 import com.android.server.backup.testing.BackupManagerServiceTestUtils;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
diff --git a/services/robotests/src/com/android/server/backup/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
similarity index 98%
rename from services/robotests/src/com/android/server/backup/KeyValueBackupTaskTest.java
rename to services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 56f5f15..fde9bc8 100644
--- a/services/robotests/src/com/android/server/backup/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.server.backup;
+package com.android.server.backup.keyvalue;
 
 import static android.app.backup.BackupManager.ERROR_AGENT_FAILURE;
 import static android.app.backup.BackupManager.ERROR_BACKUP_NOT_ALLOWED;
@@ -25,9 +25,12 @@
 import static android.app.backup.ForwardingBackupAgent.forward;
 
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createInitializedBackupManagerService;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBinderCallerAndApplicationAsSystem;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils
+        .createInitializedBackupManagerService;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils
+        .setUpBackupManagerServiceBasics;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils
+        .setUpBinderCallerAndApplicationAsSystem;
 import static com.android.server.backup.testing.PackageData.PM_PACKAGE;
 import static com.android.server.backup.testing.PackageData.fullBackupPackage;
 import static com.android.server.backup.testing.PackageData.keyValuePackage;
@@ -90,10 +93,14 @@
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
+import com.android.server.backup.BackupManagerService;
+import com.android.server.backup.BackupRestoreTask;
+import com.android.server.backup.DataChangedJournal;
+import com.android.server.backup.KeyValueBackupJob;
+import com.android.server.backup.PackageManagerBackupAgent;
+import com.android.server.backup.TransportManager;
 import com.android.server.backup.internal.BackupHandler;
-import com.android.server.backup.internal.BackupRequest;
 import com.android.server.backup.internal.OnTaskFinishedListener;
-import com.android.server.backup.internal.KeyValueBackupTask;
 import com.android.server.backup.testing.PackageData;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils;
@@ -1795,10 +1802,10 @@
      *   <li>The transport being initialized with {@link IBackupTransport#initializeDevice()}
      *   <li>{@link BackupManagerService#resetBackupState(File)} being called, which will:
      *       <ul>
-     *         <li>Call {@link ProcessedPackagesJournal#reset()}
-     *         <li>Reset current token to 0
-     *         <li>Delete state files
-     *         <li>Mark data changed for every key-value participant
+     *         <li>Reset processed packages journal.
+     *         <li>Reset current token to 0.
+     *         <li>Delete state files.
+     *         <li>Mark data changed for every key-value participant.
      *       </ul>
      * </ul>
      */
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
index f22cdb8..838902d 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
@@ -22,15 +22,14 @@
 
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.DataChangedJournal;
-import com.android.server.backup.internal.BackupRequest;
 import com.android.server.backup.internal.OnTaskFinishedListener;
-import com.android.server.backup.internal.KeyValueBackupTask;
+import com.android.server.backup.keyvalue.BackupRequest;
+import com.android.server.backup.keyvalue.KeyValueBackupTask;
 import com.android.server.backup.transport.TransportClient;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
-import java.util.ArrayList;
 import java.util.List;
 
 @Implements(KeyValueBackupTask.class)
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1dfe5df..ab94093 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -224,6 +224,13 @@
     public static final String
             KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
 
+    /**
+     * A string array containing numbers that shouldn't be included in the call log.
+     * @hide
+     */
+    public static final String KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY =
+            "unloggable_numbers_string_array";
+
     /** If true, removes the Voice Privacy option from Call Settings */
     public static final String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
 
@@ -2041,6 +2048,7 @@
         sDefaults.putBoolean(KEY_AUTO_RETRY_FAILED_WIFI_EMERGENCY_CALL, false);
         sDefaults.putBoolean(KEY_ADDITIONAL_CALL_SETTING_BOOL, true);
         sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL, false);
+        sDefaults.putStringArray(KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_ALLOW_LOCAL_DTMF_TONES_BOOL, true);
         sDefaults.putBoolean(KEY_PLAY_CALL_RECORDING_TONE_BOOL, false);
         sDefaults.putBoolean(KEY_APN_EXPAND_BOOL, true);
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index a5ee8e3..2b172da 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -16,17 +16,32 @@
 
 package android.net;
 
-import android.net.NetworkUtils;
-import android.test.suitebuilder.annotation.SmallTest;
+import static android.net.NetworkUtils.getImplicitNetmask;
+import static android.net.NetworkUtils.inet4AddressToIntHTH;
+import static android.net.NetworkUtils.inet4AddressToIntHTL;
+import static android.net.NetworkUtils.intToInet4AddressHTH;
+import static android.net.NetworkUtils.intToInet4AddressHTL;
+import static android.net.NetworkUtils.netmaskToPrefixLength;
+import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTH;
+import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTL;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.fail;
+
+import android.support.test.runner.AndroidJUnit4;
 
 import java.math.BigInteger;
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.util.TreeSet;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class NetworkUtilsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@android.support.test.filters.SmallTest
+public class NetworkUtilsTest {
 
     private InetAddress Address(String addr) {
         return InetAddress.parseNumericAddress(addr);
@@ -36,41 +51,126 @@
         return (Inet4Address) Address(addr);
     }
 
-    @SmallTest
+    @Test
     public void testGetImplicitNetmask() {
-        assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("4.2.2.2")));
-        assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("10.5.6.7")));
-        assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("173.194.72.105")));
-        assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("172.23.68.145")));
-        assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.0.2.1")));
-        assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.168.5.1")));
-        assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("224.0.0.1")));
-        assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("255.6.7.8")));
+        assertEquals(8, getImplicitNetmask(IPv4Address("4.2.2.2")));
+        assertEquals(8, getImplicitNetmask(IPv4Address("10.5.6.7")));
+        assertEquals(16, getImplicitNetmask(IPv4Address("173.194.72.105")));
+        assertEquals(16, getImplicitNetmask(IPv4Address("172.23.68.145")));
+        assertEquals(24, getImplicitNetmask(IPv4Address("192.0.2.1")));
+        assertEquals(24, getImplicitNetmask(IPv4Address("192.168.5.1")));
+        assertEquals(32, getImplicitNetmask(IPv4Address("224.0.0.1")));
+        assertEquals(32, getImplicitNetmask(IPv4Address("255.6.7.8")));
     }
 
     private void assertInvalidNetworkMask(Inet4Address addr) {
         try {
-            NetworkUtils.netmaskToPrefixLength(addr);
+            netmaskToPrefixLength(addr);
             fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception");
         } catch (IllegalArgumentException expected) {
         }
     }
 
-    @SmallTest
+    @Test
+    public void testInet4AddressToIntHTL() {
+        assertEquals(0, inet4AddressToIntHTL(IPv4Address("0.0.0.0")));
+        assertEquals(0x000080ff, inet4AddressToIntHTL(IPv4Address("255.128.0.0")));
+        assertEquals(0x0080ff0a, inet4AddressToIntHTL(IPv4Address("10.255.128.0")));
+        assertEquals(0x00feff0a, inet4AddressToIntHTL(IPv4Address("10.255.254.0")));
+        assertEquals(0xfeffa8c0, inet4AddressToIntHTL(IPv4Address("192.168.255.254")));
+        assertEquals(0xffffa8c0, inet4AddressToIntHTL(IPv4Address("192.168.255.255")));
+    }
+
+    @Test
+    public void testIntToInet4AddressHTL() {
+        assertEquals(IPv4Address("0.0.0.0"), intToInet4AddressHTL(0));
+        assertEquals(IPv4Address("255.128.0.0"), intToInet4AddressHTL(0x000080ff));
+        assertEquals(IPv4Address("10.255.128.0"), intToInet4AddressHTL(0x0080ff0a));
+        assertEquals(IPv4Address("10.255.254.0"), intToInet4AddressHTL(0x00feff0a));
+        assertEquals(IPv4Address("192.168.255.254"), intToInet4AddressHTL(0xfeffa8c0));
+        assertEquals(IPv4Address("192.168.255.255"), intToInet4AddressHTL(0xffffa8c0));
+    }
+
+    @Test
+    public void testInet4AddressToIntHTH() {
+        assertEquals(0, inet4AddressToIntHTH(IPv4Address("0.0.0.0")));
+        assertEquals(0xff800000, inet4AddressToIntHTH(IPv4Address("255.128.0.0")));
+        assertEquals(0x0aff8000, inet4AddressToIntHTH(IPv4Address("10.255.128.0")));
+        assertEquals(0x0afffe00, inet4AddressToIntHTH(IPv4Address("10.255.254.0")));
+        assertEquals(0xc0a8fffe, inet4AddressToIntHTH(IPv4Address("192.168.255.254")));
+        assertEquals(0xc0a8ffff, inet4AddressToIntHTH(IPv4Address("192.168.255.255")));
+    }
+
+    @Test
+    public void testIntToInet4AddressHTH() {
+        assertEquals(IPv4Address("0.0.0.0"), intToInet4AddressHTH(0));
+        assertEquals(IPv4Address("255.128.0.0"), intToInet4AddressHTH(0xff800000));
+        assertEquals(IPv4Address("10.255.128.0"), intToInet4AddressHTH(0x0aff8000));
+        assertEquals(IPv4Address("10.255.254.0"), intToInet4AddressHTH(0x0afffe00));
+        assertEquals(IPv4Address("192.168.255.254"), intToInet4AddressHTH(0xc0a8fffe));
+        assertEquals(IPv4Address("192.168.255.255"), intToInet4AddressHTH(0xc0a8ffff));
+    }
+
+    @Test
     public void testNetmaskToPrefixLength() {
-        assertEquals(0, NetworkUtils.netmaskToPrefixLength(IPv4Address("0.0.0.0")));
-        assertEquals(9, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.128.0.0")));
-        assertEquals(17, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.128.0")));
-        assertEquals(23, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.254.0")));
-        assertEquals(31, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.254")));
-        assertEquals(32, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.255")));
+        assertEquals(0, netmaskToPrefixLength(IPv4Address("0.0.0.0")));
+        assertEquals(9, netmaskToPrefixLength(IPv4Address("255.128.0.0")));
+        assertEquals(17, netmaskToPrefixLength(IPv4Address("255.255.128.0")));
+        assertEquals(23, netmaskToPrefixLength(IPv4Address("255.255.254.0")));
+        assertEquals(31, netmaskToPrefixLength(IPv4Address("255.255.255.254")));
+        assertEquals(32, netmaskToPrefixLength(IPv4Address("255.255.255.255")));
 
         assertInvalidNetworkMask(IPv4Address("0.0.0.1"));
         assertInvalidNetworkMask(IPv4Address("255.255.255.253"));
         assertInvalidNetworkMask(IPv4Address("255.255.0.255"));
     }
 
-    @SmallTest
+
+    @Test
+    public void testPrefixLengthToV4NetmaskIntHTL() {
+        assertEquals(0, prefixLengthToV4NetmaskIntHTL(0));
+        assertEquals(0x000080ff /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTL(9));
+        assertEquals(0x0080ffff /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTL(17));
+        assertEquals(0x00feffff /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTL(23));
+        assertEquals(0xfeffffff /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTL(31));
+        assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTL(32));
+    }
+
+    @Test
+    public void testPrefixLengthToV4NetmaskIntHTH() {
+        assertEquals(0, prefixLengthToV4NetmaskIntHTH(0));
+        assertEquals(0xff800000 /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTH(9));
+        assertEquals(0xffff8000 /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTH(17));
+        assertEquals(0xfffffe00 /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTH(23));
+        assertEquals(0xfffffffe /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTH(31));
+        assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTH(32));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testPrefixLengthToV4NetmaskIntHTH_NegativeLength() {
+        prefixLengthToV4NetmaskIntHTH(-1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testPrefixLengthToV4NetmaskIntHTH_LengthTooLarge() {
+        prefixLengthToV4NetmaskIntHTH(33);
+    }
+
+    private void checkAddressMasking(String expectedAddr, String addr, int prefixLength) {
+        final int prefix = prefixLengthToV4NetmaskIntHTH(prefixLength);
+        final int addrInt = inet4AddressToIntHTH(IPv4Address(addr));
+        assertEquals(IPv4Address(expectedAddr), intToInet4AddressHTH(prefix & addrInt));
+    }
+
+    @Test
+    public void testPrefixLengthToV4NetmaskIntHTH_MaskAddr() {
+        checkAddressMasking("192.168.0.0", "192.168.128.1", 16);
+        checkAddressMasking("255.240.0.0", "255.255.255.255", 12);
+        checkAddressMasking("255.255.255.255", "255.255.255.255", 32);
+        checkAddressMasking("0.0.0.0", "255.255.255.255", 0);
+    }
+
+    @Test
     public void testRoutedIPv4AddressCount() {
         final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
         // No routes routes to no addresses.
@@ -118,7 +218,7 @@
         assertEquals(7l - 4 + 4 + 16 + 65536, NetworkUtils.routedIPv4AddressCount(set));
     }
 
-    @SmallTest
+    @Test
     public void testRoutedIPv6AddressCount() {
         final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
         // No routes routes to no addresses.