Merge "Use pointer width from res before getWidth is ready" into qt-dev
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 8191d37..bbd3dca 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1264,7 +1264,7 @@
     // This method only sends data, it does not receive it.
     pid_t pid = IPCThreadState::self()->getCallingPid();
     uid_t uid = IPCThreadState::self()->getCallingUid();
-        // Root, system, and shell always have access
+    // Root, system, and shell always have access
     if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) {
         // Caller must be granted these permissions
         if (!checkCallingPermission(String16(kPermissionDump))) {
@@ -1349,6 +1349,64 @@
     return Status::ok();
 }
 
+Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackTypeIn,
+                                                      const android::String16& packageNameIn,
+                                                      const int64_t packageVersionCodeIn) {
+    // Note: We skip the usage stats op check here since we do not have a package name.
+    // This is ok since we are overloading the usage_stats permission.
+    // This method only sends data, it does not receive it.
+    pid_t pid = IPCThreadState::self()->getCallingPid();
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+    // Root, system, and shell always have access
+    if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) {
+        // Caller must be granted these permissions
+        if (!checkCallingPermission(String16(kPermissionDump))) {
+            return exception(binder::Status::EX_SECURITY,
+                             StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
+                                          kPermissionDump));
+        }
+        if (!checkCallingPermission(String16(kPermissionUsage))) {
+            return exception(binder::Status::EX_SECURITY,
+                             StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
+                                          kPermissionUsage));
+        }
+    }
+
+    android::util::stats_write(android::util::WATCHDOG_ROLLBACK_OCCURRED,
+            rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn);
+
+    // Fast return to save disk read.
+    if (rollbackTypeIn != android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS
+            && rollbackTypeIn !=
+                    android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE) {
+        return Status::ok();
+    }
+
+    bool readTrainInfoSuccess = false;
+    InstallTrainInfo trainInfoOnDisk;
+    readTrainInfoSuccess = StorageManager::readTrainInfo(trainInfoOnDisk);
+
+    if (!readTrainInfoSuccess) {
+        return Status::ok();
+    }
+    std::vector<int64_t> experimentIds = trainInfoOnDisk.experimentIds;
+    if (experimentIds.empty()) {
+        return Status::ok();
+    }
+    switch (rollbackTypeIn) {
+        case android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE:
+            experimentIds.push_back(experimentIds[0] + 4);
+            break;
+        case android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS:
+            experimentIds.push_back(experimentIds[0] + 5);
+            break;
+    }
+    StorageManager::writeTrainInfo(trainInfoOnDisk.trainVersionCode, trainInfoOnDisk.trainName,
+            trainInfoOnDisk.status, experimentIds);
+    return Status::ok();
+}
+
+
 Status StatsService::getRegisteredExperimentIds(std::vector<int64_t>* experimentIdsOut) {
     uid_t uid = IPCThreadState::self()->getCallingUid();
 
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index a4e6d7f..8d8514f 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -196,6 +196,14 @@
             const std::vector<int64_t>& experimentIdsIn) override;
 
     /**
+     * Binder call to log WatchdogRollbackOccurred atom.
+     */
+    virtual Status sendWatchdogRollbackOccurredAtom(
+            const int32_t rollbackTypeIn,
+            const android::String16& packageNameIn,
+            const int64_t packageVersionCodeIn) override;
+
+    /**
      * Binder call to get registered experiment IDs.
      */
     virtual Status getRegisteredExperimentIds(std::vector<int64_t>* expIdsOut);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 24df883..7646c3c 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -994,6 +994,19 @@
 
     // Name of source package (for historical reasons, since BatteryStats tracked it).
     optional string package_name = 3;
+
+    // These enum values match the STANDBY_BUCKET_XXX constants defined in UsageStatsManager.java.
+    enum Bucket {
+        UNKNOWN = 0;
+        EXEMPTED = 5;
+        ACTIVE = 10;
+        WORKING_SET = 20;
+        FREQUENT = 30;
+        RARE = 40;
+        NEVER = 50;
+    }
+    // The App Standby bucket of the app that scheduled the alarm at the time the alarm fired.
+    optional Bucket app_standby_bucket = 4;
 }
 
 /**
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index c267e77..82d0fbe 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1431,8 +1431,6 @@
 Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCDMA:Landroid/util/SparseIntArray;
 Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCommon:Landroid/util/SparseIntArray;
 Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableGSM:Landroid/util/SparseIntArray;
-Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->translate(Ljava/lang/CharSequence;)Ljava/lang/String;
-Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->useCdmaFormatForMoSms()Z
 Lcom/android/internal/telephony/SmsApplication$SmsApplicationData;->mApplicationName:Ljava/lang/String;
 Lcom/android/internal/telephony/SmsApplication;->configurePreferredActivity(Landroid/content/pm/PackageManager;Landroid/content/ComponentName;I)V
 Lcom/android/internal/telephony/SmsApplication;->getApplicationCollection(Landroid/content/Context;)Ljava/util/Collection;
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 5a69e6b..376a211 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -844,6 +844,13 @@
      */
     public abstract void forEachPackage(Consumer<PackageParser.Package> actionLocked);
 
+    /**
+     * Perform the given action for each installed package for a user.
+     * Note that packages lock will be held while performin the actions.
+     */
+    public abstract void forEachInstalledPackage(
+            @NonNull Consumer<PackageParser.Package> actionLocked, @UserIdInt int userId);
+
     /** Returns the list of enabled components */
     public abstract ArraySet<String> getEnabledComponents(String packageName, int userId);
 
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3bc40a7..fbfbfc0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3449,6 +3449,11 @@
             final NetworkCallback callback;
             synchronized (sCallbacks) {
                 callback = sCallbacks.get(request);
+                if (callback == null) {
+                    Log.w(TAG,
+                            "callback not found for " + getCallbackName(message.what) + " message");
+                    return;
+                }
                 if (message.what == CALLBACK_UNAVAIL) {
                     sCallbacks.remove(request);
                     callback.networkRequest = ALREADY_UNREGISTERED;
@@ -3457,10 +3462,6 @@
             if (DBG) {
                 Log.d(TAG, getCallbackName(message.what) + " for network " + network);
             }
-            if (callback == null) {
-                Log.w(TAG, "callback not found for " + getCallbackName(message.what) + " message");
-                return;
-            }
 
             switch (message.what) {
                 case CALLBACK_PRECHECK: {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1c97407..deb9eba 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -132,10 +132,24 @@
      * <a href="/training/articles/security-key-attestation.html">key attestation</a> to obtain
      * proof of the device's original identifiers.
      *
-     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
-     * device or profile owner and have the READ_PHONE_STATE permission. Profile owner access is
-     * deprecated and will be removed in a future release.
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). The profile
+     * owner is an app that owns a managed profile on the device; for more details see <a
+     * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
+     * access is deprecated and will be removed in a future release.
      *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then {@link Build#UNKNOWN} is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
+     * *
      * @return The serial number if specified.
      */
     @SuppressAutoDoc // No support for device / profile owner.
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index 311c86d..a596fdc 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -219,6 +219,12 @@
          in int options, in int state, in long[] experimentId);
 
     /**
+     * Logs an event for watchdog rollbacks.
+     */
+     oneway void sendWatchdogRollbackOccurredAtom(in int rollbackType, in String packageName,
+         in long packageVersionCode);
+
+    /**
      * Returns the most recently registered experiment IDs.
      */
     long[] getRegisteredExperimentIds();
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index cfc092c..f7077bb 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -23,7 +23,6 @@
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
-import android.app.IActivityManager;
 import android.content.Context;
 import android.os.IStatsManager;
 import android.os.RemoteException;
@@ -159,10 +158,6 @@
                     }
                     return false;
                 }
-                int userId = IActivityManager.Stub.asInterface(
-                        ServiceManager.getService("activity"))
-                        .getCurrentUser()
-                        .id;
                 service.sendBinaryPushStateChangedAtom(
                         trainName, trainVersionCode, options, state, experimentIds);
                 return true;
@@ -178,6 +173,46 @@
         }
     }
 
+    /**
+     * Logs an event for watchdog rollbacks.
+     *
+     * @param rollbackType          state of the rollback.
+     * @param packageName           package name being rolled back.
+     * @param packageVersionCode    version of the package being rolled back.
+     *
+     * @return True if the log request was sent to statsd.
+     *
+     * @hide
+     */
+    @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
+    public static boolean logWatchdogRollbackOccurred(int rollbackType, String packageName,
+            long packageVersionCode) {
+        synchronized (sLogLock) {
+            try {
+                IStatsManager service = getIStatsManagerLocked();
+                if (service == null) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Failed to find statsd when logging event");
+                    }
+                    return false;
+                }
+
+                service.sendWatchdogRollbackOccurredAtom(rollbackType, packageName,
+                        packageVersionCode);
+                return true;
+            } catch (RemoteException e) {
+                sService = null;
+                if (DEBUG) {
+                    Slog.d(TAG,
+                            "Failed to connect to StatsCompanionService when logging "
+                                    + "WatchdogRollbackOccurred");
+                }
+                return false;
+            }
+        }
+    }
+
+
     private static IStatsManager getIStatsManagerLocked() throws RemoteException {
         if (sService != null) {
             return sService;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a6d0dee..bf6191e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -21509,23 +21509,27 @@
         }
 
         saveCount = canvas.getSaveCount();
+        int topSaveCount = -1;
+        int bottomSaveCount = -1;
+        int leftSaveCount = -1;
+        int rightSaveCount = -1;
 
         int solidColor = getSolidColor();
         if (solidColor == 0) {
             if (drawTop) {
-                canvas.saveUnclippedLayer(left, top, right, top + length);
+                topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
             }
 
             if (drawBottom) {
-                canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
+                bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
             }
 
             if (drawLeft) {
-                canvas.saveUnclippedLayer(left, top, left + length, bottom);
+                leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
             }
 
             if (drawRight) {
-                canvas.saveUnclippedLayer(right - length, top, right, bottom);
+                rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
             }
         } else {
             scrollabilityCache.setFadeColor(solidColor);
@@ -21542,21 +21546,19 @@
         final Matrix matrix = scrollabilityCache.matrix;
         final Shader fade = scrollabilityCache.shader;
 
-        if (drawTop) {
-            matrix.setScale(1, fadeHeight * topFadeStrength);
-            matrix.postTranslate(left, top);
+        // must be restored in the reverse order that they were saved
+        if (drawRight) {
+            matrix.setScale(1, fadeHeight * rightFadeStrength);
+            matrix.postRotate(90);
+            matrix.postTranslate(right, top);
             fade.setLocalMatrix(matrix);
             p.setShader(fade);
-            canvas.drawRect(left, top, right, top + length, p);
-        }
+            if (solidColor == 0) {
+                canvas.restoreUnclippedLayer(rightSaveCount, p);
 
-        if (drawBottom) {
-            matrix.setScale(1, fadeHeight * bottomFadeStrength);
-            matrix.postRotate(180);
-            matrix.postTranslate(left, bottom);
-            fade.setLocalMatrix(matrix);
-            p.setShader(fade);
-            canvas.drawRect(left, bottom - length, right, bottom, p);
+            } else {
+                canvas.drawRect(right - length, top, right, bottom, p);
+            }
         }
 
         if (drawLeft) {
@@ -21565,16 +21567,36 @@
             matrix.postTranslate(left, top);
             fade.setLocalMatrix(matrix);
             p.setShader(fade);
-            canvas.drawRect(left, top, left + length, bottom, p);
+            if (solidColor == 0) {
+                canvas.restoreUnclippedLayer(leftSaveCount, p);
+            } else {
+                canvas.drawRect(left, top, left + length, bottom, p);
+            }
         }
 
-        if (drawRight) {
-            matrix.setScale(1, fadeHeight * rightFadeStrength);
-            matrix.postRotate(90);
-            matrix.postTranslate(right, top);
+        if (drawBottom) {
+            matrix.setScale(1, fadeHeight * bottomFadeStrength);
+            matrix.postRotate(180);
+            matrix.postTranslate(left, bottom);
             fade.setLocalMatrix(matrix);
             p.setShader(fade);
-            canvas.drawRect(right - length, top, right, bottom, p);
+            if (solidColor == 0) {
+                canvas.restoreUnclippedLayer(bottomSaveCount, p);
+            } else {
+                canvas.drawRect(left, bottom - length, right, bottom, p);
+            }
+        }
+
+        if (drawTop) {
+            matrix.setScale(1, fadeHeight * topFadeStrength);
+            matrix.postTranslate(left, top);
+            fade.setLocalMatrix(matrix);
+            p.setShader(fade);
+            if (solidColor == 0) {
+                canvas.restoreUnclippedLayer(topSaveCount, p);
+            } else {
+                canvas.drawRect(left, top, right, top + length, p);
+            }
         }
 
         canvas.restoreToCount(saveCount);
diff --git a/core/java/android/view/textclassifier/SelectionEvent.java b/core/java/android/view/textclassifier/SelectionEvent.java
index 105cbcc..9ae0c65 100644
--- a/core/java/android/view/textclassifier/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/SelectionEvent.java
@@ -24,6 +24,7 @@
 import android.view.textclassifier.TextClassifier.EntityType;
 import android.view.textclassifier.TextClassifier.WidgetType;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
@@ -115,7 +116,7 @@
     /** Unknown invocation method */
     public static final int INVOCATION_UNKNOWN = 0;
 
-    private static final String NO_SIGNATURE = "";
+    static final String NO_SIGNATURE = "";
 
     private final int mAbsoluteStart;
     private final int mAbsoluteEnd;
@@ -374,8 +375,10 @@
 
     /**
      * Sets the event type.
+     * @hide
      */
-    void setEventType(@EventType int eventType) {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public void setEventType(@EventType int eventType) {
         mEventType = eventType;
     }
 
@@ -416,8 +419,10 @@
 
     /**
      * Sets the {@link TextClassificationContext} for this event.
+     * @hide
      */
-    void setTextClassificationSessionContext(TextClassificationContext context) {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public void setTextClassificationSessionContext(TextClassificationContext context) {
         mPackageName = context.getPackageName();
         mWidgetType = context.getWidgetType();
         mWidgetVersion = context.getWidgetVersion();
@@ -432,8 +437,10 @@
 
     /**
      * Sets the invocationMethod for this event.
+     * @hide
      */
-    void setInvocationMethod(@InvocationMethod int invocationMethod) {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public void setInvocationMethod(@InvocationMethod int invocationMethod) {
         mInvocationMethod = invocationMethod;
     }
 
@@ -495,7 +502,9 @@
         return mEventIndex;
     }
 
-    SelectionEvent setEventIndex(int index) {
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public SelectionEvent setEventIndex(int index) {
         mEventIndex = index;
         return this;
     }
@@ -508,7 +517,9 @@
         return mSessionId;
     }
 
-    SelectionEvent setSessionId(TextClassificationSessionId id) {
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public SelectionEvent setSessionId(@Nullable TextClassificationSessionId id) {
         mSessionId = id;
         return this;
     }
@@ -521,7 +532,9 @@
         return mStart;
     }
 
-    SelectionEvent setStart(int start) {
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public SelectionEvent setStart(int start) {
         mStart = start;
         return this;
     }
@@ -534,7 +547,9 @@
         return mEnd;
     }
 
-    SelectionEvent setEnd(int end) {
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public SelectionEvent setEnd(int end) {
         mEnd = end;
         return this;
     }
@@ -547,7 +562,9 @@
         return mSmartStart;
     }
 
-    SelectionEvent setSmartStart(int start) {
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public SelectionEvent setSmartStart(int start) {
         this.mSmartStart = start;
         return this;
     }
@@ -560,7 +577,9 @@
         return mSmartEnd;
     }
 
-    SelectionEvent setSmartEnd(int end) {
+    /** @hide */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public SelectionEvent setSmartEnd(int end) {
         mSmartEnd = end;
         return this;
     }
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index 15f54ef..db0202a 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -84,6 +84,7 @@
     @Override
     public void onTextClassifierEvent(TextClassifierEvent event) {
         try {
+            event.mHiddenTempSessionId = mSessionId;
             mDelegate.onTextClassifierEvent(event);
         } catch (Exception e) {
             // Avoid crashing for event reporting.
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index 7b623e9..57da829 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -24,6 +24,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
@@ -150,6 +151,14 @@
     private final ULocale mLocale;
     private final Bundle mExtras;
 
+    /**
+     * Session id holder to help with converting this event to the legacy SelectionEvent.
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @Nullable
+    public TextClassificationSessionId mHiddenTempSessionId;
+
     private TextClassifierEvent(Builder builder) {
         mEventCategory = builder.mEventCategory;
         mEventType = builder.mEventType;
@@ -360,6 +369,120 @@
     }
 
     /**
+     * Returns a {@link SelectionEvent} equivalent of this event; or {@code null} if it can not be
+     * converted to a {@link SelectionEvent}.
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @Nullable
+    public final SelectionEvent toSelectionEvent() {
+        final int invocationMethod;
+        switch (getEventCategory()) {
+            case TextClassifierEvent.CATEGORY_SELECTION:
+                invocationMethod = SelectionEvent.INVOCATION_MANUAL;
+                break;
+            case TextClassifierEvent.CATEGORY_LINKIFY:
+                invocationMethod = SelectionEvent.INVOCATION_LINK;
+                break;
+            default:
+                // Cannot be converted to a SelectionEvent.
+                return null;
+        }
+
+        final String entityType = getEntityTypes().length > 0
+                ? getEntityTypes()[0] : TextClassifier.TYPE_UNKNOWN;
+        final SelectionEvent out = new SelectionEvent(
+                /* absoluteStart= */ 0,
+                /* absoluteEnd= */ 0,
+                /* eventType= */0,
+                entityType,
+                SelectionEvent.INVOCATION_UNKNOWN,
+                SelectionEvent.NO_SIGNATURE);
+        out.setInvocationMethod(invocationMethod);
+
+        final TextClassificationContext eventContext = getEventContext();
+        if (eventContext != null) {
+            out.setTextClassificationSessionContext(getEventContext());
+        }
+        out.setSessionId(mHiddenTempSessionId);
+        final String resultId = getResultId();
+        out.setResultId(resultId == null ? SelectionEvent.NO_SIGNATURE : resultId);
+        out.setEventIndex(getEventIndex());
+
+
+        final int eventType;
+        switch (getEventType()) {
+            case TextClassifierEvent.TYPE_SELECTION_STARTED:
+                eventType = SelectionEvent.EVENT_SELECTION_STARTED;
+                break;
+            case TextClassifierEvent.TYPE_SELECTION_MODIFIED:
+                eventType = SelectionEvent.EVENT_SELECTION_MODIFIED;
+                break;
+            case TextClassifierEvent.TYPE_SMART_SELECTION_SINGLE:
+                eventType = SelectionEvent.EVENT_SMART_SELECTION_SINGLE;
+                break;
+            case TextClassifierEvent.TYPE_SMART_SELECTION_MULTI:
+                eventType = SelectionEvent.EVENT_SMART_SELECTION_MULTI;
+                break;
+            case TextClassifierEvent.TYPE_AUTO_SELECTION:
+                eventType = SelectionEvent.EVENT_AUTO_SELECTION;
+                break;
+            case TextClassifierEvent.TYPE_OVERTYPE:
+                eventType = SelectionEvent.ACTION_OVERTYPE;
+                break;
+            case TextClassifierEvent.TYPE_COPY_ACTION:
+                eventType = SelectionEvent.ACTION_COPY;
+                break;
+            case TextClassifierEvent.TYPE_PASTE_ACTION:
+                eventType = SelectionEvent.ACTION_PASTE;
+                break;
+            case TextClassifierEvent.TYPE_CUT_ACTION:
+                eventType = SelectionEvent.ACTION_CUT;
+                break;
+            case TextClassifierEvent.TYPE_SHARE_ACTION:
+                eventType = SelectionEvent.ACTION_SHARE;
+                break;
+            case TextClassifierEvent.TYPE_SMART_ACTION:
+                eventType = SelectionEvent.ACTION_SMART_SHARE;
+                break;
+            case TextClassifierEvent.TYPE_SELECTION_DRAG:
+                eventType = SelectionEvent.ACTION_DRAG;
+                break;
+            case TextClassifierEvent.TYPE_SELECTION_DESTROYED:
+                eventType = SelectionEvent.ACTION_ABANDON;
+                break;
+            case TextClassifierEvent.TYPE_OTHER_ACTION:
+                eventType = SelectionEvent.ACTION_OTHER;
+                break;
+            case TextClassifierEvent.TYPE_SELECT_ALL:
+                eventType = SelectionEvent.ACTION_SELECT_ALL;
+                break;
+            case TextClassifierEvent.TYPE_SELECTION_RESET:
+                eventType = SelectionEvent.ACTION_RESET;
+                break;
+            default:
+                eventType = 0;
+                break;
+        }
+        out.setEventType(eventType);
+
+        if (this instanceof TextClassifierEvent.TextSelectionEvent) {
+            final TextClassifierEvent.TextSelectionEvent selEvent =
+                    (TextClassifierEvent.TextSelectionEvent) this;
+            // TODO: Ideally, we should have these fields in events of type
+            // TextClassifierEvent.TextLinkifyEvent events too but we're now past the API deadline
+            // and will have to do with these fields being set only in TextSelectionEvent events.
+            // Fix this at the next API bump.
+            out.setStart(selEvent.getRelativeWordStartIndex());
+            out.setEnd(selEvent.getRelativeWordEndIndex());
+            out.setSmartStart(selEvent.getRelativeSuggestedWordStartIndex());
+            out.setSmartEnd(selEvent.getRelativeSuggestedWordEndIndex());
+        }
+
+        return out;
+    }
+
+    /**
      * Builder to build a text classifier event.
      *
      * @param <T> The subclass to be built.
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 3e95f1b..024c379 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -376,7 +376,6 @@
     /** @inheritDoc */
     @Override
     public void onSelectionEvent(SelectionEvent event) {
-        Preconditions.checkNotNull(event);
         mSessionLogger.writeEvent(event);
     }
 
@@ -386,7 +385,12 @@
             Log.d(DEFAULT_LOG_TAG, "onTextClassifierEvent() called with: event = [" + event + "]");
         }
         try {
-            mTextClassifierEventTronLogger.writeEvent(event);
+            final SelectionEvent selEvent = event.toSelectionEvent();
+            if (selEvent != null) {
+                mSessionLogger.writeEvent(selEvent);
+            } else {
+                mTextClassifierEventTronLogger.writeEvent(event);
+            }
         } catch (Exception e) {
             Log.e(LOG_TAG, "Error writing event", e);
         }
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 7a8c5c8..ebc6cd7 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -106,6 +106,11 @@
     return reinterpret_cast<jint>(get_canvas(canvasHandle)->saveUnclippedLayer(l, t, r, b));
 }
 
+static void restoreUnclippedLayer(jlong canvasHandle, jint saveCount, jlong paintHandle) {
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+    get_canvas(canvasHandle)->restoreUnclippedLayer(saveCount, *paint);
+}
+
 static bool restore(jlong canvasHandle) {
     Canvas* canvas = get_canvas(canvasHandle);
     if (canvas->getSaveCount() <= 1) {
@@ -668,6 +673,7 @@
     {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
     {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
     {"nSaveUnclippedLayer","(JIIII)I", (void*) CanvasJNI::saveUnclippedLayer},
+    {"nRestoreUnclippedLayer","(JIJ)V", (void*) CanvasJNI::restoreUnclippedLayer},
     {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
     {"nRestore","(J)Z", (void*) CanvasJNI::restore},
     {"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0daebd7..2de5397 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3457,7 +3457,7 @@
 
     <!-- Flag indicating whether the assist disclosure can be disabled using
          ASSIST_DISCLOSURE_ENABLED. -->
-    <bool name="config_allowDisablingAssistDisclosure">false</bool>
+    <bool name="config_allowDisablingAssistDisclosure">true</bool>
 
     <!-- True if the device supports system navigation keys. -->
     <bool name="config_supportSystemNavigationKeys">false</bool>
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index d6c0a10..3c65caf 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -78,6 +78,7 @@
         <item>ar-YE</item> <!-- Arabic (Yemen) -->
         <item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen, Western Digits) -->
         <item>as-IN</item> <!-- Assamese (India) -->
+        <item>as-IN-u-nu-latn</item> <!-- Assamese (India, Western Digits) -->
         <item>asa-TZ</item> <!-- Asu (Tanzania) -->
         <item>ast-ES</item> <!-- Asturian (Spain) -->
         <item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic, Azerbaijan) -->
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierEventTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierEventTest.java
new file mode 100644
index 0000000..11eb567
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierEventTest.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2019 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.view.textclassifier;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.annotation.Nullable;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class TextClassifierEventTest {
+
+    private static final TextClassificationContext TC_CONTEXT =
+            new TextClassificationContext.Builder("pkg", TextClassifier.WIDGET_TYPE_TEXTVIEW)
+                    .build();
+
+    private static final TextSelection TEXT_SELECTION = new TextSelection.Builder(10, 20)
+            .setEntityType(TextClassifier.TYPE_ADDRESS, 1)
+            .setId("id1")
+            .build();
+
+    private static final TextClassification TEXT_CLASSIFICATION = new TextClassification.Builder()
+            .setEntityType(TextClassifier.TYPE_DATE, 1)
+            .setId("id2")
+            .build();
+
+    @Test
+    public void toSelectionEvent_selectionStarted() {
+        final TextClassificationSessionId sessionId = new TextClassificationSessionId();
+        final SelectionEvent expected = SelectionEvent.createSelectionStartedEvent(
+                SelectionEvent.INVOCATION_MANUAL, 0);
+        expected.setTextClassificationSessionContext(TC_CONTEXT);
+        expected.setSessionId(sessionId);
+
+        final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+                TextClassifierEvent.TYPE_SELECTION_STARTED)
+                .setEventContext(TC_CONTEXT)
+                .build();
+        event.mHiddenTempSessionId = sessionId;
+
+        assertEquals(expected, event.toSelectionEvent());
+    }
+
+    @Test
+    public void toSelectionEvent_smartSelectionMulti() {
+        final int start = -1;
+        final int end = 2;
+        final int eventIndex = 1;
+        final SelectionEvent expected = SelectionEvent.createSelectionModifiedEvent(
+                0, 3, TEXT_SELECTION);
+        expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+        expected.setEventType(SelectionEvent.EVENT_SMART_SELECTION_MULTI);
+        expected.setStart(start);
+        expected.setEnd(end);
+        expected.setEventIndex(eventIndex);
+        expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+        final String entityType = TEXT_SELECTION.getEntity(0);
+        final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+                TextClassifierEvent.TYPE_SMART_SELECTION_MULTI)
+                .setEventContext(TC_CONTEXT)
+                .setResultId(TEXT_SELECTION.getId())
+                .setRelativeWordStartIndex(start)
+                .setRelativeWordEndIndex(end)
+                .setEntityTypes(entityType)
+                .setScores(TEXT_SELECTION.getConfidenceScore(entityType))
+                .setEventIndex(eventIndex)
+                .build();
+
+        assertEquals(expected, event.toSelectionEvent());
+    }
+
+    @Test
+    public void toSelectionEvent_smartSelectionSingle() {
+        final int start = 0;
+        final int end = 1;
+        final int eventIndex = 2;
+        final SelectionEvent expected = SelectionEvent.createSelectionModifiedEvent(
+                0, 1, TEXT_SELECTION);
+        expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+        expected.setEventType(SelectionEvent.EVENT_SMART_SELECTION_SINGLE);
+        expected.setStart(start);
+        expected.setEnd(end);
+        expected.setEventIndex(eventIndex);
+        expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+        final String entityType = TEXT_SELECTION.getEntity(0);
+        final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+                TextClassifierEvent.TYPE_SMART_SELECTION_SINGLE)
+                .setEventContext(TC_CONTEXT)
+                .setResultId(TEXT_SELECTION.getId())
+                .setRelativeWordStartIndex(start)
+                .setRelativeWordEndIndex(end)
+                .setEntityTypes(entityType)
+                .setScores(TEXT_SELECTION.getConfidenceScore(entityType))
+                .setEventIndex(eventIndex)
+                .build();
+
+        assertEquals(expected, event.toSelectionEvent());
+    }
+
+    @Test
+    public void toSelectionEvent_resetSelection() {
+        final int start = 0;
+        final int end = 1;
+        final int smartStart = -1;
+        final int smartEnd = 2;
+        final int eventIndex = 3;
+        final SelectionEvent expected = SelectionEvent.createSelectionActionEvent(
+                0, 1, SelectionEvent.ACTION_RESET, TEXT_CLASSIFICATION);
+        expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+        expected.setStart(start);
+        expected.setEnd(end);
+        expected.setSmartStart(smartStart);
+        expected.setSmartEnd(smartEnd);
+        expected.setEventIndex(eventIndex);
+        expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+        final String entityType = TEXT_CLASSIFICATION.getEntity(0);
+        final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+                TextClassifierEvent.TYPE_SELECTION_RESET)
+                .setEventContext(TC_CONTEXT)
+                .setResultId(TEXT_CLASSIFICATION.getId())
+                .setRelativeSuggestedWordStartIndex(smartStart)
+                .setRelativeSuggestedWordEndIndex(smartEnd)
+                .setRelativeWordStartIndex(start)
+                .setRelativeWordEndIndex(end)
+                .setEntityTypes(TEXT_CLASSIFICATION.getEntity(0))
+                .setScores(TEXT_CLASSIFICATION.getConfidenceScore(entityType))
+                .setEventIndex(eventIndex)
+                .build();
+
+        assertEquals(expected, event.toSelectionEvent());
+    }
+
+    @Test
+    public void toSelectionEvent_modifySelection() {
+        final int start = -1;
+        final int end = 5;
+        final int eventIndex = 4;
+        final SelectionEvent expected = SelectionEvent.createSelectionModifiedEvent(0, 1);
+        expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+        expected.setStart(start);
+        expected.setEnd(end);
+        expected.setEventIndex(eventIndex);
+        expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+        final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+                TextClassifierEvent.TYPE_SELECTION_MODIFIED)
+                .setEventContext(TC_CONTEXT)
+                .setRelativeWordStartIndex(start)
+                .setRelativeWordEndIndex(end)
+                .setEventIndex(eventIndex)
+                .build();
+
+        assertEquals(expected, event.toSelectionEvent());
+    }
+
+    @Test
+    public void toSelectionEvent_copyAction() {
+        final int start = 3;
+        final int end = 4;
+        final int eventIndex = 5;
+        final SelectionEvent expected = SelectionEvent.createSelectionActionEvent(
+                5, 6, SelectionEvent.ACTION_COPY);
+        expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+        expected.setStart(start);
+        expected.setEnd(end);
+        expected.setEventIndex(eventIndex);
+        expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+        final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+                TextClassifierEvent.TYPE_COPY_ACTION)
+                .setEventContext(TC_CONTEXT)
+                .setRelativeWordStartIndex(start)
+                .setRelativeWordEndIndex(end)
+                .setEventIndex(eventIndex)
+                .build();
+
+        assertEquals(expected, event.toSelectionEvent());
+    }
+
+    @Test
+    public void toSelectionEvent_selectionDismissed() {
+        final int eventIndex = 6;
+        final SelectionEvent expected = SelectionEvent.createSelectionActionEvent(
+                0, 1, SelectionEvent.ACTION_ABANDON);
+        expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+        expected.setEventIndex(eventIndex);
+
+        final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+                TextClassifierEvent.TYPE_SELECTION_DESTROYED)
+                .setEventIndex(eventIndex)
+                .build();
+
+        assertEquals(expected, event.toSelectionEvent());
+    }
+
+    @Test
+    public void toSelectionEvent_link_smartAction() {
+        final int eventIndex = 2;
+        final SelectionEvent expected = SelectionEvent.createSelectionActionEvent(
+                1, 9, SelectionEvent.ACTION_SMART_SHARE, TEXT_CLASSIFICATION);
+        expected.setInvocationMethod(SelectionEvent.INVOCATION_LINK);
+        // TODO: TextLinkifyEvent API is missing APIs to set text indices. See related comment in
+        // TextClassifierEvent.
+        expected.setEventIndex(eventIndex);
+        expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+        final String entityType = TEXT_CLASSIFICATION.getEntity(0);
+        final TextClassifierEvent event = new TextClassifierEvent.TextLinkifyEvent.Builder(
+                TextClassifierEvent.TYPE_SMART_ACTION)
+                .setEventContext(TC_CONTEXT)
+                .setResultId(TEXT_CLASSIFICATION.getId())
+                .setEntityTypes(entityType)
+                .setScores(TEXT_CLASSIFICATION.getConfidenceScore(entityType))
+                .setActionIndices(0)
+                .setEventIndex(eventIndex)
+                .build();
+
+        assertEquals(expected, event.toSelectionEvent());
+    }
+
+    @Test
+    public void toSelectionEvent_nonSelectionOrLinkifyEvent() {
+        final TextClassifierEvent convActionEvent =
+                new TextClassifierEvent.ConversationActionsEvent.Builder(
+                        TextClassifierEvent.TYPE_ACTIONS_GENERATED)
+                        .build();
+        assertWithMessage("conversation action event")
+                .that(convActionEvent.toSelectionEvent()).isNull();
+
+        final TextClassifierEvent langDetEvent =
+                new TextClassifierEvent.ConversationActionsEvent.Builder(
+                        TextClassifierEvent.TYPE_ACTIONS_GENERATED)
+                        .setEventContext(TC_CONTEXT)
+                        .build();
+        assertWithMessage("language detection event")
+                .that(langDetEvent.toSelectionEvent()).isNull();
+    }
+
+    private static void assertEquals(
+            @Nullable SelectionEvent expected, @Nullable SelectionEvent actual) {
+        if (expected == null && actual == null) return;
+        if (expected == actual) return;
+        assertWithMessage("actual").that(actual).isNotNull();
+        assertWithMessage("expected").that(expected).isNotNull();
+        assertWithMessage("eventType")
+                .that(actual.getEventType()).isEqualTo(expected.getEventType());
+        assertWithMessage("packageName")
+                .that(actual.getPackageName()).isEqualTo(expected.getPackageName());
+        assertWithMessage("widgetType")
+                .that(actual.getWidgetType()).isEqualTo(expected.getWidgetType());
+        assertWithMessage("widgetVersion")
+                .that(actual.getWidgetVersion()).isEqualTo(expected.getWidgetVersion());
+        assertWithMessage("invocationMethod")
+                .that(actual.getInvocationMethod()).isEqualTo(expected.getInvocationMethod());
+        assertWithMessage("resultId")
+                .that(actual.getResultId()).isEqualTo(expected.getResultId());
+        assertWithMessage("sessionId")
+                .that(actual.getSessionId()).isEqualTo(expected.getSessionId());
+        assertWithMessage("entityType")
+                .that(actual.getEntityType()).isEqualTo(expected.getEntityType());
+        assertWithMessage("eventIndex")
+                .that(actual.getEventIndex()).isEqualTo(expected.getEventIndex());
+        assertWithMessage("start")
+                .that(actual.getStart()).isEqualTo(expected.getStart());
+        assertWithMessage("end")
+                .that(actual.getEnd()).isEqualTo(expected.getEnd());
+        assertWithMessage("smartStart")
+                .that(actual.getSmartStart()).isEqualTo(expected.getSmartStart());
+        assertWithMessage("smartEnd")
+                .that(actual.getSmartEnd()).isEqualTo(expected.getSmartEnd());
+    }
+}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index d4d5ae7..5648b85 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -559,6 +559,16 @@
     }
 
     /**
+     * @hide
+     * @param saveCount The save level to restore to.
+     * @param paint     This is copied and is applied to the area within the unclipped layer's
+     *                  bounds (i.e. equivalent to a drawPaint()) before restore() is called.
+     */
+    public void restoreUnclippedLayer(int saveCount, Paint paint) {
+        nRestoreUnclippedLayer(mNativeCanvasWrapper, saveCount, paint.getNativeInstance());
+    }
+
+    /**
      * Helper version of saveLayer() that takes 4 values rather than a RectF.
      *
      * As of API Level API level {@value Build.VERSION_CODES#P} the only valid
@@ -1398,6 +1408,9 @@
     @CriticalNative
     private static native int nSaveUnclippedLayer(long nativeCanvas, int l, int t, int r, int b);
     @CriticalNative
+    private static native void nRestoreUnclippedLayer(long nativeCanvas, int saveCount,
+            long nativePaint);
+    @CriticalNative
     private static native boolean nRestore(long canvasHandle);
     @CriticalNative
     private static native void nRestoreToCount(long canvasHandle, int saveCount);
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index 14e3a32..2deb565 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -26,7 +26,8 @@
 X(ClipRect) 
 X(ClipRRect) 
 X(ClipRegion)
-X(DrawPaint) 
+X(DrawPaint)
+X(DrawBehind)
 X(DrawPath) 
 X(DrawRect) 
 X(DrawRegion) 
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 8594766..e58fbbe 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -20,6 +20,7 @@
 
 #include "SkAndroidFrameworkUtils.h"
 #include "SkCanvas.h"
+#include "SkCanvasPriv.h"
 #include "SkData.h"
 #include "SkDrawShadowInfo.h"
 #include "SkImage.h"
@@ -187,6 +188,12 @@
     SkPaint paint;
     void draw(SkCanvas* c, const SkMatrix&) const { c->drawPaint(paint); }
 };
+struct DrawBehind final : Op {
+    static const auto kType = Type::DrawBehind;
+    DrawBehind(const SkPaint& paint) : paint(paint) {}
+    SkPaint paint;
+    void draw(SkCanvas* c, const SkMatrix&) const { SkCanvasPriv::DrawBehind(c, paint); }
+};
 struct DrawPath final : Op {
     static const auto kType = Type::DrawPath;
     DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {}
@@ -565,6 +572,9 @@
 void DisplayListData::drawPaint(const SkPaint& paint) {
     this->push<DrawPaint>(0, paint);
 }
+void DisplayListData::drawBehind(const SkPaint& paint) {
+    this->push<DrawBehind>(0, paint);
+}
 void DisplayListData::drawPath(const SkPath& path, const SkPaint& paint) {
     this->push<DrawPath>(0, path, paint);
 }
@@ -834,6 +844,9 @@
 void RecordingCanvas::onDrawPaint(const SkPaint& paint) {
     fDL->drawPaint(paint);
 }
+void RecordingCanvas::onDrawBehind(const SkPaint& paint) {
+    fDL->drawBehind(paint);
+}
 void RecordingCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
     fDL->drawPath(path, paint);
 }
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 3a76ca1..7269bca 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -89,6 +89,7 @@
     void clipRegion(const SkRegion&, SkClipOp);
 
     void drawPaint(const SkPaint&);
+    void drawBehind(const SkPaint&);
     void drawPath(const SkPath&, const SkPaint&);
     void drawRect(const SkRect&, const SkPaint&);
     void drawRegion(const SkRegion&, const SkPaint&);
@@ -157,6 +158,7 @@
     void onClipRegion(const SkRegion&, SkClipOp) override;
 
     void onDrawPaint(const SkPaint&) override;
+    void onDrawBehind(const SkPaint&) override;
     void onDrawPath(const SkPath&, const SkPaint&) override;
     void onDrawRect(const SkRect&, const SkPaint&) override;
     void onDrawRegion(const SkRegion&, const SkPaint&) override;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index f328a53..bebda852 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -26,6 +26,7 @@
 
 #include <SkAndroidFrameworkUtils.h>
 #include <SkAnimatedImage.h>
+#include <SkCanvasPriv.h>
 #include <SkCanvasStateUtils.h>
 #include <SkColorFilter.h>
 #include <SkDeque.h>
@@ -191,6 +192,18 @@
     return SkAndroidFrameworkUtils::SaveBehind(mCanvas, &bounds);
 }
 
+void SkiaCanvas::restoreUnclippedLayer(int restoreCount, const SkPaint& paint) {
+
+    while (mCanvas->getSaveCount() > restoreCount + 1) {
+        this->restore();
+    }
+
+    if (mCanvas->getSaveCount() == restoreCount + 1) {
+        SkCanvasPriv::DrawBehind(mCanvas, *filterPaint(paint));
+        this->restore();
+    }
+}
+
 class SkiaCanvas::Clip {
 public:
     Clip(const SkRect& rect, SkClipOp op, const SkMatrix& m)
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 3fe2bce..bbe91eb 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -69,6 +69,7 @@
     virtual int save(SaveFlags::Flags flags) override;
     virtual void restore() override;
     virtual void restoreToCount(int saveCount) override;
+    virtual void restoreUnclippedLayer(int saveCount, const SkPaint& paint) override;
 
     virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
                           SaveFlags::Flags flags) override;
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 11e8579..ac8db21 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -191,6 +191,7 @@
     virtual int save(SaveFlags::Flags flags) = 0;
     virtual void restore() = 0;
     virtual void restoreToCount(int saveCount) = 0;
+    virtual void restoreUnclippedLayer(int saveCount, const SkPaint& paint) = 0;
 
     virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
                           SaveFlags::Flags flags) = 0;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index ccc1701..1f9ab5a 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -176,7 +176,7 @@
             // position
             Matrix4 windowTransform;
             damageAccumulator.computeCurrentTransform(&windowTransform);
-            node->getSkiaLayer()->inverseTransformInWindow = windowTransform;
+            node->getSkiaLayer()->inverseTransformInWindow.loadInverse(windowTransform);
         } else {
             String8 cachesOutput;
             mRenderThread.cacheManager().dumpMemoryUsage(cachesOutput,
diff --git a/packages/CtsShim/apk/arm/CtsShim.apk b/packages/CtsShim/apk/arm/CtsShim.apk
index a911603..7d9f8e3 100644
--- a/packages/CtsShim/apk/arm/CtsShim.apk
+++ b/packages/CtsShim/apk/arm/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/arm/CtsShimPriv.apk b/packages/CtsShim/apk/arm/CtsShimPriv.apk
index 845d781..dcccada 100644
--- a/packages/CtsShim/apk/arm/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/arm/CtsShimPriv.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShim.apk b/packages/CtsShim/apk/x86/CtsShim.apk
index a911603..7d9f8e3 100644
--- a/packages/CtsShim/apk/x86/CtsShim.apk
+++ b/packages/CtsShim/apk/x86/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShimPriv.apk b/packages/CtsShim/apk/x86/CtsShimPriv.apk
index 2fc9a94..3501fa4 100644
--- a/packages/CtsShim/apk/x86/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/x86/CtsShimPriv.apk
Binary files differ
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index aefa882..c013b8c 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -42,8 +42,8 @@
     static_libs: [
         "androidx.annotation_annotation",
         "ipmemorystore-client",
-        "netd_aidl_interface-java",
-        "networkstack-aidl-interfaces-java",
+        "netd_aidl_interface-V2-java",
+        "networkstack-aidl-interfaces-V3-java",
         "datastallprotosnano",
         "networkstackprotosnano",
         "captiveportal-lib",
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index c394d4c..2fae0c7 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -49,6 +49,7 @@
 import android.net.util.SharedLog;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.ArraySet;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
@@ -62,7 +63,6 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Android service used to start the network stack when bound to via an intent.
@@ -118,14 +118,12 @@
         @GuardedBy("mValidationLogs")
         private final ArrayDeque<SharedLog> mValidationLogs = new ArrayDeque<>(MAX_VALIDATION_LOGS);
 
-        private static final int VERSION_UNKNOWN = 0;
         private static final String DUMPSYS_ARG_VERSION = "version";
 
-        /** Version of the AIDL interfaces observed on the system */
-        private final AtomicInteger mSystemAidlVersion = new AtomicInteger(VERSION_UNKNOWN);
-
-        /** Whether different versions have been observed on interfaces provided by the system */
-        private volatile boolean mConflictingSystemAidlVersions = false;
+        /** Version of the framework AIDL interfaces observed. Should hold only one value. */
+        @GuardedBy("mFrameworkAidlVersions")
+        private final ArraySet<Integer> mFrameworkAidlVersions = new ArraySet<>(1);
+        private final int mNetdAidlVersion;
 
         private SharedLog addValidationLogs(Network network, String name) {
             final SharedLog log = new SharedLog(NUM_VALIDATION_LOG_LINES, network + " - " + name);
@@ -146,6 +144,15 @@
             mCm = context.getSystemService(ConnectivityManager.class);
             mIpMemoryStoreService = new IpMemoryStoreService(context);
 
+            int netdVersion;
+            try {
+                netdVersion = mNetd.getInterfaceVersion();
+            } catch (RemoteException e) {
+                mLog.e("Error obtaining INetd version", e);
+                netdVersion = -1;
+            }
+            mNetdAidlVersion = netdVersion;
+
             try {
                 mObserverRegistry.register(mNetd);
             } catch (RemoteException e) {
@@ -154,9 +161,8 @@
         }
 
         private void updateSystemAidlVersion(final int version) {
-            final int previousVersion = mSystemAidlVersion.getAndSet(version);
-            if (previousVersion != VERSION_UNKNOWN && previousVersion != version) {
-                mConflictingSystemAidlVersions = true;
+            synchronized (mFrameworkAidlVersions) {
+                mFrameworkAidlVersions.add(version);
             }
         }
 
@@ -230,12 +236,16 @@
         protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
                 @Nullable String[] args) {
             checkDumpPermission();
+
+            final IndentingPrintWriter pw = new IndentingPrintWriter(fout, "  ");
+            pw.println("NetworkStack version:");
+            dumpVersion(pw);
+            pw.println();
+
             if (args != null && args.length >= 1 && DUMPSYS_ARG_VERSION.equals(args[0])) {
-                dumpVersion(fout);
                 return;
             }
 
-            final IndentingPrintWriter pw = new IndentingPrintWriter(fout, "  ");
             pw.println("NetworkStack logs:");
             mLog.dump(fd, pw, args);
 
@@ -283,8 +293,10 @@
          */
         private void dumpVersion(@NonNull PrintWriter fout) {
             fout.println("NetworkStackConnector: " + this.VERSION);
-            fout.println("SystemServer: " + mSystemAidlVersion);
-            fout.println("SystemServerConflicts: " + mConflictingSystemAidlVersions);
+            synchronized (mFrameworkAidlVersions) {
+                fout.println("SystemServer: " + mFrameworkAidlVersions);
+            }
+            fout.println("Netd: " + mNetdAidlVersion);
         }
 
         @Override
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/unit/Android.bp
similarity index 96%
rename from packages/NetworkStack/tests/Android.bp
rename to packages/NetworkStack/tests/unit/Android.bp
index 039f6bf..6cc80543 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/unit/Android.bp
@@ -72,7 +72,7 @@
         "libutilscallstack",
         "libziparchive",
         "libz",
-        "netd_aidl_interface-cpp",
+        "netd_aidl_interface-V2-cpp",
     ],
 }
 
@@ -94,7 +94,7 @@
         "liblog",
         "libcutils",
         "libnativehelper",
-        "netd_aidl_interface-cpp",
+        "netd_aidl_interface-V2-cpp",
     ],
     static_libs: [
         "libapf",
diff --git a/packages/NetworkStack/tests/AndroidManifest.xml b/packages/NetworkStack/tests/unit/AndroidManifest.xml
similarity index 100%
rename from packages/NetworkStack/tests/AndroidManifest.xml
rename to packages/NetworkStack/tests/unit/AndroidManifest.xml
diff --git a/packages/NetworkStack/tests/AndroidTest.xml b/packages/NetworkStack/tests/unit/AndroidTest.xml
similarity index 100%
rename from packages/NetworkStack/tests/AndroidTest.xml
rename to packages/NetworkStack/tests/unit/AndroidTest.xml
diff --git a/packages/NetworkStack/tests/jni/apf_jni.cpp b/packages/NetworkStack/tests/unit/jni/apf_jni.cpp
similarity index 100%
rename from packages/NetworkStack/tests/jni/apf_jni.cpp
rename to packages/NetworkStack/tests/unit/jni/apf_jni.cpp
diff --git a/packages/NetworkStack/tests/res/raw/apf.pcap b/packages/NetworkStack/tests/unit/res/raw/apf.pcap
similarity index 100%
rename from packages/NetworkStack/tests/res/raw/apf.pcap
rename to packages/NetworkStack/tests/unit/res/raw/apf.pcap
Binary files differ
diff --git a/packages/NetworkStack/tests/res/raw/apfPcap.pcap b/packages/NetworkStack/tests/unit/res/raw/apfPcap.pcap
similarity index 100%
rename from packages/NetworkStack/tests/res/raw/apfPcap.pcap
rename to packages/NetworkStack/tests/unit/res/raw/apfPcap.pcap
Binary files differ
diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/unit/src/android/net/apf/ApfTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/apf/ApfTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/apf/Bpf2Apf.java b/packages/NetworkStack/tests/unit/src/android/net/apf/Bpf2Apf.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/apf/Bpf2Apf.java
rename to packages/NetworkStack/tests/unit/src/android/net/apf/Bpf2Apf.java
diff --git a/packages/NetworkStack/tests/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java b/packages/NetworkStack/tests/unit/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpLeaseRepositoryTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/dhcp/DhcpLeaseRepositoryTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServerTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServerTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServingParamsTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServingParamsTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/dhcp/DhcpServingParamsTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServingParamsTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/unit/src/android/net/ip/IpClientTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/ip/IpClientTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpReachabilityMonitorTest.java b/packages/NetworkStack/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/ip/IpReachabilityMonitorTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/util/ConnectivityPacketSummaryTest.java b/packages/NetworkStack/tests/unit/src/android/net/util/ConnectivityPacketSummaryTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/util/ConnectivityPacketSummaryTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/util/ConnectivityPacketSummaryTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java b/packages/NetworkStack/tests/unit/src/android/net/util/PacketReaderTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/util/PacketReaderTest.java
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
similarity index 99%
rename from packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
rename to packages/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
index 2618675..832b712 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -297,6 +297,7 @@
         setOtherFallbackUrls(TEST_OTHER_FALLBACK_URL);
         setFallbackSpecs(null); // Test with no fallback spec by default
         when(mRandom.nextInt()).thenReturn(0);
+
         // DNS probe timeout should not be defined more than half of HANDLER_TIMEOUT_MS. Otherwise,
         // it will fail the test because of timeout expired for querying AAAA and A sequentially.
         when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)))
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
rename to packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
similarity index 100%
rename from packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
rename to packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
diff --git a/packages/NetworkStack/tests/src/com/android/server/util/SharedLogTest.java b/packages/NetworkStack/tests/unit/src/com/android/server/util/SharedLogTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/com/android/server/util/SharedLogTest.java
rename to packages/NetworkStack/tests/unit/src/com/android/server/util/SharedLogTest.java
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 1c8e141..17923cd 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -65,6 +65,8 @@
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
         <item name="android:fontFeatureSettings">@*android:string/config_headlineFontFeatureSettings</item>
         <item name="android:ellipsize">none</item>
+        <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+        <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
     </style>
     <style name="widget_title_bold">
         <item name="android:textStyle">bold</item>
@@ -72,6 +74,8 @@
         <item name="android:paddingBottom">@dimen/widget_vertical_padding_clock</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
         <item name="android:ellipsize">none</item>
+        <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+        <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
     </style>
     <style name="widget_small_bold">
         <item name="android:textStyle">bold</item>
@@ -79,6 +83,8 @@
         <item name="android:paddingBottom">@dimen/bottom_text_spacing_digital</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
         <item name="android:ellipsize">none</item>
+        <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+        <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
     </style>
 
     <style name="BouncerSecurityContainer">
@@ -108,6 +114,8 @@
         <item name="android:ellipsize">end</item>
         <item name="android:maxLines">2</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+        <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+        <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
     </style>
 
     <style name="TextAppearance.Keyguard.Secondary">
@@ -121,6 +129,8 @@
         <item name="android:textSize">16sp</item>
         <item name="android:maxLines">1</item>
         <item name="android:textColor">?attr/wallpaperTextColor</item>
+        <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+        <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
     </style>
 
 </resources>
diff --git a/packages/SystemUI/res/drawable/ic_arrow_back.xml b/packages/SystemUI/res/drawable/ic_arrow_back.xml
index 374f16b..d9c0434 100644
--- a/packages/SystemUI/res/drawable/ic_arrow_back.xml
+++ b/packages/SystemUI/res/drawable/ic_arrow_back.xml
@@ -14,6 +14,7 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoMirrored="true"
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
diff --git a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
index 6f3da75..d721988 100644
--- a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
+++ b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
@@ -21,7 +21,7 @@
 
     <path
         android:pathData="M18,14.48V18h-3.52L12,20.48L9.52,18H6v-3.52L3.52,12L6,9.52V6h3.52L12,3.52L14.48,6H18v3.52L20.48,12L18,14.48z"
-        android:fillColor="?android:attr/colorPrimary" />
+        android:fillColor="?android:attr/colorBackgroundFloating" />
 
     <path
         android:pathData=" M20,8.69 V4h-4.69L12,0.69L8.69,4H4v4.69L0.69,12L4,15.31V20h4.69L12,23.31L15.31,20H20v-4.69L23.31,12L20,8.69z M18,14.48V18h-3.52L12,20.48L9.52,18H6v-3.52L3.52,12L6,9.52V6h3.52L12,3.52L14.48,6H18v3.52L20.48,12L18,14.48z M12,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5s5,-2.24 5,-5S14.76,7 12,7z"
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 2792a01..7fc2066 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -26,7 +26,6 @@
 
     <LinearLayout
         android:id="@+id/keyguard_indication_area"
-        android:forceHasOverlappingRendering="false"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 490473ce..811f1a3 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -55,6 +55,9 @@
 
     <color name="keyguard_affordance">#ffffffff</color>
 
+    <!-- Shadows under the clock, date and other keyguard text fields -->
+    <color name="keyguard_shadow_color">#B2000000</color>
+
     <!-- The color of the legacy notification background -->
     <color name="notification_legacy_background_color">#ff1a1a1a</color>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fb226c7..ec538ff 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -181,6 +181,9 @@
     <!-- The padding on the bottom of the notifications on the keyguard -->
     <dimen name="keyguard_indication_bottom_padding">12sp</dimen>
 
+    <!-- Shadows under the clock, date and other keyguard text fields -->
+    <dimen name="keyguard_shadow_radius">5</dimen>
+
     <!-- Minimum layouted height of a notification in the statusbar-->
     <dimen name="min_notification_layout_height">48dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 1dc3474..a7fe607 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -319,11 +319,6 @@
         refreshFormat();
     }
 
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("KeyguardStatusView:");
         pw.println("  mOwnerInfo: " + (mOwnerInfo == null
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 51bd9f8..f0c38fb 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -169,7 +169,7 @@
     }
 
     protected boolean shouldShowOrb() {
-        return true;
+        return false;
     }
 
     public void startAssist(Bundle args) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 7e016bb..04637ad 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -35,7 +35,6 @@
 import static java.lang.annotation.ElementType.PARAMETER;
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
-import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityTaskManager;
@@ -61,6 +60,7 @@
 
 import androidx.annotation.IntDef;
 import androidx.annotation.MainThread;
+import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.IStatusBarService;
@@ -139,7 +139,7 @@
     @Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
 
     private BubbleData mBubbleData;
-    private BubbleStackView mStackView;
+    @Nullable private BubbleStackView mStackView;
 
     // Bubbles get added to the status bar view
     private final StatusBarWindowController mStatusBarWindowController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 812c9a7..689d161 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -212,7 +212,7 @@
             return;
         }
         mMobileDrawable.setTintList(
-                ColorStateList.valueOf(mDualToneHandler.getFillColor(darkIntensity)));
+                ColorStateList.valueOf(mDualToneHandler.getSingleColor(darkIntensity)));
         ColorStateList color = ColorStateList.valueOf(getTint(area, this, tint));
         mIn.setImageTintList(color);
         mOut.setImageTintList(color);
@@ -238,7 +238,7 @@
         // We want the ability to change the theme from the one set by SignalDrawable in certain
         // surfaces. In this way, we can pass a theme to the view.
         mMobileDrawable.setTintList(
-                ColorStateList.valueOf(mDualToneHandler.getFillColor(intensity)));
+                ColorStateList.valueOf(mDualToneHandler.getSingleColor(intensity)));
         mIn.setImageTintList(list);
         mOut.setImageTintList(list);
         mMobileType.setImageTintList(list);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index ce8463e..4d4818d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -433,7 +433,8 @@
     public void onBiometricError(int msgId, String errString,
             BiometricSourceType biometricSourceType) {
         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
-                .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType)));
+                .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType))
+                .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
         cleanup();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index aba64bdf..f221865 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -121,8 +121,8 @@
     private final int mEdgeWidth;
     // The slop to distinguish between horizontal and vertical motion
     private final float mTouchSlop;
-    // Minimum distance to move so that is can be considerd as a back swipe
-    private final float mSwipeThreshold;
+    // Duration after which we consider the event as longpress.
+    private final int mLongPressTimeout;
     // The threshold where the touch needs to be at most, such that the arrow is displayed above the
     // finger, otherwise it will be below
     private final int mMinArrowPosition;
@@ -164,8 +164,9 @@
         // TODO: Get this for the current user
         mEdgeWidth = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.config_backGestureInset);
+
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
-        mSwipeThreshold = res.getDimension(R.dimen.navigation_edge_action_drag_threshold);
+        mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
 
         mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
         mMinArrowPosition = res.getDimensionPixelSize(
@@ -308,8 +309,18 @@
         return !isInExcludedRegion;
     }
 
+    private void cancelGesture(MotionEvent ev) {
+        // Send action cancel to reset all the touch events
+        mAllowGesture = false;
+        MotionEvent cancelEv = MotionEvent.obtain(ev);
+        cancelEv.setAction(MotionEvent.ACTION_CANCEL);
+        mEdgePanel.handleTouch(cancelEv);
+        cancelEv.recycle();
+    }
+
     private void onMotionEvent(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+        int action = ev.getActionMasked();
+        if (action == MotionEvent.ACTION_DOWN) {
             // Verify if this is in within the touch region and we aren't in immersive mode, and
             // either the bouncer is showing or the notification panel is hidden
             int stateFlags = mOverviewProxyService.getSystemUiStateFlags();
@@ -330,29 +341,35 @@
                 mThresholdCrossed = false;
             }
         } else if (mAllowGesture) {
-            if (!mThresholdCrossed && ev.getAction() == MotionEvent.ACTION_MOVE) {
-                float dx = Math.abs(ev.getX() - mDownPoint.x);
-                float dy = Math.abs(ev.getY() - mDownPoint.y);
-                if (dy > dx && dy > mTouchSlop) {
-                    // Send action cancel to reset all the touch events
-                    mAllowGesture = false;
-                    MotionEvent cancelEv = MotionEvent.obtain(ev);
-                    cancelEv.setAction(MotionEvent.ACTION_CANCEL);
-                    mEdgePanel.handleTouch(cancelEv);
-                    cancelEv.recycle();
+            if (!mThresholdCrossed) {
+                if (action == MotionEvent.ACTION_POINTER_DOWN) {
+                    // We do not support multi touch for back gesture
+                    cancelGesture(ev);
                     return;
+                } else if (action == MotionEvent.ACTION_MOVE) {
+                    if ((ev.getEventTime() - ev.getDownTime()) > mLongPressTimeout) {
+                        cancelGesture(ev);
+                        return;
+                    }
+                    float dx = Math.abs(ev.getX() - mDownPoint.x);
+                    float dy = Math.abs(ev.getY() - mDownPoint.y);
+                    if (dy > dx && dy > mTouchSlop) {
+                        cancelGesture(ev);
+                        return;
 
-                } else if (dx > dy && dx > mTouchSlop) {
-                    mThresholdCrossed = true;
-                    // Capture inputs
-                    mInputMonitor.pilferPointers();
+                    } else if (dx > dy && dx > mTouchSlop) {
+                        mThresholdCrossed = true;
+                        // Capture inputs
+                        mInputMonitor.pilferPointers();
+                    }
                 }
+
             }
 
             // forward touch
             mEdgePanel.handleTouch(ev);
 
-            boolean isUp = ev.getAction() == MotionEvent.ACTION_UP;
+            boolean isUp = action == MotionEvent.ACTION_UP;
             if (isUp) {
                 boolean performAction = mEdgePanel.shouldTriggerBack();
                 if (performAction) {
@@ -363,7 +380,7 @@
                 mOverviewProxyService.notifyBackAction(performAction, (int) mDownPoint.x,
                         (int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
             }
-            if (isUp || ev.getAction() == MotionEvent.ACTION_CANCEL) {
+            if (isUp || action == MotionEvent.ACTION_CANCEL) {
                 mRegionSamplingHelper.stop();
             } else {
                 updateSamplingRect();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index b8887c4..61a3940 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -95,6 +95,7 @@
     private boolean mWasPulsingOnThisFrame;
     private boolean mWakeAndUnlockRunning;
     private boolean mKeyguardShowing;
+    private boolean mShowingLaunchAffordance;
 
     private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
             new KeyguardMonitor.Callback() {
@@ -299,7 +300,8 @@
         }
 
         boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
-        boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning;
+        boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning
+                || mShowingLaunchAffordance;
         setVisibility(invisible ? INVISIBLE : VISIBLE);
         updateClickability();
     }
@@ -485,6 +487,14 @@
     }
 
     /**
+     * When we're launching an affordance, like double pressing power to open camera.
+     */
+    public void onShowingLaunchAffordanceChanged(boolean showing) {
+        mShowingLaunchAffordance = showing;
+        update();
+    }
+
+    /**
      * Called whenever the scrims become opaque, transparent or semi-transparent.
      */
     public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 6e56854..36050ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -17,12 +17,15 @@
 package com.android.systemui.statusbar.phone;
 
 import static android.content.Intent.ACTION_OVERLAY_CHANGED;
+import static android.content.Intent.ACTION_PREFERRED_ACTIVITY_CHANGED;
 import static android.os.UserHandle.USER_CURRENT;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
 
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -56,7 +59,7 @@
 public class NavigationModeController implements Dumpable {
 
     private static final String TAG = NavigationModeController.class.getSimpleName();
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     public interface ModeChangedListener {
         void onNavigationModeChanged(int mode);
@@ -76,11 +79,19 @@
     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(ACTION_OVERLAY_CHANGED)) {
-                if (DEBUG) {
-                    Log.d(TAG, "ACTION_OVERLAY_CHANGED");
-                }
-                updateCurrentInteractionMode(true /* notify */);
+            switch (intent.getAction()) {
+                case ACTION_OVERLAY_CHANGED:
+                    if (DEBUG) {
+                        Log.d(TAG, "ACTION_OVERLAY_CHANGED");
+                    }
+                    updateCurrentInteractionMode(true /* notify */);
+                    break;
+                case ACTION_PREFERRED_ACTIVITY_CHANGED:
+                    if (DEBUG) {
+                        Log.d(TAG, "ACTION_PREFERRED_ACTIVITY_CHANGED");
+                    }
+                    switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
+                    break;
             }
         }
     };
@@ -116,6 +127,7 @@
 
                     // Update the nav mode for the current user
                     updateCurrentInteractionMode(true /* notify */);
+                    switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
 
                     // When switching users, defer enabling the gestural nav overlay until the user
                     // is all set up
@@ -140,7 +152,12 @@
         overlayFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL);
         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);
 
+        IntentFilter preferredActivityFilter = new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED);
+        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, preferredActivityFilter, null,
+                null);
+
         updateCurrentInteractionMode(false /* notify */);
+        switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
 
         // Check if we need to defer enabling gestural nav
         deferGesturalNavOverlayIfNecessary();
@@ -175,6 +192,10 @@
     private int getCurrentInteractionMode(Context context) {
         int mode = context.getResources().getInteger(
                 com.android.internal.R.integer.config_navBarInteractionMode);
+        if (DEBUG) {
+            Log.d(TAG, "getCurrentInteractionMode: mode=" + mMode
+                    + " contextUser=" + context.getUserId());
+        }
         return mode;
     }
 
@@ -250,6 +271,10 @@
         mUiOffloadThread.submit(() -> {
             try {
                 mOverlayManager.setEnabledExclusiveInCategory(overlayPkg, userId);
+                if (DEBUG) {
+                    Log.d(TAG, "setModeOverlay: overlayPackage=" + overlayPkg
+                            + " userId=" + userId);
+                }
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to enable overlay " + overlayPkg + " for user " + userId);
             }
@@ -277,4 +302,27 @@
             Log.d(TAG, "    " + a.getAssetPath());
         }
     }
+
+    private void switchFromGestureNavModeIfNotSupportedByDefaultLauncher() {
+        if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL
+                && !isGestureNavSupportedByDefaultLauncher(mCurrentUserContext)) {
+            setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT);
+        }
+    }
+
+    private boolean isGestureNavSupportedByDefaultLauncher(Context context) {
+        final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>());
+        if (cn == null) {
+            // There is no default home app set for the current user, don't make any changes yet.
+            return true;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "isGestureNavSupportedByDefaultLauncher: launcher=" + cn.getPackageName()
+                    + " contextUser=" + context.getUserId());
+        }
+
+        ComponentName recentsComponentName = ComponentName.unflattenFromString(context.getString(
+                com.android.internal.R.string.config_recentsComponentName));
+        return recentsComponentName.getPackageName().equals(cn.getPackageName());
+    }
 }
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 3fe7f36..9da75b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -151,7 +151,8 @@
     private final NotificationWakeUpCoordinator mWakeUpCoordinator;
     private final PulseExpansionHandler mPulseExpansionHandler;
 
-    private KeyguardAffordanceHelper mAffordanceHelper;
+    @VisibleForTesting
+    protected KeyguardAffordanceHelper mAffordanceHelper;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
     @VisibleForTesting
     protected KeyguardStatusBarView mKeyguardStatusBar;
@@ -340,6 +341,7 @@
      */
     private int mThemeResId;
     private KeyguardIndicationController mKeyguardIndicationController;
+    private Consumer<Boolean> mAffordanceLaunchListener;
 
     @Inject
     public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
@@ -447,6 +449,14 @@
                 R.dimen.qs_notification_padding);
     }
 
+    /**
+     * @see #launchCamera(boolean, int)
+     * @see #setLaunchingAffordance(boolean)
+     */
+    public void setLaunchAffordanceListener(Consumer<Boolean> listener) {
+        mAffordanceLaunchListener = listener;
+    }
+
     public void updateResources() {
         Resources res = getResources();
         int qsWidth = res.getDimensionPixelSize(R.dimen.qs_panel_width);
@@ -2743,6 +2753,9 @@
     private void setLaunchingAffordance(boolean launchingAffordance) {
         getLeftIcon().setLaunchingAffordance(launchingAffordance);
         getRightIcon().setLaunchingAffordance(launchingAffordance);
+        if (mAffordanceLaunchListener != null) {
+            mAffordanceLaunchListener.accept(launchingAffordance);
+        }
     }
 
     /**
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 72726b3..4e8f584 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -951,6 +951,9 @@
             createUserSwitcher();
         }
 
+        mNotificationPanel.setLaunchAffordanceListener(
+                mStatusBarWindow::onShowingLaunchAffordanceChanged);
+
         // Set up the quick settings tile panel
         View container = mStatusBarWindow.findViewById(R.id.qs_frame);
         if (container != null) {
@@ -3636,6 +3639,7 @@
 
         @Override
         public void onStartedGoingToSleep() {
+            updateNotificationPanelTouchState();
             notifyHeadsUpGoingToSleep();
             dismissVolumeDialog();
         }
@@ -3668,7 +3672,10 @@
      * Keyguard.
      */
     private void updateNotificationPanelTouchState() {
-        mNotificationPanel.setTouchAndAnimationDisabled(!mDeviceInteractive && !mPulsing);
+        boolean goingToSleepWithoutAnimation = isGoingToSleep()
+                && !DozeParameters.getInstance(mContext).shouldControlScreenOff();
+        mNotificationPanel.setTouchAndAnimationDisabled((!mDeviceInteractive && !mPulsing)
+                || goingToSleepWithoutAnimation);
     }
 
     final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 049972e..7d5f23b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -510,6 +510,15 @@
         }
     }
 
+    /**
+     * When we're launching an affordance, like double pressing power to open camera.
+     */
+    public void onShowingLaunchAffordanceChanged(boolean showing) {
+        if (mLockIcon != null) {
+            mLockIcon.onShowingLaunchAffordanceChanged(showing);
+        }
+    }
+
     public class LayoutParams extends FrameLayout.LayoutParams {
 
         public boolean ignoreRightInset;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 2f9d892..1b7ca95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -21,9 +21,11 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.StatusBarManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.MotionEvent;
@@ -36,6 +38,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.AmbientPulseManager;
+import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.PulseExpansionHandler;
@@ -55,6 +58,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.function.Consumer;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
@@ -90,6 +95,8 @@
     private HeadsUpTouchHelper.Callback mHeadsUpCallback;
     @Mock
     private PanelBar mPanelBar;
+    @Mock
+    private KeyguardAffordanceHelper mAffordanceHelper;
     private NotificationPanelView mNotificationPanelView;
 
     @Before
@@ -112,6 +119,9 @@
         mNotificationPanelView = new TestableNotificationPanelView(coordinator, expansionHandler);
         mNotificationPanelView.setHeadsUpManager(mHeadsUpManager);
         mNotificationPanelView.setBar(mPanelBar);
+
+        when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class));
+        when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class));
     }
 
     @Test
@@ -129,6 +139,19 @@
     }
 
     @Test
+    public void testAffordanceLaunchingListener() {
+        Consumer<Boolean> listener = spy((showing) -> { });
+        mNotificationPanelView.setExpandedFraction(1f);
+        mNotificationPanelView.setLaunchAffordanceListener(listener);
+        mNotificationPanelView.launchCamera(false /* animate */,
+                StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
+        verify(listener).accept(eq(true));
+
+        mNotificationPanelView.onAffordanceLaunchEnded();
+        verify(listener).accept(eq(false));
+    }
+
+    @Test
     public void testOnTouchEvent_expansionCanBeBlocked() {
         mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
                 0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
@@ -166,6 +189,7 @@
             mKeyguardBottomArea = NotificationPanelViewTest.this.mKeyguardBottomArea;
             mBigClockContainer = NotificationPanelViewTest.this.mBigClockContainer;
             mQsFrame = NotificationPanelViewTest.this.mQsFrame;
+            mAffordanceHelper = NotificationPanelViewTest.this.mAffordanceHelper;
             initDependencies(NotificationPanelViewTest.this.mStatusBar,
                     NotificationPanelViewTest.this.mGroupManager,
                     NotificationPanelViewTest.this.mNotificationShelf,
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 2616466..71d03a8 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7371,6 +7371,11 @@
     // Note: Only shows up on first time toggle
     DIALOG_DARK_UI_INFO = 1740;
 
+    // FIELD - Detailed reason in biometric authentication error.
+    // One of the constant value in BiometricConstants.java file.
+    // OS: Q
+    FIELD_BIOMETRIC_AUTH_ERROR = 1741;
+
     // ---- End Q Constants, all Q constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 9e1b3b8..9855e4e 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -51,8 +51,8 @@
         "android.hardware.configstore-V1.0-java",
         "android.hardware.contexthub-V1.0-java",
         "android.hidl.manager-V1.2-java",
-        "dnsresolver_aidl_interface-java",
-        "netd_aidl_interface-java",
+        "dnsresolver_aidl_interface-V2-java",
+        "netd_aidl_interface-V2-java",
         "netd_event_listener_interface-java",
     ],
 }
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index cb61259..dfbb55a 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1698,8 +1698,6 @@
             return;
         }
 
-        type = fixTypeIfAuto(type);
-
         // Sanity check the window length.  This will catch people mistakenly
         // trying to pass an end-of-window timestamp rather than a duration.
         if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
@@ -1815,21 +1813,6 @@
     }
 
     /**
-     * In case of cars, we need to avoid scheduling wakeup alarms, since we don't want the system
-     * to wake up from suspend arbitrarily to perform app work.
-     */
-    private int fixTypeIfAuto(int type) {
-        if (mInjector.isAutomotive()) {
-            if (type == AlarmManager.ELAPSED_REALTIME_WAKEUP) {
-                type = AlarmManager.ELAPSED_REALTIME;
-            } else if (type == AlarmManager.RTC_WAKEUP) {
-                type = AlarmManager.RTC;
-            }
-        }
-        return type;
-    }
-
-    /**
      * Return the minimum time that should elapse before an app in the specified bucket
      * can receive alarms again
      */
@@ -2232,7 +2215,6 @@
             pw.print("  mLastTickSet="); pw.println(sdf.format(new Date(mLastTickSet)));
             pw.print("  mLastTickAdded="); pw.println(sdf.format(new Date(mLastTickAdded)));
             pw.print("  mLastTickRemoved="); pw.println(sdf.format(new Date(mLastTickRemoved)));
-            pw.print("  mIsAutomotive="); pw.println(mInjector.isAutomotive());
 
             if (RECORD_ALARMS_IN_HISTORY) {
                 pw.println();
@@ -3899,12 +3881,9 @@
     static class Injector {
         private long mNativeData;
         private Context mContext;
-        private final boolean mIsAutomotive;
 
         Injector(Context context) {
             mContext = context;
-            mIsAutomotive = context.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_AUTOMOTIVE);
         }
 
         void init() {
@@ -3993,10 +3972,6 @@
         ClockReceiver getClockReceiver(AlarmManagerService service) {
             return service.new ClockReceiver();
         }
-
-        boolean isAutomotive() {
-            return mIsAutomotive;
-        }
     }
 
     private class AlarmThread extends Thread
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 8077e34..de96aaa 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -35,6 +35,7 @@
 import android.os.PowerManager.WakeLock;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.MutableBoolean;
@@ -404,26 +405,35 @@
      */
     @VisibleForTesting
     boolean handleCameraGesture(boolean useWakelock, int source) {
-        boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
-        if (!userSetupComplete) {
-            if (DBG) Slog.d(TAG, String.format(
-                    "userSetupComplete = %s, ignoring camera gesture.",
-                    userSetupComplete));
-            return false;
-        }
-        if (DBG) Slog.d(TAG, String.format(
-                "userSetupComplete = %s, performing camera gesture.",
-                userSetupComplete));
+        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "GestureLauncher:handleCameraGesture");
+        try {
+            boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
+            if (!userSetupComplete) {
+                if (DBG) {
+                    Slog.d(TAG, String.format(
+                            "userSetupComplete = %s, ignoring camera gesture.",
+                            userSetupComplete));
+                }
+                return false;
+            }
+            if (DBG) {
+                Slog.d(TAG, String.format(
+                        "userSetupComplete = %s, performing camera gesture.",
+                        userSetupComplete));
+            }
 
-        if (useWakelock) {
-            // Make sure we don't sleep too early
-            mWakeLock.acquire(500L);
+            if (useWakelock) {
+                // Make sure we don't sleep too early
+                mWakeLock.acquire(500L);
+            }
+            StatusBarManagerInternal service = LocalServices.getService(
+                    StatusBarManagerInternal.class);
+            service.onCameraLaunchGestureDetected(source);
+            return true;
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         }
-        StatusBarManagerInternal service = LocalServices.getService(
-                StatusBarManagerInternal.class);
-        service.onCameraLaunchGestureDetected(source);
-        return true;
     }
 
     private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 0da39e7..104cadc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -120,7 +120,7 @@
     /**
      * Default value for mFlagBackgroundActivityStartsEnabled if not explicitly set in
      * Settings.Global. This allows it to be set experimentally unless it has been
-     * enabled/disabled in developer options. Defaults to true.
+     * enabled/disabled in developer options. Defaults to false.
      */
     private static final String KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED =
             "default_background_activity_starts_enabled";
@@ -497,7 +497,7 @@
             boolean enabledInDeviceConfig = DeviceConfig.getBoolean(
                     DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                     KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED,
-                    /*defaultValue*/ true);
+                    /*defaultValue*/ false);
             mFlagBackgroundActivityStartsEnabled = enabledInDeviceConfig;
             if (!enabledInDeviceConfig) {
                 whitelistedPackageNames = DeviceConfig.getProperty(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a809d21..7a93753 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8457,18 +8457,43 @@
             }
         }
 
-        if (DEBUG_POWER) {
-            Slog.w(TAG, "noteWakupAlarm[ sourcePkg=" + sourcePkg + ", sourceUid=" + sourceUid
-                    + ", workSource=" + workSource + ", tag=" + tag + "]");
-        }
+        int standbyBucket = 0;
 
         mBatteryStatsService.noteWakupAlarm(sourcePkg, sourceUid, workSource, tag);
         if (workSource != null) {
-            StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, workSource, tag, sourcePkg);
+            String workSourcePackage = workSource.getName(0);
+            int workSourceUid = workSource.getAttributionUid();
+            if (workSourcePackage == null) {
+                workSourcePackage = sourcePkg;
+                workSourceUid = sourceUid;
+            }
+
+            if (mUsageStatsService != null) {
+                standbyBucket = mUsageStatsService.getAppStandbyBucket(workSourcePackage,
+                        UserHandle.getUserId(workSourceUid), SystemClock.elapsedRealtime());
+            }
+
+            StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, workSource, tag, sourcePkg,
+                    standbyBucket);
+            if (DEBUG_POWER) {
+                Slog.w(TAG, "noteWakeupAlarm[ sourcePkg=" + sourcePkg + ", sourceUid=" + sourceUid
+                        + ", workSource=" + workSource + ", tag=" + tag + ", standbyBucket="
+                        + standbyBucket + " wsName=" + workSourcePackage + ")]");
+            }
         } else {
+            if (mUsageStatsService != null) {
+                standbyBucket = mUsageStatsService.getAppStandbyBucket(sourcePkg,
+                        UserHandle.getUserId(sourceUid), SystemClock.elapsedRealtime());
+            }
             StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, sourceUid, null, tag,
-                    sourcePkg);
+                    sourcePkg, standbyBucket);
+            if (DEBUG_POWER) {
+                Slog.w(TAG, "noteWakeupAlarm[ sourcePkg=" + sourcePkg + ", sourceUid=" + sourceUid
+                        + ", workSource=" + workSource + ", tag=" + tag + ", standbyBucket="
+                        + standbyBucket + "]");
+            }
         }
+
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 2f1b22e..446b128 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -551,12 +551,10 @@
                             .removeAllowBackgroundActivityStartsToken(this);
                     ams.mHandler.removeCallbacks(mStartedWhitelistingBgActivityStartsCleanUp);
                 }
-                mAppForStartedWhitelistingBgActivityStarts = null;
             }
-            if (mHasStartedWhitelistingBgActivityStarts) {
-                // Make sure the cleanup callback knows about the new process.
-                mAppForStartedWhitelistingBgActivityStarts = _proc;
-            }
+            // Make sure the cleanup callback knows about the new process.
+            mAppForStartedWhitelistingBgActivityStarts = mHasStartedWhitelistingBgActivityStarts
+                    ? _proc : null;
             if (mHasStartedWhitelistingBgActivityStarts
                     || mHasBindingWhitelistingBgActivityStarts) {
                 _proc.addAllowBackgroundActivityStartsToken(this);
@@ -656,6 +654,9 @@
      */
     void whitelistBgActivityStartsOnServiceStart() {
         setHasStartedWhitelistingBgActivityStarts(true);
+        if (app != null) {
+            mAppForStartedWhitelistingBgActivityStarts = app;
+        }
 
         // This callback is stateless, so we create it once when we first need it.
         if (mStartedWhitelistingBgActivityStartsCleanUp == null) {
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index e40949b..dbc339b 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -27,21 +27,19 @@
 import android.net.metrics.ConnectStats;
 import android.net.metrics.DnsEvent;
 import android.net.metrics.INetdEventListener;
-import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.NetworkMetrics;
 import android.net.metrics.WakeupEvent;
 import android.net.metrics.WakeupStats;
 import android.os.RemoteException;
 import android.text.format.DateUtils;
-import android.util.Log;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.SparseArray;
 import android.util.StatsLog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.BitUtils;
-import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.RingBuffer;
 import com.android.internal.util.TokenBucket;
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
@@ -307,6 +305,11 @@
         }
     }
 
+    @Override
+    public int getInterfaceVersion() throws RemoteException {
+        return this.VERSION;
+    }
+
     private void addWakeupEvent(WakeupEvent event) {
         String iface = event.iface;
         mWakeupEvents.append(event);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index d8b7c2e..fa8c48b 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1170,7 +1170,7 @@
     }
 
     private void removeSyncsForAuthority(EndPoint info, String why) {
-        mLogger.log("removeSyncsForAuthority: ", info);
+        mLogger.log("removeSyncsForAuthority: ", info, why);
         verifyJobScheduler();
         List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index c7a3f4b..e09c661 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -1027,7 +1027,7 @@
      * Called when the set of account has changed, given the new array of
      * active accounts.
      */
-    public void removeStaleAccounts(@Nullable Account[] accounts, int userId) {
+    public void removeStaleAccounts(@Nullable Account[] currentAccounts, int userId) {
         synchronized (mAuthorities) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Slog.v(TAG, "Updating for new accounts...");
@@ -1036,9 +1036,11 @@
             Iterator<AccountInfo> accIt = mAccounts.values().iterator();
             while (accIt.hasNext()) {
                 AccountInfo acc = accIt.next();
-                if ((accounts == null) || (
-                        (acc.accountAndUser.userId == userId)
-                        && !ArrayUtils.contains(accounts, acc.accountAndUser.account))) {
+                if (acc.accountAndUser.userId != userId) {
+                    continue; // Irrelevant user.
+                }
+                if ((currentAccounts == null)
+                        || !ArrayUtils.contains(currentAccounts, acc.accountAndUser.account)) {
                     // This account no longer exists...
                     if (Log.isLoggable(TAG, Log.VERBOSE)) {
                         Slog.v(TAG, "Account removed: " + acc.accountAndUser);
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index b7e0a0f..8d4ad7f 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location;
 
+import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.app.AppOpsManager;
 import android.app.Notification;
@@ -27,6 +28,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.location.LocationManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PowerManager;
@@ -62,6 +64,9 @@
     // Max wait time for synchronous method onGpsEnabledChanged() to run.
     private static final long ON_GPS_ENABLED_CHANGED_TIMEOUT_MILLIS = 3 * 1000;
 
+    // How long to display location icon for each non-framework non-emergency location request.
+    private static final long LOCATION_ICON_DISPLAY_DURATION_MILLIS = 5 * 1000;
+
     // Wakelocks
     private static final String WAKELOCK_KEY = TAG;
     private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
@@ -77,10 +82,19 @@
 
     private boolean mIsGpsEnabled;
 
+    private static final class ProxyAppState {
+        private boolean mHasLocationPermission;
+        private boolean mIsLocationIconOn;
+
+        private ProxyAppState(boolean hasLocationPermission) {
+            mHasLocationPermission = hasLocationPermission;
+        }
+    }
+
     // Number of non-framework location access proxy apps is expected to be small (< 5).
-    private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
-    private ArrayMap<String, Boolean> mProxyAppToLocationPermissions = new ArrayMap<>(
-            ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS);
+    private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APPS_STATE = 5;
+    private ArrayMap<String, ProxyAppState> mProxyAppsState = new ArrayMap<>(
+            ARRAY_MAP_INITIAL_CAPACITY_PROXY_APPS_STATE);
 
     private PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
             uid -> runOnHandler(() -> handlePermissionsChanged(uid));
@@ -173,18 +187,18 @@
     }
 
     private void handleProxyAppPackageUpdate(String pkgName, String action) {
-        final Boolean locationPermission = mProxyAppToLocationPermissions.get(pkgName);
-        if (locationPermission == null) {
+        final ProxyAppState proxyAppState = mProxyAppsState.get(pkgName);
+        if (proxyAppState == null) {
             return; // ignore, pkgName is not one of the proxy apps in our list.
         }
 
         if (DEBUG) Log.d(TAG, "Proxy app " + pkgName + " package changed: " + action);
         final boolean updatedLocationPermission = shouldEnableLocationPermissionInGnssHal(pkgName);
-        if (locationPermission != updatedLocationPermission) {
+        if (proxyAppState.mHasLocationPermission != updatedLocationPermission) {
             // Permission changed. So, update the GNSS HAL with the updated list.
             Log.i(TAG, "Proxy app " + pkgName + " location permission changed."
                     + " IsLocationPermissionEnabled: " + updatedLocationPermission);
-            mProxyAppToLocationPermissions.put(pkgName, updatedLocationPermission);
+            proxyAppState.mHasLocationPermission = updatedLocationPermission;
             updateNfwLocationAccessProxyAppsInGnssHal();
         }
     }
@@ -196,35 +210,53 @@
 
         if (nfwLocationAccessProxyApps.isEmpty()) {
             // Stop listening for app permission changes. Clear the app list in GNSS HAL.
-            if (!mProxyAppToLocationPermissions.isEmpty()) {
+            if (!mProxyAppsState.isEmpty()) {
                 mPackageManager.removeOnPermissionsChangeListener(mOnPermissionsChangedListener);
-                mProxyAppToLocationPermissions.clear();
+                resetProxyAppsState();
                 updateNfwLocationAccessProxyAppsInGnssHal();
             }
             return;
         }
 
-        if (mProxyAppToLocationPermissions.isEmpty()) {
+        if (mProxyAppsState.isEmpty()) {
             mPackageManager.addOnPermissionsChangeListener(mOnPermissionsChangedListener);
         } else {
-            mProxyAppToLocationPermissions.clear();
+            resetProxyAppsState();
         }
 
         for (String proxyAppPkgName : nfwLocationAccessProxyApps) {
-            mProxyAppToLocationPermissions.put(proxyAppPkgName,
-                    shouldEnableLocationPermissionInGnssHal(proxyAppPkgName));
+            ProxyAppState proxyAppState = new ProxyAppState(shouldEnableLocationPermissionInGnssHal(
+                    proxyAppPkgName));
+            mProxyAppsState.put(proxyAppPkgName, proxyAppState);
         }
 
         updateNfwLocationAccessProxyAppsInGnssHal();
     }
 
+    private void resetProxyAppsState() {
+        // Clear location icons displayed.
+        for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
+            ProxyAppState proxyAppState = entry.getValue();
+            if (!proxyAppState.mIsLocationIconOn) {
+                continue;
+            }
+
+            mHandler.removeCallbacksAndMessages(proxyAppState);
+            final ApplicationInfo proxyAppInfo = getProxyAppInfo(entry.getKey());
+            if (proxyAppInfo != null) {
+                clearLocationIcon(proxyAppState, proxyAppInfo.uid, entry.getKey());
+            }
+        }
+        mProxyAppsState.clear();
+    }
+
     private boolean isProxyAppListUpdated(List<String> nfwLocationAccessProxyApps) {
-        if (nfwLocationAccessProxyApps.size() != mProxyAppToLocationPermissions.size()) {
+        if (nfwLocationAccessProxyApps.size() != mProxyAppsState.size()) {
             return true;
         }
 
         for (String nfwLocationAccessProxyApp : nfwLocationAccessProxyApps) {
-            if (!mProxyAppToLocationPermissions.containsKey(nfwLocationAccessProxyApp)) {
+            if (!mProxyAppsState.containsKey(nfwLocationAccessProxyApp)) {
                 return true;
             }
         }
@@ -326,11 +358,11 @@
     }
 
     private void handlePermissionsChanged(int uid) {
-        if (mProxyAppToLocationPermissions.isEmpty()) {
+        if (mProxyAppsState.isEmpty()) {
             return;
         }
 
-        for (Map.Entry<String, Boolean> entry : mProxyAppToLocationPermissions.entrySet()) {
+        for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
             final String proxyAppPkgName = entry.getKey();
             final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
             if (proxyAppInfo == null || proxyAppInfo.uid != uid) {
@@ -339,10 +371,11 @@
 
             final boolean isLocationPermissionEnabled = shouldEnableLocationPermissionInGnssHal(
                     proxyAppPkgName);
-            if (isLocationPermissionEnabled != entry.getValue()) {
+            ProxyAppState proxyAppState = entry.getValue();
+            if (isLocationPermissionEnabled != proxyAppState.mHasLocationPermission) {
                 Log.i(TAG, "Proxy app " + proxyAppPkgName + " location permission changed."
                         + " IsLocationPermissionEnabled: " + isLocationPermissionEnabled);
-                entry.setValue(isLocationPermissionEnabled);
+                proxyAppState.mHasLocationPermission = isLocationPermissionEnabled;
                 updateNfwLocationAccessProxyAppsInGnssHal();
             }
             return;
@@ -394,8 +427,8 @@
     private String[] getLocationPermissionEnabledProxyApps() {
         // Get a count of proxy apps with location permission enabled for array creation size.
         int countLocationPermissionEnabledProxyApps = 0;
-        for (Boolean hasLocationPermissionEnabled : mProxyAppToLocationPermissions.values()) {
-            if (hasLocationPermissionEnabled) {
+        for (ProxyAppState proxyAppState : mProxyAppsState.values()) {
+            if (proxyAppState.mHasLocationPermission) {
                 ++countLocationPermissionEnabledProxyApps;
             }
         }
@@ -403,10 +436,9 @@
         int i = 0;
         String[] locationPermissionEnabledProxyApps =
                 new String[countLocationPermissionEnabledProxyApps];
-        for (Map.Entry<String, Boolean> entry : mProxyAppToLocationPermissions.entrySet()) {
+        for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
             final String proxyApp = entry.getKey();
-            final boolean hasLocationPermissionEnabled = entry.getValue();
-            if (hasLocationPermissionEnabled) {
+            if (entry.getValue().mHasLocationPermission) {
                 locationPermissionEnabledProxyApps[i++] = proxyApp;
             }
         }
@@ -422,12 +454,11 @@
         }
 
         final String proxyAppPkgName = nfwNotification.mProxyAppPackageName;
-        final Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get(
-                proxyAppPkgName);
+        final ProxyAppState proxyAppState = mProxyAppsState.get(proxyAppPkgName);
         final boolean isLocationRequestAccepted = nfwNotification.isRequestAccepted();
         final boolean isPermissionMismatched =
-                (isLocationPermissionEnabled == null) ? isLocationRequestAccepted
-                        : (isLocationPermissionEnabled != isLocationRequestAccepted);
+                (proxyAppState == null) ? isLocationRequestAccepted
+                        : (proxyAppState.mHasLocationPermission != isLocationRequestAccepted);
         logEvent(nfwNotification, isPermissionMismatched);
 
         if (!nfwNotification.isRequestAttributedToProxyApp()) {
@@ -442,7 +473,7 @@
                 if (DEBUG) {
                     Log.d(TAG, "Non-framework location request rejected. ProxyAppPackageName field"
                             + " is not set in the notification: " + nfwNotification + ". Number of"
-                            + " configured proxy apps: " + mProxyAppToLocationPermissions.size());
+                            + " configured proxy apps: " + mProxyAppsState.size());
                 }
                 return;
             }
@@ -452,7 +483,7 @@
             return;
         }
 
-        if (isLocationPermissionEnabled == null) {
+        if (proxyAppState == null) {
             Log.w(TAG, "Could not find proxy app " + proxyAppPkgName + " in the value specified for"
                     + " config parameter: " + GnssConfiguration.CONFIG_NFW_PROXY_APPS
                     + ". AppOps service not notified for notification: " + nfwNotification);
@@ -467,18 +498,99 @@
             return;
         }
 
-        mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, proxyAppInfo.uid, proxyAppPkgName);
+        if (nfwNotification.isLocationProvided()) {
+            showLocationIcon(proxyAppState, nfwNotification, proxyAppInfo.uid, proxyAppPkgName);
+            mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, proxyAppInfo.uid,
+                    proxyAppPkgName);
+        }
 
         // Log proxy app permission mismatch between framework and GNSS HAL.
         if (isPermissionMismatched) {
             Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPkgName
-                    + " location permission is set to " + isLocationPermissionEnabled
+                    + " location permission is set to " + proxyAppState.mHasLocationPermission
                     + " but GNSS non-framework location access response type is "
                     + nfwNotification.getResponseTypeAsString() + " for notification: "
                     + nfwNotification);
         }
     }
 
+    private void showLocationIcon(ProxyAppState proxyAppState, NfwNotification nfwNotification,
+            int uid, String proxyAppPkgName) {
+        // If we receive a new NfwNotification before the location icon is turned off for the
+        // previous notification, update the timer to extend the location icon display duration.
+        final boolean isLocationIconOn = proxyAppState.mIsLocationIconOn;
+        if (!isLocationIconOn) {
+            if (!updateLocationIcon(/* displayLocationIcon = */ true, uid, proxyAppPkgName)) {
+                Log.w(TAG, "Failed to show Location icon for notification: " + nfwNotification);
+                return;
+            }
+            proxyAppState.mIsLocationIconOn = true;
+        } else {
+            // Extend timer by canceling the current one and starting a new one.
+            mHandler.removeCallbacksAndMessages(proxyAppState);
+        }
+
+        // Start timer to turn off location icon. proxyAppState is used as a token to cancel timer.
+        if (DEBUG) {
+            Log.d(TAG, "Location icon on. " + (isLocationIconOn ? "Extending" : "Setting")
+                    + " icon display timer. Uid: " + uid + ", proxyAppPkgName: " + proxyAppPkgName);
+        }
+        if (!mHandler.postDelayed(() -> handleLocationIconTimeout(proxyAppPkgName),
+                /* token = */ proxyAppState, LOCATION_ICON_DISPLAY_DURATION_MILLIS)) {
+            clearLocationIcon(proxyAppState, uid, proxyAppPkgName);
+            Log.w(TAG, "Failed to show location icon for the full duration for notification: "
+                    + nfwNotification);
+        }
+    }
+
+    private void handleLocationIconTimeout(String proxyAppPkgName) {
+        // Get uid again instead of using the one provided in startOp() call as the app could have
+        // been uninstalled and reinstalled during the timeout duration (unlikely in real world).
+        final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
+        if (proxyAppInfo != null) {
+            clearLocationIcon(mProxyAppsState.get(proxyAppPkgName), proxyAppInfo.uid,
+                    proxyAppPkgName);
+        }
+    }
+
+    private void clearLocationIcon(@Nullable ProxyAppState proxyAppState, int uid,
+            String proxyAppPkgName) {
+        updateLocationIcon(/* displayLocationIcon = */ false, uid, proxyAppPkgName);
+        if (proxyAppState != null) proxyAppState.mIsLocationIconOn = false;
+        if (DEBUG) {
+            Log.d(TAG, "Location icon off. Uid: " + uid + ", proxyAppPkgName: " + proxyAppPkgName);
+        }
+    }
+
+    private boolean updateLocationIcon(boolean displayLocationIcon, int uid,
+            String proxyAppPkgName) {
+        if (displayLocationIcon) {
+            // Need two calls to startOp() here with different op code so that the proxy app shows
+            // up in the recent location requests page and also the location icon gets displayed.
+            if (mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION, uid,
+                    proxyAppPkgName) != AppOpsManager.MODE_ALLOWED) {
+                return false;
+            }
+            if (mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, uid,
+                    proxyAppPkgName) != AppOpsManager.MODE_ALLOWED) {
+                mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, uid, proxyAppPkgName);
+                return false;
+            }
+        } else {
+            mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, uid, proxyAppPkgName);
+            mAppOps.finishOp(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, uid, proxyAppPkgName);
+        }
+        sendHighPowerMonitoringBroadcast();
+        return true;
+    }
+
+    private void sendHighPowerMonitoringBroadcast() {
+        // Send an intent to notify that a high power request has been added/removed so that
+        // the SystemUi checks the state of AppOps and updates the location icon accordingly.
+        Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
     private void handleEmergencyNfwNotification(NfwNotification nfwNotification) {
         boolean isPermissionMismatched = false;
         if (!nfwNotification.isRequestAccepted()) {
diff --git a/services/core/java/com/android/server/pm/ModuleInfoProvider.java b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
index 6499530..69510d9 100644
--- a/services/core/java/com/android/server/pm/ModuleInfoProvider.java
+++ b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
@@ -64,6 +64,7 @@
 
     // TODO: Move this to an earlier boot phase if anybody requires it then.
     private volatile boolean mMetadataLoaded;
+    private volatile String mPackageName;
 
     ModuleInfoProvider(Context context, IPackageManager packageManager) {
         mContext = context;
@@ -81,9 +82,9 @@
 
     /** Called by the {@code PackageManager} when it has completed its boot sequence */
     public void systemReady() {
-        final String packageName = mContext.getResources().getString(
+        mPackageName = mContext.getResources().getString(
                 R.string.config_defaultModuleMetadataProvider);
-        if (TextUtils.isEmpty(packageName)) {
+        if (TextUtils.isEmpty(mPackageName)) {
             Slog.w(TAG, "No configured module metadata provider.");
             return;
         }
@@ -91,13 +92,13 @@
         final Resources packageResources;
         final PackageInfo pi;
         try {
-            pi = mPackageManager.getPackageInfo(packageName,
+            pi = mPackageManager.getPackageInfo(mPackageName,
                 PackageManager.GET_META_DATA, UserHandle.USER_SYSTEM);
 
-            Context packageContext = mContext.createPackageContext(packageName, 0);
+            Context packageContext = mContext.createPackageContext(mPackageName, 0);
             packageResources = packageContext.getResources();
         } catch (RemoteException | NameNotFoundException e) {
-            Slog.w(TAG, "Unable to discover metadata package: " + packageName, e);
+            Slog.w(TAG, "Unable to discover metadata package: " + mPackageName, e);
             return;
         }
 
@@ -201,4 +202,11 @@
 
         return mModuleInfo.get(packageName);
     }
+
+    String getPackageName() {
+        if (!mMetadataLoaded) {
+            throw new IllegalStateException("Call to getVersion before metadata loaded");
+        }
+        return mPackageName;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e07a132..719e166 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5646,9 +5646,11 @@
     private int checkUidPermissionImpl(String permName, int uid) {
         synchronized (mPackages) {
             final String[] packageNames = getPackagesForUid(uid);
-            final PackageParser.Package pkg = (packageNames != null && packageNames.length > 0)
-                    ? mPackages.get(packageNames[0])
-                    : null;
+            PackageParser.Package pkg = null;
+            final int N = packageNames == null ? 0 : packageNames.length;
+            for (int i = 0; pkg == null && i < N; i++) {
+                pkg = mPackages.get(packageNames[i]);
+            }
             // Additional logs for b/111075456; ignore system UIDs
             if (pkg == null && UserHandle.getAppId(uid) >= Process.FIRST_APPLICATION_UID) {
                 if (packageNames == null || packageNames.length < 2) {
@@ -6385,6 +6387,16 @@
         }
     }
 
+    /**
+     * <em>IMPORTANT:</em> Not all packages returned by this method may be known
+     * to the system. There are two conditions in which this may occur:
+     * <ol>
+     *   <li>The package is on adoptable storage and the device has been removed</li>
+     *   <li>The package is being removed and the internal structures are partially updated</li>
+     * </ol>
+     * The second is an artifact of the current data structures and should be fixed. See
+     * b/111075456 for one such instance.
+     */
     @Override
     public String[] getPackagesForUid(int uid) {
         return getPackagesForUid_debug(uid, false);
@@ -24074,6 +24086,11 @@
                     | (appInfo.isVendor() ? IPackageManagerNative.LOCATION_VENDOR : 0)
                     | (appInfo.isProduct() ? IPackageManagerNative.LOCATION_PRODUCT : 0));
         }
+
+        @Override
+        public String getModuleMetadataPackageName() throws RemoteException {
+            return PackageManagerService.this.mModuleInfoProvider.getPackageName();
+        }
     }
 
     private class PackageManagerInternalImpl extends PackageManagerInternal {
@@ -24767,6 +24784,12 @@
         }
 
         @Override
+        public void forEachInstalledPackage(@NonNull Consumer<PackageParser.Package> actionLocked,
+                @UserIdInt int userId) {
+            PackageManagerService.this.forEachInstalledPackage(actionLocked, userId);
+        }
+
+        @Override
         public ArraySet<String> getEnabledComponents(String packageName, int userId) {
             synchronized (mPackages) {
                 PackageSetting setting = mSettings.getPackageLPr(packageName);
@@ -25058,6 +25081,21 @@
         }
     }
 
+    void forEachInstalledPackage(@NonNull Consumer<PackageParser.Package> actionLocked,
+            @UserIdInt int userId) {
+        synchronized (mPackages) {
+            int numPackages = mPackages.size();
+            for (int i = 0; i < numPackages; i++) {
+                PackageParser.Package pkg = mPackages.valueAt(i);
+                PackageSetting setting = mSettings.getPackageLPr(pkg.packageName);
+                if (setting == null || !setting.getInstalled(userId)) {
+                    continue;
+                }
+                actionLocked.accept(pkg);
+            }
+        }
+    }
+
     private static void enforceSystemOrPhoneCaller(String tag) {
         int callingUid = Binder.getCallingUid();
         if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 2b7691b8..2a1aee8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1347,6 +1347,7 @@
                     updatedUserIds);
             updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
                     permissionsState, pkg, newImplicitPermissions, updatedUserIds);
+            updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, updatedUserIds);
         }
 
         // Persist the runtime permissions state for users with changes. If permissions
@@ -1473,6 +1474,28 @@
     }
 
     /**
+     * When the app has requested legacy storage we might need to update
+     * {@link android.app.AppOpsManager#OP_LEGACY_STORAGE}. Hence force an update in
+     * {@link com.android.server.policy.PermissionPolicyService#synchronizePackagePermissionsAndAppOpsForUser(Context, String, int)}
+     *
+     * @param pkg The package for which the permissions are updated
+     * @param replace If the app is being replaced
+     * @param updatedUserIds The ids of the users that already changed.
+     *
+     * @return The ids of the users that are changed
+     */
+    private @NonNull int[] checkIfLegacyStorageOpsNeedToBeUpdated(
+            @NonNull PackageParser.Package pkg, boolean replace, @NonNull int[] updatedUserIds) {
+        if (replace && pkg.applicationInfo.hasRequestedLegacyExternalStorage() && (
+                pkg.requestedPermissions.contains(READ_EXTERNAL_STORAGE)
+                        || pkg.requestedPermissions.contains(WRITE_EXTERNAL_STORAGE))) {
+            return UserManagerService.getInstance().getUserIds();
+        }
+
+        return updatedUserIds;
+    }
+
+    /**
      * Set the state of a implicit permission that is seen for the first time.
      *
      * @param origPs The permission state of the package before the split
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index c809aca..02911e2 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -229,6 +229,15 @@
          *
          * @see #syncRestrictedOps
          */
+        private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllowIfDefault = new ArrayList<>();
+
+        /**
+         * All ops that need to be flipped to allow.
+         *
+         * Currently, only used by the restricted permissions logic.
+         *
+         * @see #syncRestrictedOps
+         */
         private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllow = new ArrayList<>();
 
         /**
@@ -238,7 +247,7 @@
          *
          * @see #syncRestrictedOps
          */
-        private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnore = new ArrayList<>();
+        private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnoreIfDefault = new ArrayList<>();
 
         /**
          * All foreground permissions
@@ -262,11 +271,16 @@
             final int allowCount = mOpsToAllow.size();
             for (int i = 0; i < allowCount; i++) {
                 final OpToUnrestrict op = mOpsToAllow.get(i);
+                setUidModeAllowed(op.code, op.uid);
+            }
+            final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
+            for (int i = 0; i < allowIfDefaultCount; i++) {
+                final OpToUnrestrict op = mOpsToAllowIfDefault.get(i);
                 setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
             }
-            final int ignoreCount = mOpsToIgnore.size();
-            for (int i = 0; i < ignoreCount; i++) {
-                final OpToUnrestrict op = mOpsToIgnore.get(i);
+            final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
+            for (int i = 0; i < ignoreIfDefaultCount; i++) {
+                final OpToUnrestrict op = mOpsToIgnoreIfDefault.get(i);
                 setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
             }
             final int defaultCount = mOpsToDefault.size();
@@ -341,7 +355,7 @@
                 if (applyRestriction) {
                     mOpsToDefault.add(new OpToRestrict(uid, opCode));
                 } else {
-                    mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
+                    mOpsToAllowIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
                 }
             } else if (permissionInfo.isSoftRestricted()) {
                 // Storage uses a special app op to decide the mount state and
@@ -356,7 +370,7 @@
                         mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName,
                                 AppOpsManager.OP_LEGACY_STORAGE));
                     } else {
-                        mOpsToIgnore.add(new OpToUnrestrict(uid, pkg.packageName,
+                        mOpsToIgnoreIfDefault.add(new OpToUnrestrict(uid, pkg.packageName,
                                 AppOpsManager.OP_LEGACY_STORAGE));
                     }
                 }
@@ -421,6 +435,10 @@
             setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_ALLOWED, packageName);
         }
 
+        private void setUidModeAllowed(int opCode, int uid) {
+            mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED);
+        }
+
         private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
             setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName);
         }
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 33803b7..9cd6b0d 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -280,7 +280,7 @@
         PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
         ByteArrayOutputStream out = new ByteArrayOutputStream();
 
-        pm.forEachPackage(FunctionalUtils.uncheckExceptions(pkg -> {
+        pm.forEachInstalledPackage(FunctionalUtils.uncheckExceptions(pkg -> {
             out.write(pkg.packageName.getBytes());
             out.write(BitUtils.toBytes(pkg.getLongVersionCode()));
             out.write(pm.getApplicationEnabledState(pkg.packageName, userId));
@@ -288,6 +288,7 @@
             ArraySet<String> enabledComponents =
                     pm.getEnabledComponents(pkg.packageName, userId);
             int numComponents = CollectionUtils.size(enabledComponents);
+            out.write(numComponents);
             for (int i = 0; i < numComponents; i++) {
                 out.write(enabledComponents.valueAt(i).getBytes());
             }
@@ -301,7 +302,7 @@
             for (Signature signature : pkg.mSigningDetails.signatures) {
                 out.write(signature.toByteArray());
             }
-        }));
+        }), userId);
 
         return PackageUtils.computeSha256Digest(out.toByteArray());
     }
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index da1c413..9c19aec 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -358,8 +358,8 @@
     private static void logEvent(@Nullable VersionedPackage moduleMetadataPackage, int type) {
         Slog.i(TAG, "Watchdog event occurred of type: " + type);
         if (moduleMetadataPackage != null) {
-            StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED, type,
-                    moduleMetadataPackage.getPackageName(), moduleMetadataPackage.getVersionCode());
+            StatsLog.logWatchdogRollbackOccurred(type, moduleMetadataPackage.getPackageName(),
+                    moduleMetadataPackage.getVersionCode());
         }
     }
 
diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING
index 921b754..8c7b5ac 100644
--- a/services/core/java/com/android/server/rollback/TEST_MAPPING
+++ b/services/core/java/com/android/server/rollback/TEST_MAPPING
@@ -14,5 +14,13 @@
         }
       ]
     }
+  ],
+  "imports": [
+    {
+      "path": "cts/tests/rollback"
+    },
+    {
+      "path": "cts/hostsidetests/rollback"
+    }
   ]
 }
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index c885c5e..1718ac6 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -161,7 +161,7 @@
     private ActivityOptions mOptions;
 
     // If it is true, background activity can only be started in an existing task that contains
-    // an activity with same uid.
+    // an activity with same uid, or if activity starts are enabled in developer options.
     private boolean mRestrictedBgActivity;
 
     private int mLaunchMode;
@@ -921,7 +921,7 @@
                 || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
             if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                     realCallingPid, realCallingUid, "Activity start")) {
-                if (!restrictedBgActivity) {
+                if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) {
                     mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
                             sourceRecord, startFlags, stack, callerApp));
                 }
@@ -1916,7 +1916,7 @@
 
         mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
 
-        if (restrictedBgActivity) {
+        if (mRestrictedBgActivity && !mService.isBackgroundActivityStartsEnabled()) {
             mAvoidMoveToFront = true;
             mDoResume = false;
         }
@@ -2380,7 +2380,6 @@
             if (handleBackgroundActivityAbort(mStartActivity)) {
                 return START_ABORTED;
             }
-            return START_ABORTED;
         }
         // We only want to allow changing stack in two cases:
         // 1. If the target task is not the top one. Otherwise we would move the launching task to
@@ -2553,17 +2552,15 @@
             if (handleBackgroundActivityAbort(mStartActivity)) {
                 return START_ABORTED;
             }
-            return START_ABORTED;
         }
         final TaskRecord task = (prev != null)
                 ? prev.getTaskRecord() : mTargetStack.createTaskRecord(
                 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId), mStartActivity.info,
                 mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
-        if (mRestrictedBgActivity && !task.containsAppUid(mCallingUid)) {
+        if (mRestrictedBgActivity && prev != null && !task.containsAppUid(mCallingUid)) {
             if (handleBackgroundActivityAbort(mStartActivity)) {
                 return START_ABORTED;
             }
-            return START_ABORTED;
         }
         addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
         mTargetStack.positionChildWindowContainerAtTop(task);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 772e5e6..765c9d0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -311,6 +311,9 @@
     public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000;
     // How long we wait until we timeout on key dispatching during instrumentation.
     static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000;
+    // How long we permit background activity starts after an activity in the process
+    // started or finished.
+    static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000;
 
     /** Used to indicate that an app transition should be animated. */
     static final boolean ANIMATE = true;
@@ -1575,6 +1578,13 @@
                     }
                 }
             }
+
+            // note down that the process has finished an activity and is in background activity
+            // starts grace period
+            if (r.app != null) {
+                r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis());
+            }
+
             final long origId = Binder.clearCallingIdentity();
             try {
                 boolean res;
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 12b62b9..2ad25cf 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -34,6 +34,7 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS;
 import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
 import static com.android.server.wm.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -50,6 +51,7 @@
 import android.content.res.Configuration;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
@@ -163,6 +165,11 @@
     private final ArrayList<TaskRecord> mRecentTasks = new ArrayList<>();
     // The most recent top-most activity that was resumed in the process for pre-Q app.
     private ActivityRecord mPreQTopResumedActivity = null;
+    // The last time an activity was launched in the process
+    private long mLastActivityLaunchTime;
+    // The last time an activity was finished in the process while the process participated
+    // in a visible task
+    private long mLastActivityFinishTime;
 
     // Last configuration that was reported to the process.
     private final Configuration mLastReportedConfiguration;
@@ -372,6 +379,20 @@
         return mUsingWrapper;
     }
 
+    void setLastActivityLaunchTime(long launchTime) {
+        if (launchTime <= mLastActivityLaunchTime) {
+            return;
+        }
+        mLastActivityLaunchTime = launchTime;
+    }
+
+    void setLastActivityFinishTimeIfNeeded(long finishTime) {
+        if (finishTime <= mLastActivityFinishTime || !hasActivityInVisibleTask()) {
+            return;
+        }
+        mLastActivityFinishTime = finishTime;
+    }
+
     public void setAllowBackgroundActivityStarts(boolean allowBackgroundActivityStarts) {
         mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
     }
@@ -381,6 +402,12 @@
         if (mAllowBackgroundActivityStarts) {
             return true;
         }
+        // allow if any activity in the caller has either started or finished very recently
+        final long now = SystemClock.uptimeMillis();
+        if (now - mLastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS
+                || now - mLastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) {
+            return true;
+        }
         // allow if the proc is instrumenting with background activity starts privs
         if (mInstrumentingWithBackgroundActivityStartPrivileges) {
             return true;
@@ -457,6 +484,8 @@
     }
 
     void addActivityIfNeeded(ActivityRecord r) {
+        // even if we already track this activity, note down that it has been launched
+        setLastActivityLaunchTime(r.lastLaunchTime);
         if (mActivities.contains(r)) {
             return;
         }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java b/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java
index 5acf83a..a9662c9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java
@@ -85,6 +85,10 @@
         map.put(
                 UpdateEngine.ErrorCodeConstants.PAYLOAD_HASH_MISMATCH_ERROR,
                 InstallSystemUpdateCallback.UPDATE_ERROR_UPDATE_FILE_INVALID);
+        // TODO(b/133396459): replace with a constant.
+        map.put(
+                26 /* kDownloadMetadataSignatureMismatch */,
+                InstallSystemUpdateCallback.UPDATE_ERROR_UPDATE_FILE_INVALID);
 
         // Error constants corresponding to errors related to devices bad state.
         map.put(
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 4b0a27b..fb548f9 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -65,10 +65,10 @@
     name: "services.net",
     srcs: ["java/**/*.java"],
     static_libs: [
-        "dnsresolver_aidl_interface-java",
+        "dnsresolver_aidl_interface-V2-java",
         "ipmemorystore-client",
-        "netd_aidl_interface-java",
-        "networkstack-aidl-interfaces-java",
+        "netd_aidl_interface-V2-java",
+        "networkstack-aidl-interfaces-V3-java",
     ],
 }
 
@@ -81,7 +81,7 @@
         "java/android/net/ipmemorystore/**/*.java",
     ],
     static_libs: [
-        "ipmemorystore-aidl-interfaces-java",
+        "ipmemorystore-aidl-interfaces-V3-java",
     ],
 }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 77e2517..cdcdf91 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -68,7 +68,6 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -122,8 +121,6 @@
     private AlarmManagerService.ClockReceiver mClockReceiver;
     @Mock
     private PowerManager.WakeLock mWakeLock;
-    @Mock
-    private PackageManager mMockPackageManager;
 
     private MockitoSession mMockingSession;
     private Injector mInjector;
@@ -241,11 +238,6 @@
         PowerManager.WakeLock getAlarmWakeLock() {
             return mWakeLock;
         }
-
-        @Override
-        boolean isAutomotive() {
-            return mIsAutomotiveOverride;
-        }
     }
 
     @Before
@@ -272,7 +264,6 @@
         when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
         doReturn("min_futurity=0,min_interval=0").when(() ->
                 Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS));
-        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
 
         mInjector = new Injector(mMockContext);
         mService = new AlarmManagerService(mMockContext, mInjector);
@@ -1024,18 +1015,6 @@
         assertAlarmTypeConversion(typesToSet, typesExpected);
     }
 
-    /**
-     * Confirm that wakeup alarms are never set for automotive.
-     */
-    @Test
-    public void alarmTypesForAuto() throws Exception {
-        mInjector.mIsAutomotiveOverride = true;
-        final int[] typesToSet = {ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME, RTC_WAKEUP, RTC};
-        final int[] typesExpected = {ELAPSED_REALTIME, ELAPSED_REALTIME, ELAPSED_REALTIME,
-                ELAPSED_REALTIME};
-        assertAlarmTypeConversion(typesToSet, typesExpected);
-    }
-
     private void assertAlarmTypeConversion(int[] typesToSet, int[] typesExpected) throws Exception {
         for (int i = 0; i < typesToSet.length; i++) {
             setTestAlarm(typesToSet[i], 1234, getNewMockPendingIntent());
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 1522a60..869913d 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -73,7 +73,7 @@
         "libui",
         "libunwindstack",
         "libutils",
-        "netd_aidl_interface-cpp",
+        "netd_aidl_interface-V2-cpp",
     ],
 
     dxflags: ["--multi-dex"],
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 92198fa..4a9cef1 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -55,6 +55,6 @@
         "libui",
         "libunwindstack",
         "libutils",
-        "netd_aidl_interface-cpp",
+        "netd_aidl_interface-V2-cpp",
     ],
 }
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 1ab1f7e..74c3939 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
@@ -769,7 +770,7 @@
         final Intent intent = createDeviceAttachedIntent(device);
 
         // Send broadcast to running activity with registered intent
-        mContext.sendBroadcast(intent);
+        mContext.sendBroadcastAsUser(intent, UserHandle.of(ActivityManager.getCurrentUser()));
 
         ApplicationInfo appInfo;
         try {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 55159c3..d77ea6e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -51,8 +51,6 @@
 import android.os.RemoteCallback;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -106,7 +104,6 @@
     final ArraySet<Integer> mLoadedKeyphraseIds = new ArraySet<>();
     ShortcutServiceInternal mShortcutServiceInternal;
     SoundTriggerInternal mSoundTriggerInternal;
-    private boolean mAllowInstantService;
 
     private final RemoteCallbackList<IVoiceInteractionSessionListener>
             mVoiceInteractionSessionListeners = new RemoteCallbackList<>();
@@ -173,14 +170,6 @@
         mServiceStub.switchUser(userHandle);
     }
 
-    // Called by Shell cmd
-    void setAllowInstantService(boolean allowed) {
-        Log.i(TAG, "setAllowInstantService(): " + allowed);
-        mContext.enforceCallingPermission(Manifest.permission.MANAGE_BIND_INSTANT_SERVICE,
-                "setAllowInstantService");
-        mAllowInstantService = allowed;
-    }
-
     class LocalService extends VoiceInteractionManagerInternal {
         @Override
         public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
@@ -234,7 +223,6 @@
                         new IVoiceInteractionSessionShowCallback.Stub() {
                             @Override
                             public void onFailed() {
-                                Slog.w(TAG, "startLocalVoiceInteraction() failed");
                             }
 
                             @Override
@@ -283,10 +271,7 @@
         }
 
         public void initForUser(int userHandle) {
-            if (DEBUG) {
-                Slog.d(TAG, "**************** initForUser user=" + userHandle
-                        + ", allowInstantService=" + mAllowInstantService);
-            }
+            if (DEBUG) Slog.d(TAG, "**************** initForUser user=" + userHandle);
             String curInteractorStr = Settings.Secure.getStringForUser(
                     mContext.getContentResolver(),
                     Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
@@ -445,7 +430,6 @@
             if (!mSafeMode) {
                 String curService = Settings.Secure.getStringForUser(
                         mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
-                if (DEBUG) Log.d(TAG, "Service for user " + mCurUser + ": " + curService);
                 ComponentName serviceComponent = null;
                 ServiceInfo serviceInfo = null;
                 if (curService != null && !curService.isEmpty()) {
@@ -482,8 +466,7 @@
                     }
                     if (hasComponent) {
                         setImplLocked(new VoiceInteractionManagerServiceImpl(mContext,
-                                UiThread.getHandler(), this, mCurUser, serviceComponent,
-                                mAllowInstantService));
+                                UiThread.getHandler(), this, mCurUser, serviceComponent));
                         mImpl.startLocked();
                     } else {
                         setImplLocked(null);
@@ -1244,26 +1227,16 @@
             synchronized (this) {
                 pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)");
                 pw.println("  mEnableService: " + mEnableService);
-                pw.println("  mAllowInstantService: " + mAllowInstantService);
                 if (mImpl == null) {
                     pw.println("  (No active implementation)");
                     return;
                 }
                 mImpl.dumpLocked(fd, pw, args);
             }
-
             mSoundTriggerInternal.dump(fd, pw, args);
         }
 
         @Override
-        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-                String[] args, ShellCallback callback, ResultReceiver resultReceiver)
-                throws RemoteException {
-            new VoiceInteractionManagerServiceShellCommand(VoiceInteractionManagerService.this)
-                    .exec(this, in, out, err, args, callback, resultReceiver);
-        }
-
-        @Override
         public void setUiHints(IVoiceInteractionService service, Bundle hints) {
             synchronized (this) {
                 enforceIsCurrentVoiceInteractionService(service);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 4881ade..a1210cf 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -80,7 +80,6 @@
     final VoiceInteractionServiceInfo mInfo;
     final ComponentName mSessionComponentName;
     final IWindowManager mIWindowManager;
-    final boolean mAllowInstant;
     boolean mBound = false;
     IVoiceInteractionService mService;
 
@@ -126,7 +125,7 @@
 
     VoiceInteractionManagerServiceImpl(Context context, Handler handler,
             VoiceInteractionManagerService.VoiceInteractionManagerServiceStub stub,
-            int userHandle, ComponentName service, boolean allowInstant) {
+            int userHandle, ComponentName service) {
         mContext = context;
         mHandler = handler;
         mServiceStub = stub;
@@ -134,7 +133,6 @@
         mComponent = service;
         mAm = ActivityManager.getService();
         mAtm = ActivityTaskManager.getService();
-        mAllowInstant = allowInstant;
         VoiceInteractionServiceInfo info;
         try {
             info = new VoiceInteractionServiceInfo(context.getPackageManager(), service, mUser);
@@ -169,7 +167,7 @@
         if (mActiveSession == null) {
             mActiveSession = new VoiceInteractionSessionConnection(mServiceStub,
                     mSessionComponentName, mUser, mContext, this,
-                    mInfo.getServiceInfo().applicationInfo.uid, mHandler, mAllowInstant);
+                    mInfo.getServiceInfo().applicationInfo.uid, mHandler);
         }
         List<IBinder> activityTokens = null;
         if (activityToken != null) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
deleted file mode 100644
index de1191f..0000000
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.voiceinteraction;
-
-import android.annotation.NonNull;
-import android.os.ShellCommand;
-
-import java.io.PrintWriter;
-
-final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
-
-    private final VoiceInteractionManagerService mService;
-
-    VoiceInteractionManagerServiceShellCommand(@NonNull VoiceInteractionManagerService service) {
-        this.mService = service;
-    }
-
-    @Override
-    public int onCommand(String cmd) {
-        if (cmd == null) {
-            return handleDefaultCommands(cmd);
-        }
-        final PrintWriter pw = getOutPrintWriter();
-        switch (cmd) {
-            case "set bind-instant-service-allowed":
-            case "set":
-                return requestSet(pw);
-            default:
-                return handleDefaultCommands(cmd);
-        }
-    }
-
-    @Override
-    public void onHelp() {
-        try (PrintWriter pw = getOutPrintWriter();) {
-            pw.println("VoiceInteraction Service (voiceinteraction) commands:");
-            pw.println("  help");
-            pw.println("    Prints this help text.");
-            pw.println("");
-            pw.println("  set bind-instant-service-allowed [true | false]");
-            pw.println("    Sets whether binding to services provided by instant apps is allowed");
-            pw.println("");
-        }
-    }
-
-    private int requestSet(@NonNull PrintWriter pw) {
-        final String what = getNextArgRequired();
-
-        switch(what) {
-            case "bind-instant-service-allowed":
-                return setBindInstantService(pw);
-            default:
-                pw.println("Invalid set: " + what);
-                return -1;
-        }
-    }
-
-    private int setBindInstantService(@NonNull PrintWriter pw) {
-        final String mode = getNextArgRequired();
-        switch (mode.toLowerCase()) {
-            case "true":
-                mService.setAllowInstantService(true);
-                return 0;
-            case "false":
-                mService.setAllowInstantService(false);
-                return 0;
-            default:
-                pw.println("Invalid mode: " + mode);
-                return -1;
-        }
-    }
-}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 3c47044..f16dec6 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -138,8 +138,7 @@
     };
 
     public VoiceInteractionSessionConnection(Object lock, ComponentName component, int user,
-            Context context, Callback callback, int callingUid, Handler handler,
-            boolean allowInstant) {
+            Context context, Callback callback, int callingUid, Handler handler) {
         mLock = lock;
         mSessionComponentName = component;
         mUser = user;
@@ -160,13 +159,10 @@
         mPermissionOwner = permOwner;
         mBindIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
         mBindIntent.setComponent(mSessionComponentName);
-        int flags = Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
-                | Context.BIND_ALLOW_OOM_MANAGEMENT
-                | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS;
-        if (allowInstant) {
-            flags |= Context.BIND_ALLOW_INSTANT;
-        }
-        mBound = mContext.bindServiceAsUser(mBindIntent, this, flags, new UserHandle(mUser));
+        mBound = mContext.bindServiceAsUser(mBindIntent, this,
+                Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
+                        | Context.BIND_ALLOW_OOM_MANAGEMENT
+                        | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, new UserHandle(mUser));
         if (mBound) {
             try {
                 mIWindowManager.addWindowToken(mToken, TYPE_VOICE_INTERACTION, DEFAULT_DISPLAY);
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 8c20afe..6860235 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -721,20 +721,17 @@
     }
 
     /**
-     * Divide a message text into several fragments, none bigger than
-     * the maximum SMS message size.
+     * Divide a message text into several fragments, none bigger than the maximum SMS message size.
      *
-     * @param text the original message.  Must not be null.
-     * @return an <code>ArrayList</code> of strings that, in order,
-     *   comprise the original message
-     *
-     * @throws IllegalArgumentException if text is null
+     * @param text the original message. Must not be null.
+     * @return an <code>ArrayList</code> of strings that, in order, comprise the original message.
+     * @throws IllegalArgumentException if text is null.
      */
     public ArrayList<String> divideMessage(String text) {
         if (null == text) {
             throw new IllegalArgumentException("text is null");
         }
-        return SmsMessage.fragmentText(text);
+        return SmsMessage.fragmentText(text, getSubscriptionId());
     }
 
     /**
@@ -1965,16 +1962,22 @@
     }
 
     /**
-     * Get default sms subscription id
+     * Get default sms subscription id.
      *
-     * @return the user-defined default SMS subscription id or
-     * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if no default is set.
+     * <p class="note"><strong>Note:</strong>This returns a value different from
+     * {@link SubscriptionManager#getDefaultSmsSubscriptionId} if the user has not chosen a default.
+     * In this case it returns the active subscription id if there's only one active subscription
+     * available.
+     *
+     * @return the user-defined default SMS subscription id, or the active subscription id if
+     * there's only one active subscription available, otherwise
+     * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
      */
     public static int getDefaultSmsSubscriptionId() {
         try {
-            return SubscriptionManager.getDefaultSmsSubscriptionId();
-        } catch (NullPointerException ex) {
-            return -1;
+            return getISmsServiceOrThrow().getPreferredSmsSubscription();
+        } catch (RemoteException e) {
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         }
     }
 
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 2aa4768..7d4bcb7 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -337,27 +337,45 @@
      */
 
     /**
-     * Calculates the number of SMS's required to encode the message body and
-     * the number of characters remaining until the next message.
+     * Calculates the number of SMS's required to encode the message body and the number of
+     * characters remaining until the next message.
      *
      * @param msgBody the message to encode
-     * @param use7bitOnly if true, characters that are not part of the
-     *         radio-specific 7-bit encoding are counted as single
-     *         space chars.  If false, and if the messageBody contains
-     *         non-7-bit encodable characters, length is calculated
-     *         using a 16-bit encoding.
-     * @return an int[4] with int[0] being the number of SMS's
-     *         required, int[1] the number of code units used, and
-     *         int[2] is the number of code units remaining until the
-     *         next message. int[3] is an indicator of the encoding
-     *         code unit size (see the ENCODING_* definitions in SmsConstants)
+     * @param use7bitOnly if true, characters that are not part of the radio-specific 7-bit encoding
+     *     are counted as single space chars. If false, and if the messageBody contains non-7-bit
+     *     encodable characters, length is calculated using a 16-bit encoding.
+     * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+     *     units used, and int[2] is the number of code units remaining until the next message.
+     *     int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
+     *     SmsConstants).
      */
     public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) {
+        return calculateLength(msgBody, use7bitOnly, SmsManager.getDefaultSmsSubscriptionId());
+    }
+
+    /**
+     * Calculates the number of SMS's required to encode the message body and the number of
+     * characters remaining until the next message.
+     *
+     * @param msgBody the message to encode
+     * @param use7bitOnly if true, characters that are not part of the radio-specific 7-bit encoding
+     *     are counted as single space chars. If false, and if the messageBody contains non-7-bit
+     *     encodable characters, length is calculated using a 16-bit encoding.
+     * @param subId Subscription to take SMS format.
+     * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+     *     units used, and int[2] is the number of code units remaining until the next message.
+     *     int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
+     *     SmsConstants).
+     * @hide
+     */
+    public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly, int subId) {
         // this function is for MO SMS
-        TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
-            com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly,
-                    true) :
-            com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
+        TextEncodingDetails ted =
+                useCdmaFormatForMoSms(subId)
+                        ? com.android.internal.telephony.cdma.SmsMessage.calculateLength(
+                                msgBody, use7bitOnly, true)
+                        : com.android.internal.telephony.gsm.SmsMessage.calculateLength(
+                                msgBody, use7bitOnly);
         int ret[] = new int[4];
         ret[0] = ted.msgCount;
         ret[1] = ted.codeUnitCount;
@@ -367,21 +385,37 @@
     }
 
     /**
-     * Divide a message text into several fragments, none bigger than
-     * the maximum SMS message text size.
+     * Divide a message text into several fragments, none bigger than the maximum SMS message text
+     * size.
      *
      * @param text text, must not be null.
-     * @return an <code>ArrayList</code> of strings that, in order,
-     *   comprise the original msg text
-     *
+     * @return an <code>ArrayList</code> of strings that, in order, comprise the original msg text.
      * @hide
      */
     @UnsupportedAppUsage
     public static ArrayList<String> fragmentText(String text) {
+        return fragmentText(text, SmsManager.getDefaultSmsSubscriptionId());
+    }
+
+    /**
+     * Divide a message text into several fragments, none bigger than the maximum SMS message text
+     * size.
+     *
+     * @param text text, must not be null.
+     * @param subId Subscription to take SMS format.
+     * @return an <code>ArrayList</code> of strings that, in order, comprise the original msg text.
+     * @hide
+     */
+    public static ArrayList<String> fragmentText(String text, int subId) {
         // This function is for MO SMS
-        TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
-            com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false, true) :
-            com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false);
+        final boolean isCdma = useCdmaFormatForMoSms(subId);
+
+        TextEncodingDetails ted =
+                isCdma
+                        ? com.android.internal.telephony.cdma.SmsMessage.calculateLength(
+                                text, false, true)
+                        : com.android.internal.telephony.gsm.SmsMessage.calculateLength(
+                                text, false);
 
         // TODO(cleanup): The code here could be rolled into the logic
         // below cleanly if these MAX_* constants were defined more
@@ -427,18 +461,19 @@
         String newMsgBody = null;
         Resources r = Resources.getSystem();
         if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
-            newMsgBody  = Sms7BitEncodingTranslator.translate(text);
+            newMsgBody = Sms7BitEncodingTranslator.translate(text, isCdma);
         }
         if (TextUtils.isEmpty(newMsgBody)) {
             newMsgBody = text;
         }
+
         int pos = 0;  // Index in code units.
         int textLen = newMsgBody.length();
         ArrayList<String> result = new ArrayList<String>(ted.msgCount);
         while (pos < textLen) {
             int nextPos = 0;  // Counts code units.
             if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
-                if (useCdmaFormatForMoSms() && ted.msgCount == 1) {
+                if (isCdma && ted.msgCount == 1) {
                     // For a singleton CDMA message, the encoding must be ASCII...
                     nextPos = pos + Math.min(limit, textLen - pos);
                 } else {
@@ -461,25 +496,39 @@
     }
 
     /**
-     * Calculates the number of SMS's required to encode the message body and
-     * the number of characters remaining until the next message, given the
-     * current encoding.
+     * Calculates the number of SMS's required to encode the message body and the number of
+     * characters remaining until the next message, given the current encoding.
      *
      * @param messageBody the message to encode
-     * @param use7bitOnly if true, characters that are not part of the radio
-     *         specific (GSM / CDMA) alphabet encoding are converted to as a
-     *         single space characters. If false, a messageBody containing
-     *         non-GSM or non-CDMA alphabet characters are encoded using
-     *         16-bit encoding.
-     * @return an int[4] with int[0] being the number of SMS's required, int[1]
-     *         the number of code units used, and int[2] is the number of code
-     *         units remaining until the next message. int[3] is the encoding
-     *         type that should be used for the message.
+     * @param use7bitOnly if true, characters that are not part of the radio specific (GSM / CDMA)
+     *     alphabet encoding are converted to as a single space characters. If false, a messageBody
+     *     containing non-GSM or non-CDMA alphabet characters are encoded using 16-bit encoding.
+     * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+     *     units used, and int[2] is the number of code units remaining until the next message.
+     *     int[3] is the encoding type that should be used for the message.
      */
     public static int[] calculateLength(String messageBody, boolean use7bitOnly) {
         return calculateLength((CharSequence)messageBody, use7bitOnly);
     }
 
+    /**
+     * Calculates the number of SMS's required to encode the message body and the number of
+     * characters remaining until the next message, given the current encoding.
+     *
+     * @param messageBody the message to encode
+     * @param use7bitOnly if true, characters that are not part of the radio specific (GSM / CDMA)
+     *     alphabet encoding are converted to as a single space characters. If false, a messageBody
+     *     containing non-GSM or non-CDMA alphabet characters are encoded using 16-bit encoding.
+     * @param subId Subscription to take SMS format.
+     * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+     *     units used, and int[2] is the number of code units remaining until the next message.
+     *     int[3] is the encoding type that should be used for the message.
+     * @hide
+     */
+    public static int[] calculateLength(String messageBody, boolean use7bitOnly, int subId) {
+        return calculateLength((CharSequence) messageBody, use7bitOnly, subId);
+    }
+
     /*
      * TODO(cleanup): It looks like there is now no useful reason why
      * apps should generate pdus themselves using these routines,
@@ -510,8 +559,12 @@
      */
     public static SubmitPdu getSubmitPdu(String scAddress,
             String destinationAddress, String message, boolean statusReportRequested) {
-        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested,
-                SubscriptionManager.getDefaultSmsSubscriptionId());
+        return getSubmitPdu(
+                scAddress,
+                destinationAddress,
+                message,
+                statusReportRequested,
+                SmsManager.getDefaultSmsSubscriptionId());
     }
 
     /**
@@ -834,7 +887,7 @@
     @UnsupportedAppUsage
     private static boolean useCdmaFormatForMoSms() {
         // IMS is registered with SMS support, check the SMS format supported
-        return useCdmaFormatForMoSms(SubscriptionManager.getDefaultSmsSubscriptionId());
+        return useCdmaFormatForMoSms(SmsManager.getDefaultSmsSubscriptionId());
     }
 
     /**
@@ -863,7 +916,7 @@
      * @return true if current phone type is cdma, false otherwise.
      */
     private static boolean isCdmaVoice() {
-        return isCdmaVoice(SubscriptionManager.getDefaultSmsSubscriptionId());
+        return isCdmaVoice(SmsManager.getDefaultSmsSubscriptionId());
     }
 
      /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index dab1e6f..d63c37a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -93,6 +93,8 @@
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.TelephonyProperties;
 
+import dalvik.system.VMRuntime;
+
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -108,8 +110,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import dalvik.system.VMRuntime;
-
 /**
  * Provides access to information about the telephony services on
  * the device. Applications can use the methods in this class to
@@ -1551,6 +1551,17 @@
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
+     *
      * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
      * MEID for CDMA.
      */
@@ -1581,6 +1592,17 @@
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
+     *
      * @param slotIndex of which deviceID is returned
      *
      * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
@@ -1613,6 +1635,17 @@
      * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
+     *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
      */
     @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -1631,6 +1664,17 @@
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
+     *
      * @param slotIndex of which IMEI is returned
      */
     @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@@ -1686,6 +1730,17 @@
      * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
+     *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
      */
     @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -1703,6 +1758,17 @@
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
+     *
      * @param slotIndex of which MEID is returned
      */
     @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@@ -2246,7 +2312,7 @@
     @UnsupportedAppUsage
     public String getNetworkOperatorForPhone(int phoneId) {
         return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
-     }
+    }
 
 
     /**
@@ -2446,21 +2512,7 @@
      * @return the NETWORK_TYPE_xxxx for current data connection.
      */
     public @NetworkType int getNetworkType() {
-       try {
-           ITelephony telephony = getITelephony();
-           if (telephony != null) {
-               return telephony.getNetworkType();
-            } else {
-                // This can happen when the ITelephony interface is not up yet.
-                return NETWORK_TYPE_UNKNOWN;
-            }
-        } catch(RemoteException ex) {
-            // This shouldn't happen in the normal case
-            return NETWORK_TYPE_UNKNOWN;
-        } catch (NullPointerException ex) {
-            // This could happen before phone restarts due to crashing
-            return NETWORK_TYPE_UNKNOWN;
-        }
+        return getNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
     }
 
     /**
@@ -2491,7 +2543,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public int getNetworkType(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -3217,6 +3269,17 @@
      * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
+     *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
      */
     @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -3235,6 +3298,17 @@
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
+     *
      * @param subId for which Sim Serial number is returned
      * @hide
      */
@@ -3466,6 +3540,17 @@
      * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
+     *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
      */
     @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -3485,6 +3570,17 @@
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
+     * <p>If the calling app does not meet one of these requirements then this method will behave
+     * as follows:
+     *
+     * <ul>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
+     *     READ_PHONE_STATE permission then null is returned.</li>
+     *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+     *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+     *     higher, then a SecurityException is thrown.</li>
+     * </ul>
+     *
      * @param subId whose subscriber id is returned
      * @hide
      */
@@ -5261,7 +5357,7 @@
      */
     public String getMmsUserAgent() {
         if (mContext == null) return null;
-        return mContext.getResources().getString(
+        return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString(
                 com.android.internal.R.string.config_mms_user_agent);
     }
 
@@ -5270,7 +5366,7 @@
      */
     public String getMmsUAProfUrl() {
         if (mContext == null) return null;
-        return mContext.getResources().getString(
+        return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString(
                 com.android.internal.R.string.config_mms_user_agent_profile_url);
     }
 
diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
index a774cdc..8797589 100644
--- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -16,19 +16,17 @@
 
 package com.android.internal.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.res.Resources;
+import android.os.Build;
+import android.telephony.Rlog;
 import android.text.TextUtils;
 import android.util.SparseIntArray;
 
-import android.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.telephony.Rlog;
+import com.android.internal.R;
 
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
-import com.android.internal.telephony.SmsConstants;
-import com.android.internal.R;
-
 import java.util.ArrayList;
 import java.util.List;
 
@@ -868,7 +866,6 @@
                 ted.msgCount = 1;
                 ted.codeUnitsRemaining = SmsConstants.MAX_USER_DATA_SEPTETS - septets;
             }
-            ted.codeUnitSize = SmsConstants.ENCODING_7BIT;
             return ted;
         }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 68fd9ac..63aded1 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -460,13 +460,6 @@
     void sendDialerSpecialCode(String callingPackageName, String inputCode);
 
     /**
-     * Returns the network type for data transmission
-     * Legacy call, permission-free
-     */
-    @UnsupportedAppUsage
-    int getNetworkType();
-
-    /**
      * Returns the network type of a subId.
      * @param subId user preferred subId.
      * @param callingPackage package making the call.
diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
index 439eaea..a360c64 100644
--- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
+++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
@@ -16,19 +16,14 @@
 
 package com.android.internal.telephony;
 
-import android.telephony.Rlog;
-import android.os.Build;
-import android.util.SparseIntArray;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
-import android.telephony.SmsManager;
-import android.telephony.TelephonyManager;
+import android.os.Build;
+import android.telephony.Rlog;
+import android.util.SparseIntArray;
 
-import com.android.internal.util.XmlUtils;
 import com.android.internal.telephony.cdma.sms.UserData;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
+import com.android.internal.util.XmlUtils;
 
 public class Sms7BitEncodingTranslator {
     private static final String TAG = "Sms7BitEncodingTranslator";
@@ -47,17 +42,14 @@
     private static final String XML_TO_TAG = "to";
 
     /**
-     * Translates each message character that is not supported by GSM 7bit
-     * alphabet into a supported one
+     * Translates each message character that is not supported by GSM 7bit alphabet into a supported
+     * one.
      *
-     * @param message
-     *            message to be translated
-     * @param throwsException
-     *            if true and some error occurs during translation, an exception
-     *            is thrown; otherwise a null String is returned
-     * @return translated message or null if some error occur
+     * @param message message to be translated.
+     * @param isCdmaFormat true if cdma format should be used.
+     * @return translated message or null if some error occur.
      */
-    public static String translate(CharSequence message) {
+    public static String translate(CharSequence message, boolean isCdmaFormat) {
         if (message == null) {
             Rlog.w(TAG, "Null message can not be translated");
             return null;
@@ -80,7 +72,6 @@
                 (mTranslationTableGSM != null && mTranslationTableGSM.size() > 0) ||
                 (mTranslationTableCDMA != null && mTranslationTableCDMA.size() > 0)) {
             char[] output = new char[size];
-            boolean isCdmaFormat = useCdmaFormatForMoSms();
             for (int i = 0; i < size; i++) {
                 output[i] = translateIfNeeded(message.charAt(i), isCdmaFormat);
             }
@@ -159,16 +150,6 @@
         }
     }
 
-    private static boolean useCdmaFormatForMoSms() {
-        if (!SmsManager.getDefault().isImsSmsSupported()) {
-            // use Voice technology to determine SMS format.
-            return TelephonyManager.getDefault().getCurrentPhoneType()
-                    == PhoneConstants.PHONE_TYPE_CDMA;
-        }
-        // IMS is registered with SMS support, check the SMS format supported
-        return (SmsConstants.FORMAT_3GPP2.equals(SmsManager.getDefault().getImsSmsFormat()));
-    }
-
     /**
      * Load the whole translation table file from the framework resource
      * encoded in XML.
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 2552f04..e8e2a3d 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -102,6 +102,16 @@
                 callingPackage, message);
     }
 
+    /** Identical to checkCallingOrSelfReadPhoneState but never throws SecurityException */
+    public static boolean checkCallingOrSelfReadPhoneStateNoThrow(
+            Context context, int subId, String callingPackage, String message) {
+        try {
+            return checkCallingOrSelfReadPhoneState(context, subId, callingPackage, message);
+        } catch (SecurityException se) {
+            return false;
+        }
+    }
+
     /**
      * Check whether the app with the given pid/uid can read phone state.
      *
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index a31fa0b..f2ebc98 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -16,18 +16,18 @@
 
 package com.android.internal.telephony.cdma;
 
-import android.os.Parcel;
+import android.content.res.Resources;
 import android.os.SystemProperties;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
 import android.telephony.SmsCbLocation;
 import android.telephony.SmsCbMessage;
 import android.telephony.cdma.CdmaSmsCbProgramData;
-import android.telephony.Rlog;
-import android.util.Log;
 import android.text.TextUtils;
-import android.content.res.Resources;
+import android.util.Log;
 
 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.Sms7BitEncodingTranslator;
 import com.android.internal.telephony.SmsAddress;
 import com.android.internal.telephony.SmsConstants;
 import com.android.internal.telephony.SmsHeader;
@@ -41,7 +41,6 @@
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.util.BitwiseInputStream;
 import com.android.internal.util.HexDump;
-import com.android.internal.telephony.Sms7BitEncodingTranslator;
 
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
@@ -418,7 +417,7 @@
         CharSequence newMsgBody = null;
         Resources r = Resources.getSystem();
         if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
-            newMsgBody  = Sms7BitEncodingTranslator.translate(messageBody);
+            newMsgBody = Sms7BitEncodingTranslator.translate(messageBody, true);
         }
         if (TextUtils.isEmpty(newMsgBody)) {
             newMsgBody = messageBody;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index 19465a4..e236571 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -16,34 +16,33 @@
 
 package com.android.internal.telephony.gsm;
 
-import android.telephony.PhoneNumberUtils;
-import android.text.format.Time;
-import android.telephony.Rlog;
+import static com.android.internal.telephony.SmsConstants.ENCODING_16BIT;
+import static com.android.internal.telephony.SmsConstants.ENCODING_7BIT;
+import static com.android.internal.telephony.SmsConstants.ENCODING_8BIT;
+import static com.android.internal.telephony.SmsConstants.ENCODING_KSC5601;
+import static com.android.internal.telephony.SmsConstants.ENCODING_UNKNOWN;
+import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES;
+import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_SEPTETS;
+import static com.android.internal.telephony.SmsConstants.MessageClass;
+
 import android.content.res.Resources;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
 import android.text.TextUtils;
+import android.text.format.Time;
 
 import com.android.internal.telephony.EncodeException;
 import com.android.internal.telephony.GsmAlphabet;
 import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
-import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.telephony.Sms7BitEncodingTranslator;
 import com.android.internal.telephony.SmsHeader;
 import com.android.internal.telephony.SmsMessageBase;
-import com.android.internal.telephony.Sms7BitEncodingTranslator;
+import com.android.internal.telephony.uicc.IccUtils;
 
 import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
 import java.text.ParseException;
 
-import static com.android.internal.telephony.SmsConstants.MessageClass;
-import static com.android.internal.telephony.SmsConstants.ENCODING_UNKNOWN;
-import static com.android.internal.telephony.SmsConstants.ENCODING_7BIT;
-import static com.android.internal.telephony.SmsConstants.ENCODING_8BIT;
-import static com.android.internal.telephony.SmsConstants.ENCODING_16BIT;
-import static com.android.internal.telephony.SmsConstants.ENCODING_KSC5601;
-import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_SEPTETS;
-import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES;
-import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
-
 /**
  * A Short Message Service message.
  *
@@ -914,7 +913,7 @@
         CharSequence newMsgBody = null;
         Resources r = Resources.getSystem();
         if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
-            newMsgBody  = Sms7BitEncodingTranslator.translate(msgBody);
+            newMsgBody = Sms7BitEncodingTranslator.translate(msgBody, false);
         }
         if (TextUtils.isEmpty(newMsgBody)) {
             newMsgBody = msgBody;
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 1932871..1cf3d36 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -78,45 +78,6 @@
     package_splits: ["anydpi"],
 }
 
-apex {
-    name: "com.android.tests.rollback.testapex.RollbackTestApexV1",
-    manifest: "TestApex/RollbackTestApexV1.json",
-    file_contexts: "apex.test",
-    prebuilts: ["RollbackTestApex.prebuilt.txt"],
-    key: "RollbackTestApex.key",
-    installable: false,
-}
-
-apex {
-    name: "com.android.tests.rollback.testapex.RollbackTestApexV2",
-    manifest: "TestApex/RollbackTestApexV2.json",
-    file_contexts: "apex.test",
-    prebuilts: ["RollbackTestApex.prebuilt.txt"],
-    key: "RollbackTestApex.key",
-    installable: false,
-}
-
-apex {
-    name: "com.android.tests.rollback.testapex.RollbackTestApexV3",
-    manifest: "TestApex/RollbackTestApexV3.json",
-    file_contexts: "apex.test",
-    prebuilts: ["RollbackTestApex.prebuilt.txt"],
-    key: "RollbackTestApex.key",
-    installable: false,
-}
-
-apex_key {
-    name: "RollbackTestApex.key",
-    public_key: "TestApex/com.android.tests.rollback.testapex.avbpubkey",
-    private_key: "TestApex/com.android.tests.rollback.testapex.pem",
-    installable: false,
-}
-
-prebuilt_etc {
-    name: "RollbackTestApex.prebuilt.txt",
-    src: "TestApex/RollbackTestApex.prebuilt.txt",
-}
-
 android_test {
     name: "RollbackTest",
     manifest: "RollbackTest/AndroidManifest.xml",
@@ -132,9 +93,6 @@
         ":RollbackTestAppBv2",
         ":RollbackTestAppASplitV1",
         ":RollbackTestAppASplitV2",
-        ":com.android.tests.rollback.testapex.RollbackTestApexV1",
-        ":com.android.tests.rollback.testapex.RollbackTestApexV2",
-        ":com.android.tests.rollback.testapex.RollbackTestApexV3",
     ],
     test_config: "RollbackTest.xml",
     sdk_version: "test_current",
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index b3a9f49..1ddfa6e 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -17,7 +17,6 @@
 package com.android.tests.rollback;
 
 import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals;
-import static com.android.tests.rollback.RollbackTestUtils.getRecentlyCommittedRollbackInfoById;
 import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage;
 
 import android.Manifest;
@@ -31,7 +30,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -55,15 +53,7 @@
     private static final String TAG = "RollbackTest";
     private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A";
     private static final String TEST_APP_A_V1 = "RollbackTestAppAv1.apk";
-    private static final String TEST_APP_A_V2 = "RollbackTestAppAv2.apk";
     private static final String TEST_APP_A_CRASHING_V2 = "RollbackTestAppACrashingV2.apk";
-    private static final String TEST_APEX_PKG = "com.android.tests.rollback.testapex";
-    private static final String TEST_APEX_V1 =
-            "com.android.tests.rollback.testapex.RollbackTestApexV1.apex";
-    private static final String TEST_APEX_V2 =
-            "com.android.tests.rollback.testapex.RollbackTestApexV2.apex";
-    private static final String TEST_APEX_V3 =
-            "com.android.tests.rollback.testapex.RollbackTestApexV3.apex";
 
     /**
      * Adopts common shell permissions needed for rollback tests.
@@ -85,59 +75,6 @@
         RollbackTestUtils.dropShellPermissionIdentity();
     }
 
-
-    /**
-     * Test rollbacks of staged installs involving only apks.
-     * Enable rollback phase.
-     */
-    @Test
-    public void testApkOnlyEnableRollback() throws Exception {
-        RollbackTestUtils.uninstall(TEST_APP_A);
-        assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
-        RollbackTestUtils.install(TEST_APP_A_V1, false);
-        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-        RollbackTestUtils.processUserData(TEST_APP_A);
-
-        RollbackTestUtils.installStaged(true, TEST_APP_A_V2);
-
-        // At this point, the host test driver will reboot the device and run
-        // testApkOnlyCommitRollback().
-    }
-
-    /**
-     * Test rollbacks of staged installs involving only apks.
-     * Commit rollback phase.
-     */
-    @Test
-    public void testApkOnlyCommitRollback() throws Exception {
-        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-        RollbackTestUtils.processUserData(TEST_APP_A);
-
-        RollbackManager rm = RollbackTestUtils.getRollbackManager();
-        RollbackInfo rollback = getUniqueRollbackInfoForPackage(
-                rm.getAvailableRollbacks(), TEST_APP_A);
-        assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
-        assertTrue(rollback.isStaged());
-
-        RollbackTestUtils.rollback(rollback.getRollbackId(),
-                new VersionedPackage(TEST_APP_A, 2));
-
-        rollback = getUniqueRollbackInfoForPackage(
-                rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
-        assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback, new VersionedPackage(TEST_APP_A, 2));
-        assertTrue(rollback.isStaged());
-        assertNotEquals(-1, rollback.getCommittedSessionId());
-
-        RollbackTestUtils.waitForSessionReady(rollback.getCommittedSessionId());
-
-        // The app should not be rolled back until after reboot.
-        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
-        // At this point, the host test driver will reboot the device and run
-        // testApkOnlyConfirmRollback().
-    }
-
     /**
      * Test rollbacks of staged installs involving only apks with bad update.
      * Enable rollback phase.
@@ -209,7 +146,7 @@
      * Confirm rollback phase.
      */
     @Test
-    public void testApkOnlyConfirmRollback() throws Exception {
+    public void testBadApkOnlyConfirmRollback() throws Exception {
         assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
         RollbackTestUtils.processUserData(TEST_APP_A);
 
@@ -220,171 +157,4 @@
         assertTrue(rollback.isStaged());
         assertNotEquals(-1, rollback.getCommittedSessionId());
     }
-
-    /**
-     * Test rollbacks of staged installs an apk and an apex.
-     * Enable rollback phase.
-     */
-    @Test
-    public void testApkAndApexEnableRollback() throws Exception {
-        RollbackTestUtils.uninstall(TEST_APP_A);
-        RollbackTestUtils.install(TEST_APP_A_V1, false);
-
-        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
-        RollbackTestUtils.installStaged(true, TEST_APP_A_V2, TEST_APEX_V2);
-
-        // At this point, the host test driver will reboot the device and run
-        // testApkAndApexCommitRollback().
-    }
-
-    /**
-     * Test rollbacks of staged installs an apk and an apex.
-     * Commit rollback phase.
-     */
-    @Test
-    public void testApkAndApexCommitRollback() throws Exception {
-        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
-        RollbackTestUtils.processUserData(TEST_APP_A);
-
-        RollbackManager rm = RollbackTestUtils.getRollbackManager();
-
-        RollbackInfo rollback = getUniqueRollbackInfoForPackage(
-                rm.getAvailableRollbacks(), TEST_APP_A);
-        String[] packagesNames = {TEST_APEX_PKG, TEST_APP_A};
-        assertRollbackInfoEquals(packagesNames, 2, 1, rollback);
-        assertTrue(rollback.isStaged());
-
-        RollbackTestUtils.rollback(rollback.getRollbackId());
-
-        RollbackInfo committed = getRecentlyCommittedRollbackInfoById(rollback.getRollbackId());
-
-        assertRollbackInfoEquals(packagesNames, 2, 1, committed);
-        assertTrue(committed.isStaged());
-        assertNotEquals(-1, committed.getCommittedSessionId());
-
-        RollbackTestUtils.waitForSessionReady(committed.getCommittedSessionId());
-
-        // The apex and apk should not be rolled back until after reboot.
-        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
-        // At this point, the host test driver will reboot the device and run
-        // testApkAndApexConfirmRollback().
-    }
-
-    /**
-     * Test rollbacks of staged installs an apk and an apex.
-     * Confirm rollback phase.
-     */
-    @Test
-    public void testApkAndApexConfirmRollback() throws Exception {
-        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
-        RollbackTestUtils.processUserData(TEST_APP_A);
-    }
-
-    /**
-     * Test rollbacks of staged installs involving only apex.
-     * Enable rollback phase.
-     */
-    @Test
-    public void testApexOnlyEnableRollback() throws Exception {
-        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-        RollbackTestUtils.installStaged(true, TEST_APEX_V2);
-
-        // At this point, the host test driver will reboot the device and run
-        // testApexOnlyCommitRollback().
-    }
-
-    /**
-     * Test rollbacks of staged installs involving only apex.
-     * Commit rollback phase.
-     */
-    @Test
-    public void testApexOnlyCommitRollback() throws Exception {
-        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-
-        RollbackManager rm = RollbackTestUtils.getRollbackManager();
-        RollbackInfo rollback = getUniqueRollbackInfoForPackage(
-                rm.getAvailableRollbacks(), TEST_APEX_PKG);
-        assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, rollback);
-        assertTrue(rollback.isStaged());
-
-        RollbackTestUtils.rollback(rollback.getRollbackId());
-
-        RollbackInfo committed = getRecentlyCommittedRollbackInfoById(rollback.getRollbackId());
-
-        assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, committed);
-        assertTrue(committed.isStaged());
-        assertNotEquals(-1, committed.getCommittedSessionId());
-
-        RollbackTestUtils.waitForSessionReady(committed.getCommittedSessionId());
-
-        // The apex should not be rolled back until after reboot.
-        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-
-        // At this point, the host test driver will reboot the device and run
-        // testApexOnlyConfirmRollback().
-    }
-
-    /**
-     * Test rollbacks of staged installs involving only apex.
-     * Confirm rollback phase.
-     */
-    @Test
-    public void testApexOnlyConfirmRollback() throws Exception {
-        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-    }
-
-    /**
-     * Tests that apex update expires existing rollbacks for that apex.
-     * Enable rollback phase.
-     */
-    @Test
-    public void testApexRollbackExpirationEnableRollback() throws Exception {
-        assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-        RollbackTestUtils.installStaged(true, TEST_APEX_V2);
-
-        // At this point, the host test driver will reboot the device and run
-        // testApexRollbackExpirationUpdateApex().
-    }
-
-    /**
-     * Tests that apex update expires existing rollbacks for that apex.
-     * Update apex phase.
-     */
-    @Test
-    public void testApexRollbackExpirationUpdateApex() throws Exception {
-        assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-        RollbackTestUtils.installStaged(false, TEST_APEX_V3);
-
-        // At this point, the host test driver will reboot the device and run
-        // testApexRollbackExpirationConfirmExpiration().
-    }
-
-    /**
-     * Tests that apex update expires existing rollbacks for that apex.
-     * Confirm expiration phase.
-     */
-    @Test
-    public void testApexRollbackExpirationConfirmExpiration() throws Exception {
-        assertEquals(3, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-
-        RollbackManager rm = RollbackTestUtils.getRollbackManager();
-        assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APEX_PKG));
-    }
-
-    /**
-     * Helper function called by the host test to install v1 of the test apex,
-     * assuming the test apex is not installed.
-     */
-    @Test
-    public void installTestApexV1() throws Exception {
-        RollbackTestUtils.installStaged(false, TEST_APEX_V1);
-    }
 }
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 2433434..75a95ad 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -19,7 +19,6 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -32,9 +31,6 @@
  */
 @RunWith(DeviceJUnit4ClassRunner.class)
 public class StagedRollbackTest extends BaseHostJUnit4Test {
-
-    private static final String TEST_APEX_PKG = "com.android.tests.rollback.testapex";
-
     /**
      * Runs the given phase of a test by calling into the device.
      * Throws an exception if the test phase fails.
@@ -48,18 +44,6 @@
     }
 
     /**
-     * Tests staged rollbacks involving only apks.
-     */
-    @Test
-    public void testApkOnly() throws Exception {
-        runPhase("testApkOnlyEnableRollback");
-        getDevice().reboot();
-        runPhase("testApkOnlyCommitRollback");
-        getDevice().reboot();
-        runPhase("testApkOnlyConfirmRollback");
-    }
-
-    /**
      * Tests watchdog triggered staged rollbacks involving only apks.
      */
     @Test
@@ -79,66 +63,6 @@
         }
 
         getDevice().waitForDeviceAvailable();
-        runPhase("testApkOnlyConfirmRollback");
-    }
-
-    /**
-     * Tests staged rollbacks involving only apex.
-     */
-    @Test
-    public void testApexOnly() throws Exception {
-        installTestApexV1();
-        runPhase("testApexOnlyEnableRollback");
-        getDevice().reboot();
-        runPhase("testApexOnlyCommitRollback");
-        getDevice().reboot();
-        runPhase("testApexOnlyConfirmRollback");
-    }
-
-    /**
-     * Tests staged rollbacks involving apk and apex.
-     */
-    @Test
-    public void testApkAndApex() throws Exception {
-        installTestApexV1();
-        runPhase("testApkAndApexEnableRollback");
-        getDevice().reboot();
-        runPhase("testApkAndApexCommitRollback");
-        getDevice().reboot();
-        runPhase("testApkAndApexConfirmRollback");
-    }
-
-    /**
-     * Tests that apex update expires existing rollbacks for that apex.
-     */
-    @Test
-    public void testApexRollbackExpiration() throws Exception {
-        installTestApexV1();
-        runPhase("testApexRollbackExpirationEnableRollback");
-        getDevice().reboot();
-        runPhase("testApexRollbackExpirationUpdateApex");
-        getDevice().reboot();
-        runPhase("testApexRollbackExpirationConfirmExpiration");
-    }
-
-    /**
-     * Do whatever is necessary to get version 1 of the test apex installed on
-     * the device. Try to do so without extra reboots where possible to keep
-     * the test execution time down.
-     */
-    private void installTestApexV1() throws Exception {
-        for (ITestDevice.ApexInfo apexInfo : getDevice().getActiveApexes()) {
-            if (TEST_APEX_PKG.equals(apexInfo.name)) {
-                if (apexInfo.versionCode == 1) {
-                    return;
-                }
-                getDevice().uninstallPackage(TEST_APEX_PKG);
-                getDevice().reboot();
-                break;
-            }
-        }
-
-        runPhase("installTestApexV1");
-        getDevice().reboot();
+        runPhase("testBadApkOnlyConfirmRollback");
     }
 }
diff --git a/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt b/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt
deleted file mode 100644
index e871146..0000000
--- a/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-This file contains dummy content to include in the RollbackTestApex.
-
diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV1.json b/tests/RollbackTest/TestApex/RollbackTestApexV1.json
deleted file mode 100644
index c3239ca..0000000
--- a/tests/RollbackTest/TestApex/RollbackTestApexV1.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "name": "com.android.tests.rollback.testapex",
-    "version": 1
-}
diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV2.json b/tests/RollbackTest/TestApex/RollbackTestApexV2.json
deleted file mode 100644
index 9de3f45..0000000
--- a/tests/RollbackTest/TestApex/RollbackTestApexV2.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "name": "com.android.tests.rollback.testapex",
-    "version": 2
-}
diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV3.json b/tests/RollbackTest/TestApex/RollbackTestApexV3.json
deleted file mode 100644
index 87a2c9d..0000000
--- a/tests/RollbackTest/TestApex/RollbackTestApexV3.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "name": "com.android.tests.rollback.testapex",
-    "version": 3
-}
diff --git a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey
deleted file mode 100644
index b347331..0000000
--- a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem
deleted file mode 100644
index 7181ce5..0000000
--- a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEArBLX+v6RMiK6soQFgbc0RZ+wticTD5sCbu9Q5B5WT7UnV1Wt
-cNI/n2bjks3UYNxTneOzMQOVjd4ln0BYZoNvoDtrc1BsYABpt4FywSq1zz/3sp3L
-3Vp8vaUyRsx0Da+PcOdYHPFs1WPX3Shw3MSPhUO/72KTm6GhO/cHEPEzSQLaw/zO
-8FiPpDdRqILqVJlu1DZ+i1DO+To9mKt59uLlxy3F+HAMnQaNW6+2NCV/vdCxQrEL
-m7PpsM6DymsFKcvVra1Il4apKkYNgcgTQ+AlmyPxGo6twfZvRMrU3bcrUmrg3OAx
-tMD7MufXlKkoFMlT5clrQ7P2ErKoFxhTVWhBL5ZJv/lKwaTfxCLyNvYQ7JALKtOL
-9xx4c77NdyYVjxMDAJ7E+Uj3QjdOv3FxM38Fcvt0zN4SSlmDjEDtm2e2w53Ztgz1
-zHAuNllIW1zGdPqa+ROoa9JLJePlyNXG9Rn1sSkjM9WwteaJ3nrdje6uBsvo7I9g
-1MWab2XNXQwJNHACICtyU7QPryGP4U/lyHqWEkdoXrs8O36gmTGU/EsJYSIVILax
-0HZC3zkmxHgiN95ZvD+Y5Y9HDXAN04kT8O1V/QD4QUCP8MGXNrkQP/JZAnu5Y2D1
-Wrn/7Tft2ON3OpH5vUgR99bKR549LcRrYgxeTnci3xkOsnTjZRxEUJFQgVUCAwEA
-AQKCAgEAlBzIMbDLk+cW4rAG+WeTo9ZXygKKQqV/i7OM4j5GtudMTL1fxDwFLZTn
-kCaBhzo+8ynaxPa71ViA87n0HZFHFRnwXFq+XkgctyrCdwjnY9RAxktS/l5z/t1i
-EFTOFDWod1t6mbcpoegGF8RGmZDLpL7zR/+G5LBUU4RHXcrwBQli+s3x5imkwoon
-TLAbOeSz5BBgDlTpQtdhy7bWDa+ybya0QCtagBLyvBfb8rjQYrduzOQOBODw5xJr
-mGFUGWztqUf9swfjNpMD71EjXApk9EwUrXJgmBMiJYmdfpa6wH9kvFpyDo8J6gBr
-rPeJm5LMF3+vR6Bw0Bld3DtBB8PsTrockOdeJNHfnY54480e7AahfM5gkeuIYC4P
-E3CIbyAgpS8+OLpsXP207AOjFz1TLiOqyDUDsBqSMNEQ7QbIPTQw8UZ/o0vEoqEv
-RrJAvIAv0KUcFNUL0t6VX2OXbV+i+T85wPey3XqK9P8Zzc8NUEGJ2paDUkSuemKC
-nF9/siGaoBHXsNUkQuV9xYo4co66MHDGAx/OdUM5lPiUcrF/bR+ZUA3p1BLUQXbQ
-aJD9uKlvJ4ZRSwhR/fQc5UiVWl3l76k+0Ia/Ddd1ArphVhbvGPOsm3W7wJ6KukSk
-rBJh1PPV1HnA+icS2Wvu2kVdz9+39cQUYJIICO1uwWfPIb/R5MUCggEBAOSwkwXs
-jqewNc6X4mc19RGKIMUvOrRrQkOOY33pI+BjoqI8cl+NOHNB7F8/gVnHIfhZpOG6
-WD5St1/qlSPT1Nte+38P+woAp5mdclZyRgYb4MjZybZihUPIPVgUbxiZTDHy1Sw0
-kRgmvaV3ccvG9/9bBUKNr9Z+XySsIhq5DzY+yIZ33vhLB/0g05x2HVIsSlsRWzri
-lw0iX/v07bdIRUIv7QB8xcLY/23pIbHAXS8DaknN8YxpKtjilOnUWVp/dx4SIcJY
-6PtSBfPcwVJ2MA/xXWBvDP82/XxvbxKnjj8lvkbfqMC6jrXJBw3NT/he8b932IBb
-PwLGU4hoKvjXfUcCggEBAMCfa4N1KUXW0Mo3BcDk2Hk8zVYuTPDNTWg1Mxb46sn+
-HNVJKU0OrejM2hNNCwzJG7eVQBorJj5XefhaQFTvWoLKbf1YZuWKaQrRwKkHEqDi
-edplA2RkpUebeS4KYIr22rzu3ZrZqiJmRU5kAS9hwOzwFvnXUgGy7IoZKXhpo0HK
-xvwylb/C5FXh97tecDdH/5evB/DC515TIhPzUQ5tpT0oAl9MU7Pe1E/opzrD/0sR
-dqKVJcl9vBRbtcAIkCOVpLoA9T2VvisafZAJaRXc3ACFMceewgpVAtBCsWUtLfvW
-fHMHWfti5je19SWg7bUK56uHJ0vdAI+irkfpe1t0aoMCggEAR5cPL3eSYOREs9vQ
-QEcf5NG82H2kfv5kzAkzFCN7267VJryNgWQQG+SzPk3/DD/OXpSRjShsn3X9ecVR
-0tlpdRMS3//8snDqBqjHNlCnoxnvEHE9OB83YLS6n2wmKykyNSCzoxcBpPHbxITT
-1tr+n626w87fEOKWnkBUnND59h1JYO79mfTDF3bDR+Oh4iuDS2bvjEuKxc3RBmry
-T8IMDGA8bT6iGhEcRSgKKD7z7NfA2kHiL/ZsN2EXBOw43J+yhnNephx3MtXGj0S4
-MDxXZ2ZDuQCKrQpl6CJqPwi8+v+xxTYW+d5s9nNsBeIT+sieHTZDTEtEOnYjiDwz
-15p92QKCAQEAkMwGNQawpOhLgYcFEzC0LcbwEFWzztx10N0U77LkRD16jTZ3Do73
-WmYLlLC4mr7e0A0o58MB96EodfHaJD7dSi5Dqkt25hw6xEBS1H0Vms1EjlCa0S/7
-Mq4D1QFF+5B/c8EX4ty20S8R8FCqt2SDc1kz3FHpOo+20kUB8Jtwdveox1J7UXB+
-1rSL1lSyhEviLbMMhAbvh+90UYz5pJ/1s9hMmDi3PyJFdWBNvZYyZcrV5He7tRCI
-fsFGCfol6CoIby5jLA1Rq/M46jq4vQ+ObfGyLv3/nWa0O7u2wHjK9WIRoSKomJmK
-t9xXURb9Obfd2Qo7FwMl9dNzsWkpKuGDYwKCAQB+hiWu2C+0foJ4Z8auM1SK8be4
-waplfD7qIvONE/vtl+VAN+eVpz5kkQJfXiafktAHahgEdSx43bofR0Kv0/R7IRs3
-M1WYAr0w+19TXLXkuh2oYIbcoGrIN3HMmlKMv44xh/QUhRe337cCLejP0SESNN+k
-5wT91SbJwuCw/QsG3sD6NIMtCNWdcsAQq/ruhz7pQ/JZUFOueV0tkzbK+oNHWbNU
-lS99qjPaVCXZFlz/t2/89cljh9mtRjcfXIBfuTijN9sXNcLTXsfLsyHJ86eEbI2U
-o2JQ7Sjs10LpiwBbNNHBmulARgRONNMgik6tpNIS0tk9eke0lCX42bDFtAD4
------END RSA PRIVATE KEY-----
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 1fbb658..306cc51 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -56,7 +56,7 @@
         "libutilscallstack",
         "libziparchive",
         "libz",
-        "netd_aidl_interface-cpp",
+        "netd_aidl_interface-V2-cpp",
         "libnetworkstatsfactorytestjni",
     ],
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b0cc207..fa059fa 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -3816,11 +3816,20 @@
         networkCallback.assertNoCallback();
     }
 
+    @Test
+    public void testUnfulfillableNetworkRequest() throws Exception {
+        runUnfulfillableNetworkRequest(false);
+    }
+
+    @Test
+    public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
+        runUnfulfillableNetworkRequest(true);
+    }
+
     /**
      * Validate the callback flow for a factory releasing a request as unfulfillable.
      */
-    @Test
-    public void testUnfulfillableNetworkRequest() throws Exception {
+    private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3855,14 +3864,25 @@
             }
         }
 
-        // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
         testFactory.expectRemoveRequests(1);
-        testFactory.triggerUnfulfillable(requests.get(newRequestId));
-        networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
-        testFactory.waitForRequests();
+        if (preUnregister) {
+            mCm.unregisterNetworkCallback(networkCallback);
 
-        // unregister network callback - a no-op, but should not fail
-        mCm.unregisterNetworkCallback(networkCallback);
+            // Simulate the factory releasing the request as unfulfillable: no-op since
+            // the callback has already been unregistered (but a test that no exceptions are
+            // thrown).
+            testFactory.triggerUnfulfillable(requests.get(newRequestId));
+        } else {
+            // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
+            testFactory.triggerUnfulfillable(requests.get(newRequestId));
+
+            networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
+            testFactory.waitForRequests();
+
+            // unregister network callback - a no-op (since already freed by the
+            // on-unavailable), but should not fail or throw exceptions.
+            mCm.unregisterNetworkCallback(networkCallback);
+        }
 
         testFactory.unregister();
         handlerThread.quit();