Merge "Add enums for battery settings page."
diff --git a/api/current.txt b/api/current.txt
index db13a0b..2e33d01 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10482,8 +10482,11 @@
     field public static final int GET_SIGNATURES = 64; // 0x40
     field public static final deprecated int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
+    field public static final int INSTALL_REASON_DEVICE_RESTORE = 2; // 0x2
+    field public static final int INSTALL_REASON_DEVICE_SETUP = 3; // 0x3
     field public static final int INSTALL_REASON_POLICY = 1; // 0x1
     field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0
+    field public static final int INSTALL_REASON_USER = 4; // 0x4
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
     field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
@@ -36417,7 +36420,6 @@
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
-    field public static final int PURPOSE_WRAP_KEY = 16; // 0x10
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 9536d13..7b9d05b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -11084,8 +11084,11 @@
     field public static final int INSTALL_PARSE_FAILED_NOT_APK = -100; // 0xffffff9c
     field public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; // 0xffffff99
     field public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; // 0xffffff9a
+    field public static final int INSTALL_REASON_DEVICE_RESTORE = 2; // 0x2
+    field public static final int INSTALL_REASON_DEVICE_SETUP = 3; // 0x3
     field public static final int INSTALL_REASON_POLICY = 1; // 0x1
     field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0
+    field public static final int INSTALL_REASON_USER = 4; // 0x4
     field public static final int INSTALL_SUCCEEDED = 1; // 0x1
     field public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS = 2; // 0x2
     field public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK = 4; // 0x4
@@ -39340,7 +39343,6 @@
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
-    field public static final int PURPOSE_WRAP_KEY = 16; // 0x10
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 5776bc3..625c4b0 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -10517,8 +10517,11 @@
     field public static final int GET_SIGNATURES = 64; // 0x40
     field public static final deprecated int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
+    field public static final int INSTALL_REASON_DEVICE_RESTORE = 2; // 0x2
+    field public static final int INSTALL_REASON_DEVICE_SETUP = 3; // 0x3
     field public static final int INSTALL_REASON_POLICY = 1; // 0x1
     field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0
+    field public static final int INSTALL_REASON_USER = 4; // 0x4
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
     field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
@@ -36556,7 +36559,6 @@
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
-    field public static final int PURPOSE_WRAP_KEY = 16; // 0x10
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 73dc996..b3b5bcf 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -745,7 +745,8 @@
     public static final int DONT_KILL_APP = 0x00000001;
 
     /** @hide */
-    @IntDef({INSTALL_REASON_UNKNOWN, INSTALL_REASON_POLICY})
+    @IntDef({INSTALL_REASON_UNKNOWN, INSTALL_REASON_POLICY, INSTALL_REASON_DEVICE_RESTORE,
+            INSTALL_REASON_DEVICE_SETUP, INSTALL_REASON_USER})
     @Retention(RetentionPolicy.SOURCE)
     public @interface InstallReason {}
 
@@ -760,6 +761,21 @@
     public static final int INSTALL_REASON_POLICY = 1;
 
     /**
+     * Code indicating that this package was installed as part of restoring from another device.
+     */
+    public static final int INSTALL_REASON_DEVICE_RESTORE = 2;
+
+    /**
+     * Code indicating that this package was installed as part of device setup.
+     */
+    public static final int INSTALL_REASON_DEVICE_SETUP = 3;
+
+    /**
+     * Code indicating that the package installation was initiated by the user.
+     */
+    public static final int INSTALL_REASON_USER = 4;
+
+    /**
      * Installation return code: this is passed to the
      * {@link IPackageInstallObserver} on success.
      *
@@ -6126,6 +6142,9 @@
      *
      * @see #INSTALL_REASON_UNKNOWN
      * @see #INSTALL_REASON_POLICY
+     * @see #INSTALL_REASON_DEVICE_RESTORE
+     * @see #INSTALL_REASON_DEVICE_SETUP
+     * @see #INSTALL_REASON_USER
      *
      * @hide
      */
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 5461e6b..ad8ad69 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -138,8 +138,6 @@
     public static final int KM_PURPOSE_DECRYPT = 1;
     public static final int KM_PURPOSE_SIGN = 2;
     public static final int KM_PURPOSE_VERIFY = 3;
-    public static final int KM_PURPOSE_DERIVE_KEY = 4;
-    public static final int KM_PURPOSE_WRAP_KEY = 5;
 
     // Key formats.
     public static final int KM_KEY_FORMAT_X509 = 0;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6430633..61b1247 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -404,6 +404,15 @@
         }
     }
 
+    private Rect getParentSurfaceInsets() {
+        final ViewRootImpl root = getViewRootImpl();
+        if (root == null) {
+            return null;
+        } else {
+            return root.mWindowAttributes.surfaceInsets;
+        }
+    }
+
     /** @hide */
     protected void updateSurface() {
         if (!mHaveFrame) {
@@ -459,6 +468,9 @@
                     mTranslator.translateRectInAppWindowToScreen(mScreenRect);
                 }
 
+                final Rect surfaceInsets = getParentSurfaceInsets();
+                mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
+
                 if (creating) {
                     mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
                     mSurfaceControl = new SurfaceControl(mSurfaceSession,
@@ -615,7 +627,7 @@
         } else {
             // Calculate the window position in case RT loses the window
             // and we need to fallback to a UI-thread driven position update
-            getLocationInWindow(mLocation);
+            getLocationInSurface(mLocation);
             final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
                     || mWindowSpaceTop != mLocation[1];
             final boolean layoutSizeChanged = getWidth() != mScreenRect.width()
@@ -628,8 +640,6 @@
                 mLocation[0] = getWidth();
                 mLocation[1] = getHeight();
 
-                transformFromViewToWindowSpace(mLocation);
-
                 mScreenRect.set(mWindowSpaceLeft, mWindowSpaceTop,
                         mLocation[0], mLocation[1]);
 
@@ -688,6 +698,7 @@
         if (mSurfaceControl == null) {
             return;
         }
+
         // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
         // its 2nd frame if RenderThread is running slowly could potentially see
         // this as false, enter the branch, get pre-empted, then this comes along
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index c348cc5..a196540 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -232,6 +232,73 @@
     return localBitmap->bitmap();
 }
 
+void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
+    SkASSERT(info);
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+    LocalScopedBitmap localBitmap(bitmapHandle);
+
+    const SkImageInfo& imageInfo = localBitmap->info();
+    info->width = imageInfo.width();
+    info->height = imageInfo.height();
+    info->stride = localBitmap->rowBytes();
+    info->flags = 0;
+    switch (imageInfo.colorType()) {
+        case kN32_SkColorType:
+            info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
+            break;
+        case kRGB_565_SkColorType:
+            info->format = ANDROID_BITMAP_FORMAT_RGB_565;
+            break;
+        case kARGB_4444_SkColorType:
+            info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
+            break;
+        case kAlpha_8_SkColorType:
+            info->format = ANDROID_BITMAP_FORMAT_A_8;
+            break;
+        default:
+            info->format = ANDROID_BITMAP_FORMAT_NONE;
+            break;
+    }
+}
+
+void* lockPixels(JNIEnv* env, jobject bitmap) {
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+
+    LocalScopedBitmap localBitmap(bitmapHandle);
+    if (!localBitmap->valid()) return nullptr;
+
+    SkPixelRef& pixelRef = localBitmap->bitmap();
+    pixelRef.lockPixels();
+    if (!pixelRef.pixels()) {
+        pixelRef.unlockPixels();
+        return nullptr;
+    }
+    pixelRef.ref();
+    return pixelRef.pixels();
+}
+
+bool unlockPixels(JNIEnv* env, jobject bitmap) {
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+
+    LocalScopedBitmap localBitmap(bitmapHandle);
+    if (!localBitmap->valid()) return false;
+
+    SkPixelRef& pixelRef = localBitmap->bitmap();
+    pixelRef.notifyPixelsChanged();
+    pixelRef.unlockPixels();
+    pixelRef.unref();
+    return true;
+}
+
 } // namespace bitmap
 
 } // namespace android
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index 387a128..a4bfc94 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -17,6 +17,7 @@
 #define BITMAP_H_
 
 #include <jni.h>
+#include <android/bitmap.h>
 #include <SkBitmap.h>
 #include <SkColorTable.h>
 #include <SkImageInfo.h>
@@ -44,6 +45,13 @@
 Bitmap& toBitmap(JNIEnv* env, jobject bitmap);
 Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle);
 
+// NDK access
+void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info);
+// Returns a pointer to the pixels or nullptr if the bitmap is not valid
+void* lockPixels(JNIEnv* env, jobject bitmap);
+// Returns true if unlocked, false if the bitmap is no longer valid (destroyed)
+bool unlockPixels(JNIEnv* env, jobject bitmap);
+
 /** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
     sync with isPremultiplied
 */
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index edcbb3f..6e8c931 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -452,10 +452,6 @@
             const RenderProperties& props = node.properties();
             uirenderer::Rect bounds(props.getWidth(), props.getHeight());
             transform.mapRect(bounds);
-            bounds.left -= info.windowInsetLeft;
-            bounds.right -= info.windowInsetLeft;
-            bounds.top -= info.windowInsetTop;
-            bounds.bottom -= info.windowInsetTop;
 
             if (CC_LIKELY(transform.isPureTranslate())) {
                 // snap/round the computed bounds, so they match the rounding behavior
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 37eae48a..99edf6e 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -178,13 +178,9 @@
             }
         }
         // TODO: This is hacky
-        info.windowInsetLeft = -stagingProperties().getLeft();
-        info.windowInsetTop = -stagingProperties().getTop();
         info.updateWindowPositions = true;
         RenderNode::prepareTree(info);
         info.updateWindowPositions = false;
-        info.windowInsetLeft = 0;
-        info.windowInsetTop = 0;
         info.errorHandler = nullptr;
     }
 
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index bf7a779a..d6b1cf1 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -45,7 +45,6 @@
                 PURPOSE_DECRYPT,
                 PURPOSE_SIGN,
                 PURPOSE_VERIFY,
-                PURPOSE_WRAP_KEY,
                 })
     public @interface PurposeEnum {}
 
@@ -70,12 +69,6 @@
     public static final int PURPOSE_VERIFY = 1 << 3;
 
     /**
-     * Purpose of key: wrapping key for secure key import.
-     */
-    public static final int PURPOSE_WRAP_KEY = 1 << 4;
-
-
-    /**
      * @hide
      */
     public static abstract class Purpose {
@@ -91,8 +84,6 @@
                     return KeymasterDefs.KM_PURPOSE_SIGN;
                 case PURPOSE_VERIFY:
                     return KeymasterDefs.KM_PURPOSE_VERIFY;
-                case PURPOSE_WRAP_KEY:
-                    return KeymasterDefs.KM_PURPOSE_WRAP_KEY;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
@@ -108,8 +99,6 @@
                     return PURPOSE_SIGN;
                 case KeymasterDefs.KM_PURPOSE_VERIFY:
                     return PURPOSE_VERIFY;
-                case KeymasterDefs.KM_PURPOSE_WRAP_KEY:
-                    return PURPOSE_WRAP_KEY;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index c6fbe2bd5..e39614b 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -91,8 +91,6 @@
     LayerUpdateQueue* layerUpdateQueue = nullptr;
     ErrorHandler* errorHandler = nullptr;
 
-    int32_t windowInsetLeft = 0;
-    int32_t windowInsetTop = 0;
     bool updateWindowPositions = false;
 
     struct Out {
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index 6d2de98..bf5cabb 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -15,11 +15,7 @@
  */
 
 #include <android/bitmap.h>
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <GraphicsJNI.h>
-#pragma GCC diagnostic pop
+#include <Bitmap.h>
 
 int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
                           AndroidBitmapInfo* info) {
@@ -27,32 +23,8 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkBitmap bm;
-    GraphicsJNI::getSkBitmap(env, jbitmap, &bm);
-
     if (info) {
-        info->width     = bm.width();
-        info->height    = bm.height();
-        info->stride    = bm.rowBytes();
-        info->flags     = 0;
-
-        switch (bm.colorType()) {
-            case kN32_SkColorType:
-                info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
-                break;
-            case kRGB_565_SkColorType:
-                info->format = ANDROID_BITMAP_FORMAT_RGB_565;
-                break;
-            case kARGB_4444_SkColorType:
-                info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
-                break;
-            case kAlpha_8_SkColorType:
-                info->format = ANDROID_BITMAP_FORMAT_A_8;
-                break;
-            default:
-                info->format = ANDROID_BITMAP_FORMAT_NONE;
-                break;
-        }
+        android::bitmap::imageInfo(env, jbitmap, info);
     }
     return ANDROID_BITMAP_RESULT_SUCCESS;
 }
@@ -62,19 +34,11 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkPixelRef* pixelRef = GraphicsJNI::refSkPixelRef(env, jbitmap);
-    if (!pixelRef) {
+    void* addr = android::bitmap::lockPixels(env, jbitmap);
+    if (!addr) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
 
-    pixelRef->lockPixels();
-    void* addr = pixelRef->pixels();
-    if (NULL == addr) {
-        pixelRef->unlockPixels();
-        pixelRef->unref();
-        return ANDROID_BITMAP_RESULT_ALLOCATION_FAILED;
-    }
-
     if (addrPtr) {
         *addrPtr = addr;
     }
@@ -86,26 +50,10 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkPixelRef* pixelRef = GraphicsJNI::refSkPixelRef(env, jbitmap);
-    if (!pixelRef) {
+    bool unlocked = android::bitmap::unlockPixels(env, jbitmap);
+    if (!unlocked) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
-
-    // notifyPixelsChanged() needs be called to apply writes to GL-backed
-    // bitmaps.  Note that this will slow down read-only accesses to the
-    // bitmaps, but the NDK methods are primarily intended to be used for
-    // writes.
-    pixelRef->notifyPixelsChanged();
-
-    pixelRef->unlockPixels();
-    // Awkward in that we need to double-unref as the call to get the SkPixelRef
-    // did a ref(), so we need to unref() for the local ref and for the previous
-    // AndroidBitmap_lockPixels(). However this keeps GraphicsJNI a bit safer
-    // if others start using it without knowing about android::Bitmap's "fun"
-    // ref counting mechanism(s).
-    pixelRef->unref();
-    pixelRef->unref();
-
     return ANDROID_BITMAP_RESULT_SUCCESS;
 }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
index 7f7249f0..b06b032 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
@@ -28,6 +28,7 @@
 import android.util.Log;
 
 import com.android.settingslib.R;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -35,6 +36,13 @@
 public class AppUtils {
     private static final String TAG = "AppUtils";
 
+    /**
+     * This should normally only be set in robolectric tests, to avoid getting a method not found
+     * exception when calling the isInstantApp method of the ApplicationInfo class, because
+     * robolectric does not yet have an implementation of it.
+     */
+    private static InstantAppDataProvider sInstantAppDataProvider = null;
+
     public static CharSequence getLaunchByDefaultSummary(ApplicationsState.AppEntry appEntry,
             IUsbManager usbManager, PackageManager pm, Context context) {
         String packageName = appEntry.info.packageName;
@@ -74,7 +82,11 @@
      * Returns a boolean indicating whether the given package should be considered an instant app
      */
     public static boolean isInstant(ApplicationInfo info) {
-        if (info.isInstantApp()) {
+        if (sInstantAppDataProvider != null) {
+            if (sInstantAppDataProvider.isInstantApp(info)) {
+                return true;
+            }
+        } else if (info.isInstantApp()) {
             return true;
         }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/instantapps/InstantAppDataProvider.java b/packages/SettingsLib/src/com/android/settingslib/applications/instantapps/InstantAppDataProvider.java
new file mode 100644
index 0000000..8b15715
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/instantapps/InstantAppDataProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.applications.instantapps;
+
+import android.content.pm.ApplicationInfo;
+
+/**
+ * This helps deal with the fact that robolectric does not yet have an implementation of the
+ * isInstantApp method of ApplicationInfo, so we get a method not found exception when running tests
+ * if we try to call it directly.
+ */
+public interface InstantAppDataProvider {
+    public boolean isInstantApp(ApplicationInfo info);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 3df7e66..50972c7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -223,7 +223,8 @@
         }
 
         final Context context = getContext();
-        int level = WifiManager.calculateSignalLevel(mAccessPoint.getRssi(), 5 /* levels */);
+        int level = WifiManager.calculateSignalLevel(
+                mAccessPoint.getRssi(), WifiManager.RSSI_LEVELS);
         int wifiBadge = mAccessPoint.getBadge();
         if (level != mLevel || wifiBadge != mWifiBadge) {
             mLevel = level;
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
index ddee89e..674ed5a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
@@ -19,7 +19,7 @@
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
 
-@ProvidesInterface(action = NavGesture.ACTION, version = NavBarButtonProvider.VERSION)
+@ProvidesInterface(action = NavGesture.ACTION, version = NavGesture.VERSION)
 public interface NavGesture extends Plugin {
 
     public static final String ACTION = "com.android.systemui.action.PLUGIN_NAV_GESTURE";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index 821e635..a87b50a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -116,19 +116,20 @@
     }
 
     private void notifyKeyguardChanged() {
-        mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+        // Copy the list to allow removal during callback.
+        new ArrayList<Callback>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
     }
 
     public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) {
         mKeyguardFadingAway = true;
         mKeyguardFadingAwayDelay = delay;
         mKeyguardFadingAwayDuration = fadeoutDuration;
-        mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+        notifyKeyguardChanged();
     }
 
     public void notifyKeyguardDoneFading() {
         mKeyguardFadingAway = false;
-        mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+        notifyKeyguardChanged();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 51d931e..bc3eec9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -39,6 +39,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.MathUtils;
+import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneConstants;
@@ -78,6 +79,7 @@
     private static final int EMERGENCY_FIRST_CONTROLLER = 100;
     private static final int EMERGENCY_VOICE_CONTROLLER = 200;
     private static final int EMERGENCY_NO_SUB = 300;
+    private static final int EMERGENCY_ASSUMED_VOICE_CONTROLLER = 400;
 
     private final Context mContext;
     private final TelephonyManager mPhone;
@@ -99,8 +101,7 @@
     final EthernetSignalController mEthernetSignalController;
 
     @VisibleForTesting
-    final Map<Integer, MobileSignalController> mMobileSignalControllers =
-            new HashMap<Integer, MobileSignalController>();
+    final SparseArray<MobileSignalController> mMobileSignalControllers = new SparseArray<>();
     // When no SIMs are around at setup, and one is added later, it seems to default to the first
     // SIM for most actions.  This may be null if there aren't any SIMs around.
     private MobileSignalController mDefaultSignalController;
@@ -232,7 +233,8 @@
     }
 
     private void registerListeners() {
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.registerListener();
         }
         if (mSubscriptionListener == null) {
@@ -261,7 +263,8 @@
 
     private void unregisterListeners() {
         mListening = false;
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.unregisterListener();
         }
         mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener);
@@ -305,7 +308,7 @@
             if (DEBUG) Log.e(TAG, "No data sim selected");
             return mDefaultSignalController;
         }
-        if (mMobileSignalControllers.containsKey(dataSubId)) {
+        if (mMobileSignalControllers.indexOfKey(dataSubId) >= 0) {
             return mMobileSignalControllers.get(dataSubId);
         }
         if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId);
@@ -326,8 +329,8 @@
         }
         int voiceSubId = mSubDefaults.getDefaultVoiceSubId();
         if (!SubscriptionManager.isValidSubscriptionId(voiceSubId)) {
-            for (MobileSignalController mobileSignalController :
-                                            mMobileSignalControllers.values()) {
+            for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
                 if (!mobileSignalController.getState().isEmergency) {
                     mEmergencySource = EMERGENCY_FIRST_CONTROLLER
                             + mobileSignalController.mSubscriptionInfo.getSubscriptionId();
@@ -336,11 +339,20 @@
                 }
             }
         }
-        if (mMobileSignalControllers.containsKey(voiceSubId)) {
+        if (mMobileSignalControllers.indexOfKey(voiceSubId) >= 0) {
             mEmergencySource = EMERGENCY_VOICE_CONTROLLER + voiceSubId;
             if (DEBUG) Log.d(TAG, "Getting emergency from " + voiceSubId);
             return mMobileSignalControllers.get(voiceSubId).getState().isEmergency;
         }
+        // If we have the wrong subId but there is only one sim anyway, assume it should be the
+        // default.
+        if (mMobileSignalControllers.size() == 1) {
+            mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER
+                    + mMobileSignalControllers.keyAt(0);
+            if (DEBUG) Log.d(TAG, "Getting assumed emergency from "
+                    + mMobileSignalControllers.keyAt(0));
+            return mMobileSignalControllers.valueAt(0).getState().isEmergency;
+        }
         if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId);
         mEmergencySource = EMERGENCY_NO_SUB + voiceSubId;
         // Something is wrong, better assume we can't make calls...
@@ -363,7 +375,8 @@
         cb.setNoSims(mHasNoSims);
         mWifiSignalController.notifyListeners(cb);
         mEthernetSignalController.notifyListeners(cb);
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.notifyListeners(cb);
         }
         mCallbackHandler.setListening(cb, true);
@@ -416,7 +429,8 @@
         } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
             // Notify every MobileSignalController so they can know whether they are the
             // data sim or not.
-            for (MobileSignalController controller : mMobileSignalControllers.values()) {
+            for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                 controller.handleBroadcast(intent);
             }
         } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
@@ -433,7 +447,7 @@
             int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
                     SubscriptionManager.INVALID_SUBSCRIPTION_ID);
             if (SubscriptionManager.isValidSubscriptionId(subId)) {
-                if (mMobileSignalControllers.containsKey(subId)) {
+                if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
                     mMobileSignalControllers.get(subId).handleBroadcast(intent);
                 } else {
                     // Can't find this subscription...  We must be out of date.
@@ -458,8 +472,9 @@
 
     @VisibleForTesting
     void handleConfigurationChanged() {
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
-            mobileSignalController.setConfiguration(mConfig);
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController controller = mMobileSignalControllers.valueAt(i);
+            controller.setConfiguration(mConfig);
         }
         refreshLocale();
     }
@@ -511,15 +526,20 @@
         });
         mCurrentSubscriptions = subscriptions;
 
-        HashMap<Integer, MobileSignalController> cachedControllers =
-                new HashMap<Integer, MobileSignalController>(mMobileSignalControllers);
+        SparseArray<MobileSignalController> cachedControllers =
+                new SparseArray<MobileSignalController>();
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            cachedControllers.put(mMobileSignalControllers.keyAt(i),
+                    mMobileSignalControllers.valueAt(i));
+        }
         mMobileSignalControllers.clear();
         final int num = subscriptions.size();
         for (int i = 0; i < num; i++) {
             int subId = subscriptions.get(i).getSubscriptionId();
             // If we have a copy of this controller already reuse it, otherwise make a new one.
-            if (cachedControllers.containsKey(subId)) {
-                mMobileSignalControllers.put(subId, cachedControllers.remove(subId));
+            if (cachedControllers.indexOfKey(subId) >= 0) {
+                mMobileSignalControllers.put(subId, cachedControllers.get(subId));
+                cachedControllers.remove(subId);
             } else {
                 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
                         mHasMobileDataFeature, mPhone, mCallbackHandler,
@@ -535,7 +555,8 @@
             }
         }
         if (mListening) {
-            for (Integer key : cachedControllers.keySet()) {
+            for (int i = 0; i < cachedControllers.size(); i++) {
+                int key = cachedControllers.keyAt(i);
                 if (cachedControllers.get(key) == mDefaultSignalController) {
                     mDefaultSignalController = null;
                 }
@@ -557,7 +578,8 @@
 
     private void handleSetUserSetupComplete(boolean userSetup) {
         mUserSetup = userSetup;
-        for (MobileSignalController controller : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController controller = mMobileSignalControllers.valueAt(i);
             controller.setUserSetupComplete(mUserSetup);
         }
     }
@@ -568,7 +590,7 @@
             return false;
         }
         for (SubscriptionInfo info : allSubscriptions) {
-            if (!mMobileSignalControllers.containsKey(info.getSubscriptionId())) {
+            if (mMobileSignalControllers.indexOfKey(info.getSubscriptionId()) < 0) {
                 return false;
             }
         }
@@ -580,7 +602,8 @@
                 Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
         if (airplaneMode != mAirplaneMode || force) {
             mAirplaneMode = airplaneMode;
-            for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+            for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
                 mobileSignalController.setAirplaneMode(mAirplaneMode);
             }
             notifyListeners();
@@ -601,7 +624,8 @@
      */
     private void notifyAllListeners() {
         notifyListeners();
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.notifyListeners();
         }
         mWifiSignalController.notifyListeners();
@@ -650,7 +674,8 @@
      */
     private void pushConnectivityToSignals() {
         // We want to update all the icons, all at once, for any condition change
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
         }
         mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
@@ -682,7 +707,8 @@
         pw.print("  mEmergencySource=");
         pw.println(emergencyToString(mEmergencySource));
 
-        for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
+        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.dump(pw);
         }
         mWifiSignalController.dump(pw);
@@ -694,6 +720,9 @@
 
     private static final String emergencyToString(int emergencySource) {
         if (emergencySource > EMERGENCY_NO_SUB) {
+            return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER)
+                    + ")";
+        } else if (emergencySource > EMERGENCY_NO_SUB) {
             return "NO_SUB(" + (emergencySource - EMERGENCY_NO_SUB) + ")";
         } else if (emergencySource > EMERGENCY_VOICE_CONTROLLER) {
             return "VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")";
@@ -724,7 +753,8 @@
             // Update what MobileSignalControllers, because they may change
             // to set the number of sim slots.
             updateMobileControllers();
-            for (MobileSignalController controller : mMobileSignalControllers.values()) {
+            for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                 controller.resetLastState();
             }
             mWifiSignalController.resetLastState();
@@ -747,7 +777,8 @@
                     connected.set(mWifiSignalController.mTransportType);
                 }
                 mWifiSignalController.updateConnectivity(connected, connected);
-                for (MobileSignalController controller : mMobileSignalControllers.values()) {
+                for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                    MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                     if (mDemoInetCondition) {
                         connected.set(controller.mTransportType);
                     }
@@ -820,8 +851,7 @@
                     mCallbackHandler.setSubs(subs);
                 }
                 // Hack to index linearly for easy use.
-                MobileSignalController controller = mMobileSignalControllers
-                        .values().toArray(new MobileSignalController[0])[slot];
+                MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
                 controller.getState().dataSim = datatype != null;
                 controller.getState().isDefault = datatype != null;
                 controller.getState().dataConnected = datatype != null;
@@ -875,7 +905,8 @@
             String carrierNetworkChange = args.getString("carriernetworkchange");
             if (carrierNetworkChange != null) {
                 boolean show = carrierNetworkChange.equals("show");
-                for (MobileSignalController controller : mMobileSignalControllers.values()) {
+                for (int i = 0; i < mMobileSignalControllers.size(); i++) {
+                    MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                     controller.setCarrierNetworkChangeMode(show);
                 }
             }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 2c0f9c9..1555856 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -94,6 +94,14 @@
     }
 
     @Test
+    public void testNoEmergencyOnlyWrongSubscription() {
+        setupDefaultSignal();
+        setDefaultSubId(42);
+        mNetworkController.recalculateEmergency();
+        verifyEmergencyOnly(false);
+    }
+
+    @Test
     public void testNoEmengencyNoSubscriptions() {
         setupDefaultSignal();
         setSubscriptions();
@@ -286,12 +294,12 @@
         for (int i = 0; i < testSubscriptions.length; i++) {
             if (i == indexToSkipController) {
                 // Make sure a controller was created despite us not adding one.
-                assertTrue(mNetworkController.mMobileSignalControllers.containsKey(
-                        testSubscriptions[i]));
+                assertTrue(mNetworkController.mMobileSignalControllers.indexOfKey(
+                        testSubscriptions[i]) >= 0);
             } else if (i == indexToSkipSubscription) {
                 // Make sure the controller that did exist was removed
-                assertFalse(mNetworkController.mMobileSignalControllers.containsKey(
-                        testSubscriptions[i]));
+                assertFalse(mNetworkController.mMobileSignalControllers.indexOfKey(
+                        testSubscriptions[i]) >= 0);
             } else {
                 // If a MobileSignalController is around it needs to not be unregistered.
                 Mockito.verify(mobileSignalControllers[i], Mockito.never())
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index dae5da3..0e767da 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3050,6 +3050,10 @@
             throw new IllegalArgumentException("null not allowed: pkg=" + pkg
                     + " id=" + id + " notification=" + notification);
         }
+
+        // The system can post notifications for any package, let us resolve that.
+        final int notificationUid = resolveNotificationUid(opPkg, callingUid, userId);
+
         // Fix the notification as best we can.
         try {
             final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
@@ -3069,13 +3073,13 @@
             channelId = (new Notification.TvExtender(notification)).getChannel();
         }
         final NotificationChannel channel =  mRankingHelper.getNotificationChannelWithFallback(pkg,
-                callingUid, channelId, false /* includeDeleted */);
+                notificationUid, channelId, false /* includeDeleted */);
         final StatusBarNotification n = new StatusBarNotification(
-                pkg, opPkg, id, tag, callingUid, callingPid, notification,
+                pkg, opPkg, id, tag, notificationUid, callingPid, notification,
                 user, null, System.currentTimeMillis());
         final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
 
-        if (!checkDisqualifyingFeatures(userId, callingUid, id,tag, r)) {
+        if (!checkDisqualifyingFeatures(userId, notificationUid, id,tag, r)) {
             return;
         }
 
@@ -3101,6 +3105,19 @@
         idOut[0] = id;
     }
 
+    private int resolveNotificationUid(String opPackageName, int callingUid, int userId) {
+        // The system can post notifications on behalf of any package it wants
+        if (isCallerSystem() && opPackageName != null && !"android".equals(opPackageName)) {
+            try {
+                return getContext().getPackageManager()
+                        .getPackageUidAsUser(opPackageName, userId);
+            } catch (NameNotFoundException e) {
+                /* ignore */
+            }
+        }
+        return callingUid;
+    }
+
     /**
      * Checks if a notification can be posted. checks rate limiter, snooze helper, and blocking.
      *
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index bbd227e..aac04da 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -314,7 +314,8 @@
         optimizer.performDexOpt(pkg, libraryDependencies,
                 null /* ISAs */, false /* checkProfiles */,
                 getCompilerFilterForReason(compilationReason),
-                null /* CompilerStats.PackageStats */);
+                null /* CompilerStats.PackageStats */,
+                mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName));
 
         return commands;
     }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index b589057..d9ea728 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -104,7 +104,7 @@
      */
     int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries,
             String[] instructionSets, boolean checkProfiles, String targetCompilationFilter,
-            CompilerStats.PackageStats packageStats) {
+            CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps) {
         if (!canOptimizePackage(pkg)) {
             return DEX_OPT_SKIPPED;
         }
@@ -119,7 +119,7 @@
             }
             try {
                 return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles,
-                        targetCompilationFilter, packageStats);
+                        targetCompilationFilter, packageStats, isUsedByOtherApps);
             } finally {
                 if (useLock) {
                     mDexoptWakeLock.release();
@@ -135,7 +135,8 @@
     @GuardedBy("mInstallLock")
     private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries,
             String[] targetInstructionSets, boolean checkForProfileUpdates,
-            String targetCompilerFilter, CompilerStats.PackageStats packageStats) {
+            String targetCompilerFilter, CompilerStats.PackageStats packageStats,
+            boolean isUsedByOtherApps) {
         final String[] instructionSets = targetInstructionSets != null ?
                 targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
         final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
@@ -143,7 +144,7 @@
         final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
 
         final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo,
-                targetCompilerFilter, isUsedByOtherApps(pkg));
+                targetCompilerFilter, isUsedByOtherApps);
         final boolean profileUpdated = checkForProfileUpdates &&
                 isProfileUpdated(pkg, sharedGid, compilerFilter);
 
@@ -477,40 +478,6 @@
         mSystemReady = true;
     }
 
-    /**
-     * Returns true if the profiling data collected for the given app indicate
-     * that the apps's APK has been loaded by another app.
-     * Note that this returns false for all forward-locked apps and apps without
-     * any collected profiling data.
-     */
-    public static boolean isUsedByOtherApps(PackageParser.Package pkg) {
-        if (pkg.isForwardLocked()) {
-            // Skip the check for forward locked packages since they don't share their code.
-            return false;
-        }
-
-        for (String apkPath : pkg.getAllCodePathsExcludingResourceOnly()) {
-            try {
-                apkPath = PackageManagerServiceUtils.realpath(new File(apkPath));
-            } catch (IOException e) {
-                // Log an error but continue without it.
-                Slog.w(TAG, "Failed to get canonical path", e);
-                continue;
-            }
-            String useMarker = apkPath.replace('/', '@');
-            final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
-            for (int i = 0; i < currentUserIds.length; i++) {
-                File profileDir =
-                        Environment.getDataProfilesDeForeignDexDirectory(currentUserIds[i]);
-                File foreignUseMark = new File(profileDir, useMarker);
-                if (foreignUseMark.exists()) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     private String printDexoptFlags(int flags) {
         ArrayList<String> flagsList = new ArrayList<>();
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9ce8cd7..f77609f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8441,11 +8441,13 @@
                 pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets,
                         false /* checkProfiles */,
                         getCompilerFilterForReason(REASON_NON_SYSTEM_LIBRARY),
-                        getOrCreateCompilerPackageStats(depPackage));
+                        getOrCreateCompilerPackageStats(depPackage),
+                        mDexManager.isUsedByOtherApps(p.packageName));
             }
         }
         return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, checkProfiles,
-                targetCompilerFilter, getOrCreateCompilerPackageStats(p));
+                targetCompilerFilter, getOrCreateCompilerPackageStats(p),
+                mDexManager.isUsedByOtherApps(p.packageName));
     }
 
     // Performs dexopt on the used secondary dex files belonging to the given package.
@@ -16656,13 +16658,19 @@
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
 
-//        // Ephemeral apps must have target SDK >= O.
-//        // TODO: Update conditional and error message when O gets locked down
-//        if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
-//            res.setError(PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID,
-//                    "Ephemeral apps must have target SDK version of at least O");
-//            return;
-//        }
+        // Instant apps must have target SDK >= O and have targetSanboxVersion >= 2
+        if (instantApp && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
+            Slog.w(TAG, "Instant app package " + pkg.packageName
+                    + " does not target O, this will be a fatal error.");
+            // STOPSHIP: Make this a fatal error
+            pkg.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
+        }
+        if (instantApp && pkg.applicationInfo.targetSandboxVersion != 2) {
+            Slog.w(TAG, "Instant app package " + pkg.packageName
+                    + " does not target targetSandboxVersion 2, this will be a fatal error.");
+            // STOPSHIP: Make this a fatal error
+            pkg.applicationInfo.targetSandboxVersion = 2;
+        }
 
         if (pkg.applicationInfo.isStaticSharedLibrary()) {
             // Static shared libraries have synthetic package names
@@ -16959,7 +16967,8 @@
             mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
                     null /* instructionSets */, false /* checkProfiles */,
                     getCompilerFilterForReason(REASON_INSTALL),
-                    getOrCreateCompilerPackageStats(pkg));
+                    getOrCreateCompilerPackageStats(pkg),
+                    mDexManager.isUsedByOtherApps(pkg.packageName));
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             // Notify BackgroundDexOptJobService that the package has been changed.
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 45887e1..9feee8c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -133,7 +133,8 @@
                 sortTemp, packageManagerService);
 
         // Give priority to apps used by other apps.
-        applyPackageFilter((pkg) -> PackageDexOptimizer.isUsedByOtherApps(pkg), result,
+        applyPackageFilter((pkg) ->
+                packageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), result,
                 remainingPkgs, sortTemp, packageManagerService);
 
         // Filter out packages that aren't recently used, add all remaining apps.
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 00f3711..01124e2 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -359,6 +359,23 @@
     }
 
     /**
+     * Return true if the profiling data collected for the given app indicate
+     * that the apps's APK has been loaded by another app.
+     * Note that this returns false for all apps without any collected profiling data.
+    */
+    public boolean isUsedByOtherApps(String packageName) {
+        PackageUseInfo useInfo = getPackageUseInfo(packageName);
+        if (useInfo == null) {
+            // No use info, means the package was not used or it was used but not by other apps.
+            // Note that right now we might prune packages which are not used by other apps.
+            // TODO(calin): maybe we should not (prune) so we can have an accurate view when we try
+            // to access the package use.
+            return false;
+        }
+        return useInfo.isUsedByOtherApps();
+    }
+
+    /**
      * Retrieves the package which owns the given dexPath.
      */
     private DexSearchResult getDexPackage(
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 6d572d7..4806068 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1532,6 +1532,13 @@
             return changed;
         }
 
+        // Next up we will notify the client that it's visibility has changed.
+        // We need to prevent it from destroying child surfaces until
+        // the animation has finished.
+        if (!visible && isVisibleNow()) {
+            mWinAnimator.detachChildren();
+        }
+
         if (visible != isVisibleNow()) {
             if (!runningAppAnimation) {
                 final AccessibilityController accessibilityController =