Merge "Add logs, reorder bugreport."
diff --git a/api/current.txt b/api/current.txt
index 9df1764..a4c933f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24096,6 +24096,7 @@
     field public static final java.lang.String COLUMN_AUTHOR = "author";
     field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
     field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
@@ -24238,11 +24239,13 @@
     field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
     field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
+    field public static final java.lang.String ACTION_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
     field public static final java.lang.String ACTION_VIEW_RECORDING_SCHEDULES = "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
     field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_PROGRAM_ID = "android.media.tv.extra.PROGRAM_ID";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
diff --git a/api/system-current.txt b/api/system-current.txt
index eed1718..a806153 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -25885,6 +25885,7 @@
     field public static final java.lang.String COLUMN_AUTHOR = "author";
     field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
     field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
@@ -26108,11 +26109,13 @@
     field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
     field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
+    field public static final java.lang.String ACTION_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
     field public static final java.lang.String ACTION_VIEW_RECORDING_SCHEDULES = "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
     field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_PROGRAM_ID = "android.media.tv.extra.PROGRAM_ID";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
diff --git a/api/test-current.txt b/api/test-current.txt
index 114060d..b47331b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -24189,6 +24189,7 @@
     field public static final java.lang.String COLUMN_AUTHOR = "author";
     field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
     field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
@@ -24331,11 +24332,13 @@
     field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
     field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
+    field public static final java.lang.String ACTION_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
     field public static final java.lang.String ACTION_VIEW_RECORDING_SCHEDULES = "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
     field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_PROGRAM_ID = "android.media.tv.extra.PROGRAM_ID";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 7015381..51b2d3d 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -553,8 +553,12 @@
                     sessionParams.abiOverride = checkAbiArgument(nextOptionData());
                     break;
                 case "--ephemeral":
+                case "--instant":
                     sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
                     break;
+                case "--full":
+                    sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
+                    break;
                 case "--user":
                     params.userId = UserHandle.parseUserArg(nextOptionData());
                     break;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 333e412..1652299 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1687,7 +1687,7 @@
     public int installExistingPackageAsUser(String packageName, int userId)
             throws NameNotFoundException {
         try {
-            int res = mPM.installExistingPackageAsUser(packageName, userId,
+            int res = mPM.installExistingPackageAsUser(packageName, userId, 0 /*installFlags*/,
                     PackageManager.INSTALL_REASON_UNKNOWN);
             if (res == INSTALL_FAILED_INVALID_URI) {
                 throw new NameNotFoundException("Package " + packageName + " doesn't exist");
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 45a46b3..812daf8 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3684,7 +3684,8 @@
                         mContext, backgroundColor);
                 mSecondaryTextColor = NotificationColorUtil.resolveSecondaryColor(
                         mContext, backgroundColor);
-                mActionBarColor = NotificationColorUtil.resolveActionBarColor(backgroundColor);
+                mActionBarColor = NotificationColorUtil.resolveActionBarColor(mContext,
+                        backgroundColor);
             }
         }
 
@@ -4166,12 +4167,21 @@
                     mN.extras.putCharSequence(EXTRA_SUB_TEXT, newSummary);
                 }
             }
+            Boolean colorized = (Boolean) mN.extras.get(EXTRA_COLORIZED);
+            mN.extras.putBoolean(EXTRA_COLORIZED, false);
+
             RemoteViews header = makeNotificationHeader();
+
             if (summary != null) {
                 mN.extras.putCharSequence(EXTRA_SUB_TEXT, summary);
             } else {
                 mN.extras.remove(EXTRA_SUB_TEXT);
             }
+            if (colorized != null) {
+                mN.extras.putBoolean(EXTRA_COLORIZED, colorized);
+            } else {
+                mN.extras.remove(EXTRA_COLORIZED);
+            }
             mN.color = color;
             return header;
         }
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index e6cae69..56609eb 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -284,8 +284,6 @@
 
     /** Whether or not the intent filter is visible to ephemeral apps. */
     private boolean mVisibleToEphemeral;
-    /** Whether or not the intent filter is part of an ephemeral app. */
-    private boolean mEphemeral;
     // These functions are the start of more optimized code for managing
     // the string sets...  not yet implemented.
 
@@ -656,19 +654,10 @@
         mVisibleToEphemeral = visibleToEmphemeral;
     }
     /** @hide */
-    public boolean isVisibleToEphemeral() {
+    public boolean isVisibleToInstantApp() {
         return mVisibleToEphemeral;
     }
 
-    /** @hide */
-    public void setEphemeral(boolean ephemeral) {
-        mEphemeral = ephemeral;
-    }
-    /** @hide */
-    public boolean isEphemeral() {
-        return mEphemeral;
-    }
-
     /**
      * Add a new Intent action to match against.  If any actions are included
      * in the filter, then an Intent's action must be one of those values for
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1fa4181..9737b11 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -498,11 +498,12 @@
     public static final int PRIVATE_FLAG_DIRECT_BOOT_AWARE = 1 << 6;
 
     /**
-     * Value for {@link #flags}: {@code true} if the application is blocked via restrictions
-     * and for most purposes is considered as not installed.
-     * {@hide}
+     * Value for {@link #privateFlags}: {@code true} if the application is installed
+     * as instant app.
+     *
+     * @hide
      */
-    public static final int PRIVATE_FLAG_EPHEMERAL = 1 << 7;
+    public static final int PRIVATE_FLAG_INSTANT = 1 << 7;
 
     /**
      * When set, at least one component inside this application is direct boot
@@ -681,7 +682,21 @@
      *
      * {@hide}
      */
-    public String seinfo = "default";
+    public String seInfo = "default";
+
+    /**
+     * The seinfo tag generated per-user. This value may change based upon the
+     * user's configuration. For example, when an instant app is installed for
+     * a user. It is an error if this field is ever {@code null} when trying to
+     * start a new process.
+     * <p>NOTE: We need to separate this out because we modify per-user values
+     * multiple times. This needs to be refactored since we're performing more
+     * work than necessary and these values should only be set once. When that
+     * happens, we can merge the per-user value with the seInfo state above.
+     *
+     * {@hide}
+     */
+    public String seInfoUser;
 
     /**
      * Paths to all shared libraries this application is linked against.  This
@@ -1009,8 +1024,9 @@
         if (resourceDirs != null) {
             pw.println(prefix + "resourceDirs=" + Arrays.toString(resourceDirs));
         }
-        if ((flags&DUMP_FLAG_DETAILS) != 0 && seinfo != null) {
-            pw.println(prefix + "seinfo=" + seinfo);
+        if ((flags&DUMP_FLAG_DETAILS) != 0 && seInfo != null) {
+            pw.println(prefix + "seinfo=" + seInfo);
+            pw.println(prefix + "seinfoUser=" + seInfoUser);
         }
         pw.println(prefix + "dataDir=" + dataDir);
         if ((flags&DUMP_FLAG_DETAILS) != 0) {
@@ -1120,7 +1136,8 @@
         primaryCpuAbi = orig.primaryCpuAbi;
         secondaryCpuAbi = orig.secondaryCpuAbi;
         resourceDirs = orig.resourceDirs;
-        seinfo = orig.seinfo;
+        seInfo = orig.seInfo;
+        seInfoUser = orig.seInfoUser;
         sharedLibraryFiles = orig.sharedLibraryFiles;
         dataDir = orig.dataDir;
         deviceEncryptedDataDir = deviceProtectedDataDir = orig.deviceProtectedDataDir;
@@ -1181,7 +1198,8 @@
         dest.writeString(primaryCpuAbi);
         dest.writeString(secondaryCpuAbi);
         dest.writeStringArray(resourceDirs);
-        dest.writeString(seinfo);
+        dest.writeString(seInfo);
+        dest.writeString(seInfoUser);
         dest.writeStringArray(sharedLibraryFiles);
         dest.writeString(dataDir);
         dest.writeString(deviceProtectedDataDir);
@@ -1242,7 +1260,8 @@
         primaryCpuAbi = source.readString();
         secondaryCpuAbi = source.readString();
         resourceDirs = source.readStringArray();
-        seinfo = source.readString();
+        seInfo = source.readString();
+        seInfoUser = source.readString();
         sharedLibraryFiles = source.readStringArray();
         dataDir = source.readString();
         deviceEncryptedDataDir = deviceProtectedDataDir = source.readString();
@@ -1330,7 +1349,6 @@
         } else {
             dataDir = credentialProtectedDataDir;
         }
-        // TODO: modify per-user ephemerality
     }
 
     /**
@@ -1415,7 +1433,7 @@
      * @hide
      */
     public boolean isInstantApp() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_EPHEMERAL) != 0;
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
     }
 
     /**
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 9d36a73..ffb777d 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -553,7 +553,8 @@
     boolean setInstallLocation(int loc);
     int getInstallLocation();
 
-    int installExistingPackageAsUser(String packageName, int userId, int installReason);
+    int installExistingPackageAsUser(String packageName, int userId, int installFlags,
+            int installReason);
 
     void verifyPendingInstall(int id, int verificationCode);
     void extendVerificationTimeout(int id, int verificationCodeAtTimeout, long millisecondsToDelay);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 4de967c..278a6d0 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1096,9 +1096,11 @@
         @SystemApi
         public void setInstallAsInstantApp(boolean isInstantApp) {
             if (isInstantApp) {
-                installFlags |= PackageManager.INSTALL_EPHEMERAL;
+                installFlags |= PackageManager.INSTALL_INSTANT_APP;
+                installFlags &= ~PackageManager.INSTALL_FULL_APP;
             } else {
-                installFlags &= ~PackageManager.INSTALL_EPHEMERAL;
+                installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
+                installFlags |= PackageManager.INSTALL_FULL_APP;
             }
         }
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 308153d..5733982 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -452,17 +452,17 @@
 
     /**
      * Internal {@link PackageInfo} flag: include components that are part of an
-     * ephemeral app. By default, ephemeral components are not matched.
+     * instant app. By default, instant app components are not matched.
      * @hide
      */
-    public static final int MATCH_EPHEMERAL = 0x00800000;
+    public static final int MATCH_INSTANT = 0x00800000;
 
     /**
      * Internal {@link PackageInfo} flag: include only components that are exposed to
      * ephemeral apps.
      * @hide
      */
-    public static final int MATCH_VISIBLE_TO_EPHEMERAL_ONLY = 0x01000000;
+    public static final int MATCH_VISIBLE_TO_INSTANT_APP_ONLY = 0x01000000;
 
     /**
      * Internal flag used to indicate that a system component has done their
@@ -613,7 +613,7 @@
             INSTALL_GRANT_RUNTIME_PERMISSIONS,
             INSTALL_FORCE_VOLUME_UUID,
             INSTALL_FORCE_PERMISSION_PROMPT,
-            INSTALL_EPHEMERAL,
+            INSTALL_INSTANT_APP,
             INSTALL_DONT_KILL_APP,
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -714,7 +714,16 @@
      *
      * @hide
      */
-    public static final int INSTALL_EPHEMERAL = 0x00000800;
+    public static final int INSTALL_INSTANT_APP = 0x00000800;
+
+    /**
+     * Flag parameter for {@link #installPackage} to indicate that this package is
+     * to be installed as a heavy weight app. This is fundamentally the opposite of
+     * {@link #INSTALL_INSTANT_APP}.
+     *
+     * @hide
+     */
+    public static final int INSTALL_FULL_APP = 0x00004000;
 
     /**
      * Flag parameter for {@link #installPackage} to indicate that this package contains
@@ -1185,12 +1194,12 @@
     public static final int INSTALL_FAILED_ABORTED = -115;
 
     /**
-     * Installation failed return code: ephemeral app installs are incompatible with some
+     * Installation failed return code: instant app installs are incompatible with some
      * other installation flags supplied for the operation; or other circumstances such
-     * as trying to upgrade a system app via an ephemeral install.
+     * as trying to upgrade a system app via an instant app install.
      * @hide
      */
-    public static final int INSTALL_FAILED_EPHEMERAL_INVALID = -116;
+    public static final int INSTALL_FAILED_INSTANT_APP_INVALID = -116;
 
     /** @hide */
     @IntDef(flag = true, value = {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 7a9aaaf..98e71a0 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -720,6 +720,8 @@
     public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
     public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
     public final static int PARSE_ENFORCE_CODE = 1<<10;
+    /** @deprecated remove when fixing b/34761192 */
+    @Deprecated
     public final static int PARSE_IS_EPHEMERAL = 1<<11;
     public final static int PARSE_FORCE_SDK = 1<<12;
 
@@ -2012,10 +2014,6 @@
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
         }
 
-        if ((flags & PARSE_IS_EPHEMERAL) != 0) {
-            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_EPHEMERAL;
-        }
-
         if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
         }
@@ -4149,11 +4147,8 @@
                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
         }
 
-        final boolean hasVisibleToEphemeral =
-                sa.hasValue(R.styleable.AndroidManifestActivity_visibleToInstantApps);
-        final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
-        final boolean visibleToEphemeral = isEphemeral
-                || sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
+        final boolean visibleToEphemeral =
+                sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
         if (visibleToEphemeral) {
             a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
         }
@@ -4188,8 +4183,6 @@
                         intent, outError)) {
                     return null;
                 }
-                intent.setEphemeral(isEphemeral);
-                intent.setVisibleToEphemeral(visibleToEphemeral || isWebBrowsableIntent(intent));
                 if (intent.countActions() == 0) {
                     Slog.w(TAG, "No actions in intent filter at "
                             + mArchiveSourcePath + " "
@@ -4198,7 +4191,8 @@
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
-                if (!hasVisibleToEphemeral && intent.isVisibleToEphemeral()) {
+                intent.setVisibleToEphemeral(visibleToEphemeral || isWebBrowsableIntent(intent));
+                if (intent.isVisibleToInstantApp()) {
                     a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                 }
             } else if (!receiver && parser.getName().equals("preferred")) {
@@ -4207,8 +4201,6 @@
                         intent, outError)) {
                     return null;
                 }
-                intent.setEphemeral(isEphemeral);
-                intent.setVisibleToEphemeral(visibleToEphemeral || isWebBrowsableIntent(intent));
                 if (intent.countActions() == 0) {
                     Slog.w(TAG, "No actions in preferred at "
                             + mArchiveSourcePath + " "
@@ -4220,7 +4212,8 @@
                     owner.preferredActivityFilters.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
-                if (!hasVisibleToEphemeral && intent.isVisibleToEphemeral()) {
+                intent.setVisibleToEphemeral(visibleToEphemeral || isWebBrowsableIntent(intent));
+                if (intent.isVisibleToInstantApp()) {
                     a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                 }
             } else if (parser.getName().equals("meta-data")) {
@@ -4472,9 +4465,8 @@
         }
 
         // TODO add visibleToInstantApps attribute to activity alias
-        final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
-        final boolean visibleToEphemeral = isEphemeral
-                || ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0);
+        final boolean visibleToEphemeral =
+                ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0);
 
         sa.recycle();
 
@@ -4502,13 +4494,12 @@
                             + mArchiveSourcePath + " "
                             + parser.getPositionDescription());
                 } else {
-                    intent.setEphemeral(isEphemeral);
-                    intent.setVisibleToEphemeral(visibleToEphemeral
-                            || isWebBrowsableIntent(intent));
+                    intent.setVisibleToEphemeral(
+                            visibleToEphemeral || isWebBrowsableIntent(intent));
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
-                if (intent.isVisibleToEphemeral()) {
+                if (intent.isVisibleToInstantApp()) {
                     a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                 }
             } else if (parser.getName().equals("meta-data")) {
@@ -4649,11 +4640,8 @@
                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
         }
 
-        final boolean hasVisibleToEphemeral =
-                sa.hasValue(R.styleable.AndroidManifestProvider_visibleToInstantApps);
-        final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
-        final boolean visibleToEphemeral = isEphemeral
-                || sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
+        final boolean visibleToEphemeral =
+                sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
         if (visibleToEphemeral) {
             p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
         }
@@ -4681,7 +4669,7 @@
         p.info.authority = cpname.intern();
 
         if (!parseProviderTags(
-                res, parser, isEphemeral, hasVisibleToEphemeral, visibleToEphemeral, p, outError)) {
+                res, parser, visibleToEphemeral, p, outError)) {
             return null;
         }
 
@@ -4689,8 +4677,7 @@
     }
 
     private boolean parseProviderTags(Resources res, XmlResourceParser parser,
-            boolean isEphemeral, boolean hasVisibleToEphemeral, boolean visibleToEphemeral,
-            Provider outInfo, String[] outError)
+            boolean visibleToEphemeral, Provider outInfo, String[] outError)
                     throws XmlPullParserException, IOException {
         int outerDepth = parser.getDepth();
         int type;
@@ -4707,11 +4694,10 @@
                         intent, outError)) {
                     return false;
                 }
-                intent.setEphemeral(isEphemeral);
-                intent.setVisibleToEphemeral(visibleToEphemeral || isWebBrowsableIntent(intent));
                 outInfo.intents.add(intent);
                 // adjust provider flags when we implicitly expose it via a browsable filter
-                if (!hasVisibleToEphemeral && intent.isVisibleToEphemeral()) {
+                intent.setVisibleToEphemeral(visibleToEphemeral || isWebBrowsableIntent(intent));
+                if (intent.isVisibleToInstantApp()) {
                     outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                 }
 
@@ -4963,11 +4949,8 @@
                     ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
         }
 
-        final boolean hasVisibleToEphemeral =
-                sa.hasValue(R.styleable.AndroidManifestService_visibleToInstantApps);
-        final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
-        final boolean visibleToEphemeral = isEphemeral
-                || sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
+        final boolean visibleToEphemeral =
+                sa.getBoolean(R.styleable.AndroidManifestService_visibleToInstantApps, false);
         if (visibleToEphemeral) {
             s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
         }
@@ -4999,10 +4982,9 @@
                         intent, outError)) {
                     return null;
                 }
-                intent.setEphemeral(isEphemeral);
-                intent.setVisibleToEphemeral(visibleToEphemeral || isWebBrowsableIntent(intent));
                 // adjust activity flags when we implicitly expose it via a browsable filter
-                if (!hasVisibleToEphemeral && intent.isVisibleToEphemeral()) {
+                intent.setVisibleToEphemeral(visibleToEphemeral || isWebBrowsableIntent(intent));
+                if (intent.isVisibleToInstantApp()) {
                     s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                 }
                 s.intents.add(intent);
@@ -6482,6 +6464,9 @@
         if (state.stopped) {
             return true;
         }
+        if (state.instantApp != p.applicationInfo.isInstantApp()) {
+            return true;
+        }
         if ((flags & PackageManager.GET_META_DATA) != 0
                 && (metaData != null || p.mAppMetaData != null)) {
             return true;
@@ -6517,6 +6502,11 @@
         } else {
             ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
         }
+        if (state.instantApp) {
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
+        } else {
+            ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
+        }
         if (state.hidden) {
             ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
         } else {
@@ -6537,6 +6527,7 @@
         if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
             ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
         }
+        ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
     }
 
     public static ApplicationInfo generateApplicationInfo(Package p, int flags,
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index e19aa99..24f1164 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -43,6 +43,7 @@
     public boolean hidden; // Is the app restricted by owner / admin
     public boolean suspended;
     public boolean blockUninstall;
+    public boolean instantApp;
     public int enabled;
     public String lastDisableAppCaller;
     public int domainVerificationStatus;
@@ -71,6 +72,7 @@
         hidden = o.hidden;
         suspended = o.suspended;
         blockUninstall = o.blockUninstall;
+        instantApp = o.instantApp;
         enabled = o.enabled;
         lastDisableAppCaller = o.lastDisableAppCaller;
         domainVerificationStatus = o.domainVerificationStatus;
@@ -188,6 +190,9 @@
         if (blockUninstall != oldState.blockUninstall) {
             return false;
         }
+        if (instantApp != oldState.instantApp) {
+            return false;
+        }
         if (enabled != oldState.enabled) {
             return false;
         }
diff --git a/core/java/android/content/pm/SELinuxUtil.java b/core/java/android/content/pm/SELinuxUtil.java
new file mode 100644
index 0000000..871f672
--- /dev/null
+++ b/core/java/android/content/pm/SELinuxUtil.java
@@ -0,0 +1,43 @@
+/*
+ * 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 android.content.pm;
+
+import com.android.internal.util.ArrayUtils;
+
+/**
+ * Utility methods that need to be used in application space.
+ * @hide
+ */
+public final class SELinuxUtil {
+
+    /** Append to existing seinfo label for instant apps @hide */
+    private static final String INSTANT_APP_STR = ":ephemeralapp";
+
+    /** Append to existing seinfo when modifications are complete @hide */
+    private static final String COMPLETE_TAG = "complete";
+    private static final String COMPLETE_STR = ":" + COMPLETE_TAG;
+
+    /** @hide */
+    public static String assignSeinfoUser(PackageUserState userState) {
+        String seInfo = "";
+        if (userState.instantApp)
+            seInfo += INSTANT_APP_STR;
+        seInfo += COMPLETE_STR;
+        return seInfo;
+    }
+
+}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 7cdb3ce..39f4d42 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -311,11 +311,6 @@
     }
 
     /** {@hide} */
-    public static File getDataAppEphemeralDirectory(String volumeUuid) {
-        return new File(getDataDirectory(volumeUuid), "app-ephemeral");
-    }
-
-    /** {@hide} */
     public static File getDataUserCeDirectory(String volumeUuid) {
         return new File(getDataDirectory(volumeUuid), "user");
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2dfba28..b554e2d 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4128,20 +4128,20 @@
         }
 
         /**
-         * System settings which can be accessed by ephemeral apps.
+         * System settings which can be accessed by instant apps.
          * @hide
          */
-        public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>();
+        public static final Set<String> INSTANT_APP_SETTINGS = new ArraySet<>();
         static {
-            EPHEMERAL_SETTINGS.add(TEXT_AUTO_REPLACE);
-            EPHEMERAL_SETTINGS.add(TEXT_AUTO_CAPS);
-            EPHEMERAL_SETTINGS.add(TEXT_AUTO_PUNCTUATE);
-            EPHEMERAL_SETTINGS.add(TEXT_SHOW_PASSWORD);
-            EPHEMERAL_SETTINGS.add(DATE_FORMAT);
-            EPHEMERAL_SETTINGS.add(FONT_SCALE);
-            EPHEMERAL_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED);
-            EPHEMERAL_SETTINGS.add(TIME_12_24);
-            EPHEMERAL_SETTINGS.add(SOUND_EFFECTS_ENABLED);
+            INSTANT_APP_SETTINGS.add(TEXT_AUTO_REPLACE);
+            INSTANT_APP_SETTINGS.add(TEXT_AUTO_CAPS);
+            INSTANT_APP_SETTINGS.add(TEXT_AUTO_PUNCTUATE);
+            INSTANT_APP_SETTINGS.add(TEXT_SHOW_PASSWORD);
+            INSTANT_APP_SETTINGS.add(DATE_FORMAT);
+            INSTANT_APP_SETTINGS.add(FONT_SCALE);
+            INSTANT_APP_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED);
+            INSTANT_APP_SETTINGS.add(TIME_12_24);
+            INSTANT_APP_SETTINGS.add(SOUND_EFFECTS_ENABLED);
         }
 
         /**
@@ -6988,17 +6988,17 @@
         }
 
         /**
-         * Secure settings which can be accessed by ephemeral apps.
+         * Secure settings which can be accessed by instant apps.
          * @hide
          */
-        public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>();
+        public static final Set<String> INSTANT_APP_SETTINGS = new ArraySet<>();
         static {
-            EPHEMERAL_SETTINGS.add(ENABLED_ACCESSIBILITY_SERVICES);
-            EPHEMERAL_SETTINGS.add(ACCESSIBILITY_SPEAK_PASSWORD);
-            EPHEMERAL_SETTINGS.add(ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
+            INSTANT_APP_SETTINGS.add(ENABLED_ACCESSIBILITY_SERVICES);
+            INSTANT_APP_SETTINGS.add(ACCESSIBILITY_SPEAK_PASSWORD);
+            INSTANT_APP_SETTINGS.add(ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
 
-            EPHEMERAL_SETTINGS.add(DEFAULT_INPUT_METHOD);
-            EPHEMERAL_SETTINGS.add(ENABLED_INPUT_METHODS);
+            INSTANT_APP_SETTINGS.add(DEFAULT_INPUT_METHOD);
+            INSTANT_APP_SETTINGS.add(ENABLED_INPUT_METHODS);
         }
 
         /**
@@ -10136,16 +10136,16 @@
         public static final String CELL_ON = "cell_on";
 
         /**
-         * Global settings which can be accessed by ephemeral apps.
+         * Global settings which can be accessed by instant apps.
          * @hide
          */
-        public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>();
+        public static final Set<String> INSTANT_APP_SETTINGS = new ArraySet<>();
         static {
-            EPHEMERAL_SETTINGS.add(WAIT_FOR_DEBUGGER);
-            EPHEMERAL_SETTINGS.add(DEVICE_PROVISIONED);
-            EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES);
-            EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RTL);
-            EPHEMERAL_SETTINGS.add(EPHEMERAL_COOKIE_MAX_SIZE_BYTES);
+            INSTANT_APP_SETTINGS.add(WAIT_FOR_DEBUGGER);
+            INSTANT_APP_SETTINGS.add(DEVICE_PROVISIONED);
+            INSTANT_APP_SETTINGS.add(DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES);
+            INSTANT_APP_SETTINGS.add(DEVELOPMENT_FORCE_RTL);
+            INSTANT_APP_SETTINGS.add(EPHEMERAL_COOKIE_MAX_SIZE_BYTES);
         }
 
         /**
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index eec3cb0..e088717 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -534,7 +534,7 @@
         final int prefer;
         final boolean checkBoth;
         boolean ephemeral = false;
-        if ((installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
+        if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
             prefer = RECOMMEND_INSTALL_INTERNAL;
             ephemeral = true;
             checkBoth = false;
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index b4890b7..44b21b4 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -456,7 +456,10 @@
         }
     }
 
-    public static int resolveActionBarColor(int backgroundColor) {
+    public static int resolveActionBarColor(Context context, int backgroundColor) {
+        if (backgroundColor == Notification.COLOR_DEFAULT) {
+            return context.getColor(com.android.internal.R.color.notification_action_list);
+        }
         boolean useDark = shouldUseDark(backgroundColor);
         final double[] result = ColorUtilsFromCompat.getTempDouble3Array();
         ColorUtilsFromCompat.colorToLAB(backgroundColor, result);
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 00e8c05..ff90160 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -98,6 +98,8 @@
                 mUpdateTexImage = false;
                 doUpdateTexImage();
             }
+            GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
+            static_cast<GlLayer*>(mLayer)->setRenderTarget(renderTarget);
         }
         if (mTransform) {
             mLayer->getTransform().load(*mTransform);
@@ -140,12 +142,8 @@
         }
         #endif
         mSurfaceTexture->getTransformMatrix(transform);
-        GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
 
-        LOG_ALWAYS_FATAL_IF(renderTarget != GL_TEXTURE_2D && renderTarget != GL_TEXTURE_EXTERNAL_OES,
-                "doUpdateTexImage target %x, 2d %x, EXT %x",
-                renderTarget, GL_TEXTURE_2D, GL_TEXTURE_EXTERNAL_OES);
-        updateLayer(forceFilter, renderTarget, transform);
+        updateLayer(forceFilter, transform);
     }
 }
 
@@ -155,28 +153,17 @@
                         mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
 
     static const mat4 identityMatrix;
-    updateLayer(false, GL_NONE, identityMatrix.data);
+    updateLayer(false, identityMatrix.data);
 
     VkLayer* vkLayer = static_cast<VkLayer*>(mLayer);
     vkLayer->updateTexture();
 }
 
-void DeferredLayerUpdater::updateLayer(bool forceFilter, GLenum renderTarget,
-        const float* textureTransform) {
+void DeferredLayerUpdater::updateLayer(bool forceFilter, const float* textureTransform) {
     mLayer->setBlend(mBlend);
     mLayer->setForceFilter(forceFilter);
     mLayer->setSize(mWidth, mHeight);
     mLayer->getTexTransform().load(textureTransform);
-
-    if (mLayer->getApi() == Layer::Api::OpenGL) {
-        GlLayer* glLayer = static_cast<GlLayer*>(mLayer);
-        if (renderTarget != glLayer->getRenderTarget()) {
-            glLayer->setRenderTarget(renderTarget);
-            glLayer->bindTexture();
-            glLayer->setFilter(GL_NEAREST, false, true);
-            glLayer->setWrap(GL_CLAMP_TO_EDGE, false, true);
-        }
-    }
 }
 
 void DeferredLayerUpdater::detachSurfaceTexture() {
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 6717361..6164e47 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -101,7 +101,7 @@
 
     void detachSurfaceTexture();
 
-    void updateLayer(bool forceFilter, GLenum renderTarget, const float* textureTransform);
+    void updateLayer(bool forceFilter, const float* textureTransform);
 
     void destroyLayer();
 
diff --git a/libs/hwui/GlLayer.cpp b/libs/hwui/GlLayer.cpp
index aacad54..070e954 100644
--- a/libs/hwui/GlLayer.cpp
+++ b/libs/hwui/GlLayer.cpp
@@ -55,9 +55,15 @@
     texture.deleteTexture();
 }
 
-void GlLayer::bindTexture() const {
-    if (texture.mId) {
-        caches.textureState().bindTexture(texture.target(), texture.mId);
+void GlLayer::setRenderTarget(GLenum renderTarget) {
+    if (renderTarget != getRenderTarget()) {
+        // new render target: bind with new target, and update filter/wrap
+        texture.mTarget = renderTarget;
+        if (texture.mId) {
+            caches.textureState().bindTexture(texture.target(), texture.mId);
+        }
+        texture.setFilter(GL_NEAREST, false, true);
+        texture.setWrap(GL_CLAMP_TO_EDGE, false, true);
     }
 }
 
diff --git a/libs/hwui/GlLayer.h b/libs/hwui/GlLayer.h
index 85ddaff..20aaf4a 100644
--- a/libs/hwui/GlLayer.h
+++ b/libs/hwui/GlLayer.h
@@ -68,23 +68,12 @@
         return texture.target();
     }
 
-    inline void setRenderTarget(GLenum renderTarget) {
-        texture.mTarget = renderTarget;
-    }
-
     inline bool isRenderable() const {
         return texture.target() != GL_NONE;
     }
 
-    void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
-        texture.setWrap(wrap, bindTexture, force);
-    }
+    void setRenderTarget(GLenum renderTarget);
 
-    void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
-        texture.setFilter(filter, bindTexture, force);
-    }
-
-    void bindTexture() const;
     void generateTexture();
 
     /**
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index de80ee3..f2b0eb3 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -128,6 +128,8 @@
         return false;
     }
 
+    // acquire most recent buffer for drawing
+    deferredLayer->updateTexImage();
     deferredLayer->apply();
 
     SkCanvas canvas(*bitmap);
diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp
index 8a5d9cc..acd6110 100644
--- a/libs/hwui/renderthread/OpenGLPipeline.cpp
+++ b/libs/hwui/renderthread/OpenGLPipeline.cpp
@@ -120,6 +120,8 @@
 
 bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
     ATRACE_CALL();
+    // acquire most recent buffer for drawing
+    layer->updateTexImage();
     layer->apply();
     return OpenGLReadbackImpl::copyLayerInto(mRenderThread,
             static_cast<GlLayer&>(*layer->backingLayer()), bitmap);
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 3e52c39..64ec58d 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -74,7 +74,11 @@
     layerUpdater->setTransform(&transform);
 
     // updateLayer so it's ready to draw
-    layerUpdater->updateLayer(true, GL_TEXTURE_EXTERNAL_OES, Matrix4::identity().data);
+    layerUpdater->updateLayer(true, Matrix4::identity().data);
+    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
+        static_cast<GlLayer*>(layerUpdater->backingLayer())->setRenderTarget(
+                GL_TEXTURE_EXTERNAL_OES);
+    }
     return layerUpdater;
 }
 
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index 1ef9dba..87d897e 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -44,7 +44,12 @@
     // push the deferred updates to the layer
     Matrix4 scaledMatrix;
     scaledMatrix.loadScale(0.5, 0.5, 0.0);
-    layerUpdater->updateLayer(true, GL_TEXTURE_EXTERNAL_OES, scaledMatrix.data);
+    layerUpdater->updateLayer(true, scaledMatrix.data);
+    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
+        GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
+        glLayer->setRenderTarget(GL_TEXTURE_EXTERNAL_OES);
+    }
+
 
     // the backing layer should now have all the properties applied.
     if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index ddbd542e..45f88f3 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -1977,6 +1977,24 @@
         public static final String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
 
         /**
+         * The flag indicating whether this TV program is browsable or not.
+         *
+         * <p>This column can only be set by system apps. For other applications, it is a read-only
+         * column. Trying to modify it may cause {@link SecurityException}.
+         *
+         * <p>A value of 1 indicates that the program is browsable and can be shown to users in
+         * the UI. A value of 0 indicates that the program should be hidden from users and the
+         * application who changes this value to 0 should send
+         * {@link TvInputManager#ACTION_PROGRAM_BROWSABLE_DISABLED} to the owner of the program
+         * to notify this change.
+         *
+         * <p>This value is set to 1 (browsable) by default.
+         *
+         * <p>Type: INTEGER (boolean)
+         */
+        public static final String COLUMN_BROWSABLE = "browsable";
+
+        /**
          * The internal ID used by individual TV input services.
          *
          * <p>This is internal to the provider that inserted it, and should not be decoded by other
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index b630270..4c2b031 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -325,23 +325,39 @@
             "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
 
     /**
+     * Action sent by the system to tell the target TV input that one of its program's browsable
+     * state is disabled, i.e., it will no longer be shown to users, which, for example, might
+     * be a result of users' interaction with UI.
+     *
+     * <p>The intent must contain the following bundle parameter:
+     * <ul>
+     *     <li>{@link #EXTRA_PROGRAM_ID} the program ID as a long integer.
+     * </ul>
+     */
+    public static final String ACTION_PROGRAM_BROWSABLE_DISABLED =
+            "android.media.tv.action.PROGRAM_BROWSABLE_DISABLED";
+
+    /**
      * Action sent by an application telling the system to set the given channel as browsable.
      *
      * <p>The intent must contain the following bundle parameters:
      * <ul>
-     *     <li>{@link #EXTRA_CHANNEL_ID} then channel ID as an integer.
+     *     <li>{@link #EXTRA_CHANNEL_ID} the channel ID as a long integer.
      *     <li>{@link #EXTRA_PACKAGE_NAME} the package name of the requesting application.
      * </ul>
      */
     public static final String ACTION_MAKE_CHANNEL_BROWSABLE
             = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
 
-    /** The key for a bundle parameter containing a channel ID as an integer */
+    /** The key for a bundle parameter containing a channel ID as a long integer */
     public static final String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
 
     /** The key for a bundle parameter containing a package name as a string. */
     public static final String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
 
+    /** The key for a bundle parameter containing a program ID as a long integer */
+    public static final String EXTRA_PROGRAM_ID = "android.media.tv.extra.PROGRAM_ID";
+
     private final ITvInputManager mService;
 
     private final Object mLock = new Object();
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 11e2a71..8653523 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -215,6 +215,13 @@
         return colorAccent;
     }
 
+    public static Drawable getDrawable(Context context, int attr) {
+        TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
+        Drawable drawable = ta.getDrawable(0);
+        ta.recycle();
+        return drawable;
+    }
+
     /**
      * Determine whether a package is a "system package", in which case certain things (like
      * disabling notifications or disabling the package altogether) should be disallowed.
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
index 4c11197..0fc9a4d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
@@ -116,7 +116,7 @@
                 if (info == null || !info.enabled
                         || (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
                     mIPm.installExistingPackageAsUser(packageName, mUser.getIdentifier(),
-                            PackageManager.INSTALL_REASON_UNKNOWN);
+                            0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
                     if (DEBUG) {
                         Log.d(TAG, "Installing " + packageName);
                     }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
index 4df199c..8cfec7a 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
@@ -146,7 +146,7 @@
         mHelper.applyUserAppsStates(mockListener);
 
         verify(mIpm, times(1)).installExistingPackageAsUser("app1", testUserId,
-                PackageManager.INSTALL_REASON_UNKNOWN);
+                0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
         verify(mIpm, times(1)).setApplicationHiddenSettingAsUser("app2", false, testUserId);
         verify(mockListener).onDisableUiForPackage("app2");
         verify(mPm, times(1)).deletePackageAsUser(eq("app3"), any(IPackageDeleteObserver.class),
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index edcb9b5..a3a8553 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1531,14 +1531,14 @@
         }
     }
 
-    private Set<String> getEphemeralAccessibleSettings(int settingsType) {
+    private Set<String> getInstantAppAccessibleSettings(int settingsType) {
         switch (settingsType) {
             case SETTINGS_TYPE_GLOBAL:
-                return Settings.Global.EPHEMERAL_SETTINGS;
+                return Settings.Global.INSTANT_APP_SETTINGS;
             case SETTINGS_TYPE_SECURE:
-                return Settings.Secure.EPHEMERAL_SETTINGS;
+                return Settings.Secure.INSTANT_APP_SETTINGS;
             case SETTINGS_TYPE_SYSTEM:
-                return Settings.System.EPHEMERAL_SETTINGS;
+                return Settings.System.INSTANT_APP_SETTINGS;
             default:
                 throw new IllegalArgumentException("Invalid settings type: " + settingsType);
         }
@@ -1547,7 +1547,7 @@
     private List<String> getSettingsNamesLocked(int settingsType, int userId) {
         ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId);
         if (ai.isInstantApp()) {
-            return new ArrayList<String>(getEphemeralAccessibleSettings(settingsType));
+            return new ArrayList<String>(getInstantAppAccessibleSettings(settingsType));
         } else {
             return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId);
         }
@@ -1561,7 +1561,7 @@
         if (!ai.isInstantApp()) {
             return;
         }
-        if (!getEphemeralAccessibleSettings(settingsType).contains(settingName)) {
+        if (!getInstantAppAccessibleSettings(settingsType).contains(settingName)) {
             throw new SecurityException("Setting " + settingName + " is not accessible from"
                     + " ephemeral package " + getCallingPackage());
         }
diff --git a/packages/SystemUI/res/drawable/ic_remove_circle.xml b/packages/SystemUI/res/drawable/ic_remove_circle.xml
new file mode 100644
index 0000000..439cc78
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_remove_circle.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="48dp"
+    android:width="48dp"
+    android:tint="#db4437"
+    android:viewportHeight="48"
+    android:viewportWidth="48" >
+    <path android:fillColor="@android:color/white"
+       android:pathData="M24,4C12.95,4,4,12.95,4,24
+                         s8.95,20,20,20,20-8.95,20-20
+                         S35.05,4,24,4zm10,22H14v-4h20v4z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/preference_widget_radiobutton.xml b/packages/SystemUI/res/layout/preference_widget_radiobutton.xml
new file mode 100644
index 0000000..b3ec43d
--- /dev/null
+++ b/packages/SystemUI/res/layout/preference_widget_radiobutton.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<!-- Layout used by CheckBoxPreference for the checkbox style. This is inflated
+     inside android.R.layout.preference. -->
+<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/checkbox"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:focusable="false"
+    android:clickable="false" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 67def4f..77de9a2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1527,14 +1527,12 @@
     <!-- SysUI Tuner: Button that controls layout of navigation bar [CHAR LIMIT=60] -->
     <string name="nav_bar_layout">Layout</string>
 
-    <!-- SysUI Tuner: Label for section of settings about the left nav button [CHAR LIMIT=60] -->
-    <string name="nav_bar_left">Left</string>
-
-    <!-- SysUI Tuner: Label for section of settings about the right nav button [CHAR LIMIT=60] -->
-    <string name="nav_bar_right">Right</string>
+    <!-- SysUI Tuner: Setting for button type in nav bar [CHAR LIMIT=60] -->
+    <string name="left_nav_bar_button_type">Extra left button type</string>
 
     <!-- SysUI Tuner: Setting for button type in nav bar [CHAR LIMIT=60] -->
-    <string name="nav_bar_button_type">Button type</string>
+    <string name="right_nav_bar_button_type">Extra right button type</string>
+
 
     <!-- SysUI Tuner: Added to nav bar option to indicate it is the default [CHAR LIMIT=60] -->
     <string name="nav_bar_default"> (default)</string>
@@ -1543,7 +1541,7 @@
     <string-array name="nav_bar_buttons">
         <item>Clipboard</item>
         <item>Keycode</item>
-        <item>Menu / Keyboard Switcher</item>
+        <item>Keyboard switcher</item>
         <item>None</item>
     </string-array>
     <string-array name="nav_bar_button_values" translatable="false">
@@ -1555,10 +1553,10 @@
 
     <!-- SysUI Tuner: Labels for different types of navigation bar layouts [CHAR LIMIT=60] -->
     <string-array name="nav_bar_layouts">
-        <item>Divided (default)</item>
-        <item>Centered</item>
-        <item>Left-aligned</item>
-        <item>Right-aligned</item>
+        <item>Normal</item>
+        <item>Compact</item>
+        <item>Left-leaning</item>
+        <item>Right-leaning</item>
     </string-array>
 
     <string-array name="nav_bar_layouts_values" translatable="false">
@@ -1569,7 +1567,7 @@
     </string-array>
 
     <!-- SysUI Tuner: Name of Combination Menu / Keyboard Switcher button [CHAR LIMIT=30] -->
-    <string name="menu_ime">Menu / Keyboard Switcher</string>
+    <string name="menu_ime">Keyboard switcher</string>
     <!-- SysUI Tuner: Save the current settings [CHAR LIMIT=30] -->
     <string name="save">Save</string>
     <!-- SysUI Tuner: Reset to default settings [CHAR LIMIT=30] -->
@@ -1585,10 +1583,16 @@
     <string name="accessibility_key">Custom navigation button</string>
 
     <!-- SysUI Tuner: Nav bar button that emulates a keycode [CHAR LIMIT=30] -->
-    <string name="keycode">Keycode</string>
+    <string name="left_keycode">Left keycode</string>
+
+    <!-- SysUI Tuner: Nav bar button that emulates a keycode [CHAR LIMIT=30] -->
+    <string name="right_keycode">Right keycode</string>
 
     <!-- SysUI Tuner: Settings to change nav bar icon [CHAR LIMIT=30] -->
-    <string name="icon">Icon</string>
+    <string name="left_icon">Left icon</string>
+
+    <!-- SysUI Tuner: Settings to change nav bar icon [CHAR LIMIT=30] -->
+    <string name="right_icon">Right icon</string>
 
     <!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
     <string name="drag_to_add_tiles">Drag to add tiles</string>
@@ -1725,6 +1729,9 @@
         not appear on production builds ever. -->
     <string name="tuner_doze_always_on" translatable="false">Always on</string>
 
+    <!-- SysUI Tuner: Section to customize lockscreen shortcuts [CHAR LIMIT=60] -->
+    <string name="tuner_lock_screen">Lock screen</string>
+
     <!-- Making the PIP fullscreen [CHAR LIMIT=25] -->
     <string name="pip_phone_expand">Expand</string>
 
@@ -1760,20 +1767,47 @@
     <!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=300] -->
     <string name="high_temp_dialog_message">Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally.</string>
 
-    <!-- SysUI Tuner: Group of settings for left lock screen affordance [CHAR LIMIT=60] -->
-    <string name="lockscreen_left">Left</string>
-
-    <!-- SysUI Tuner: Group of settings for right lock screen affordance [CHAR LIMIT=60] -->
-    <string name="lockscreen_right">Right</string>
-
-    <!-- SysUI Tuner: Switch controlling whether to customize lock screen button [CHAR LIMIT=60] -->
-    <string name="lockscreen_customize">Customize shortcut</string>
+    <!-- SysUI Tuner: Button to select lock screen shortcut [CHAR LIMIT=60] -->
+    <string name="lockscreen_shortcut_left">Left shortcut</string>
 
     <!-- SysUI Tuner: Button to select lock screen shortcut [CHAR LIMIT=60] -->
-    <string name="lockscreen_shortcut">Shortcut</string>
+    <string name="lockscreen_shortcut_right">Right shortcut</string>
 
-    <!-- SysUI Tuner: Switch to control if device gets unlocked [CHAR LIMIT=60] -->
-    <string name="lockscreen_unlock">Prompt for password</string>
+    <!-- SysUI Tuner: Switch to control if device gets unlocked by left shortcut [CHAR LIMIT=60] -->
+    <string name="lockscreen_unlock_left">Left shortcut also unlocks</string>
+
+    <!-- SysUI Tuner: Switch to control if device gets unlocked by right shortcut [CHAR LIMIT=60] -->
+    <string name="lockscreen_unlock_right">Right shortcut also unlocks</string>
+
+    <!-- SysUI Tuner: Summary of no shortcut being selected [CHAR LIMIT=60] -->
+    <string name="lockscreen_none">None</string>
+
+    <!-- SysUI Tuner: Format string for describing launching an app [CHAR LIMIT=60] -->
+    <string name="tuner_launch_app">Launch <xliff:g id="app" example="Settings">%1$s</xliff:g></string>
+
+    <!-- SysUI Tuner: Label for section of other apps that can be launched [CHAR LIMIT=60] -->
+    <string name="tuner_other_apps">Other apps</string>
+
+    <!-- SysUI Tuner: Label for icon shaped like a circle [CHAR LIMIT=60] -->
+    <string name="tuner_circle">Circle</string>
+
+    <!-- SysUI Tuner: Label for icon shaped like a plus [CHAR LIMIT=60] -->
+    <string name="tuner_plus">Plus</string>
+
+    <!-- SysUI Tuner: Label for icon shaped like a minus [CHAR LIMIT=60] -->
+    <string name="tuner_minus">Minus</string>
+
+    <!-- SysUI Tuner: Label for icon shaped like a left [CHAR LIMIT=60] -->
+    <string name="tuner_left">Left</string>
+
+    <!-- SysUI Tuner: Label for icon shaped like a right [CHAR LIMIT=60] -->
+    <string name="tuner_right">Right</string>
+
+    <!-- SysUI Tuner: Label for icon shaped like a menu [CHAR LIMIT=60] -->
+    <string name="tuner_menu">Menu</string>
+
+    <!-- SysUI Tuner: App subheading for shortcut selection [CHAR LIMIT=60] -->
+    <string name="tuner_app"><xliff:g id="app">%1$s</xliff:g> app</string>
 
     <!-- Title for the notification channel containing important alerts like low battery. [CHAR LIMIT=NONE] -->
     <string name="notification_channel_alerts">Alerts</string>
diff --git a/packages/SystemUI/res/xml/lockscreen_settings.xml b/packages/SystemUI/res/xml/lockscreen_settings.xml
index 73e29af..1e7d266 100644
--- a/packages/SystemUI/res/xml/lockscreen_settings.xml
+++ b/packages/SystemUI/res/xml/lockscreen_settings.xml
@@ -18,42 +18,25 @@
     xmlns:sysui="http://schemas.android.com/apk/res-auto"
     android:title="@string/other">
 
-    <PreferenceCategory
-        android:key="left"
-        android:title="@string/lockscreen_left">
 
-        <SwitchPreference
-            android:key="customize"
-            android:title="@string/lockscreen_customize" />
+    <Preference
+        android:key="sysui_keyguard_left"
+        android:title="@string/lockscreen_shortcut_left"
+        android:fragment="com.android.systemui.tuner.ShortcutPicker" />
 
-        <Preference
-            android:key="shortcut"
-            android:title="@string/lockscreen_shortcut" />
+    <com.android.systemui.tuner.TunerSwitch
+        android:key="sysui_keyguard_left_unlock"
+        android:title="@string/lockscreen_unlock_left"
+        sysui:defValue="true" />
 
-        <com.android.systemui.tuner.TunerSwitch
-            android:key="sysui_keyguard_left_unlock"
-            android:title="@string/lockscreen_unlock"
-            sysui:defValue="true" />
+    <Preference
+        android:key="sysui_keyguard_right"
+        android:title="@string/lockscreen_shortcut_right" 
+        android:fragment="com.android.systemui.tuner.ShortcutPicker" />
 
-    </PreferenceCategory>
-
-    <PreferenceCategory
-        android:key="right"
-        android:title="@string/lockscreen_right">
-
-        <SwitchPreference
-            android:key="customize"
-            android:title="@string/lockscreen_customize" />
-
-        <Preference
-            android:key="shortcut"
-            android:title="@string/lockscreen_shortcut" />
-
-        <com.android.systemui.tuner.TunerSwitch
-            android:key="sysui_keyguard_right_unlock"
-            android:title="@string/lockscreen_unlock"
-            sysui:defValue="true" />
-
-    </PreferenceCategory>
+    <com.android.systemui.tuner.TunerSwitch
+        android:key="sysui_keyguard_right_unlock"
+        android:title="@string/lockscreen_unlock_right"
+        sysui:defValue="true" />
 
 </PreferenceScreen>
diff --git a/packages/SystemUI/res/xml/nav_bar_tuner.xml b/packages/SystemUI/res/xml/nav_bar_tuner.xml
index 6fa8bec..68e8fad 100644
--- a/packages/SystemUI/res/xml/nav_bar_tuner.xml
+++ b/packages/SystemUI/res/xml/nav_bar_tuner.xml
@@ -18,7 +18,7 @@
     xmlns:sysui="http://schemas.android.com/apk/res-auto"
     android:title="@string/nav_bar">
 
-    <ListPreference
+    <com.android.systemui.tuner.RadioListPreference
         android:key="layout"
         android:title="@string/nav_bar_layout"
         android:summary="%s"
@@ -26,54 +26,42 @@
         android:entries="@array/nav_bar_layouts"
         android:entryValues="@array/nav_bar_layouts_values" />
 
-    <PreferenceCategory
-        android:key="left"
-        android:title="@string/nav_bar_left">
+    <com.android.systemui.tuner.RadioListPreference
+        android:key="type_left"
+        android:title="@string/left_nav_bar_button_type"
+        android:persistent="false"
+        android:summary="%s"
+        android:entries="@array/nav_bar_buttons"
+        android:entryValues="@array/nav_bar_button_values" />
 
-        <DropDownPreference
-            android:key="type_left"
-            android:title="@string/nav_bar_button_type"
-            android:persistent="false"
-            android:summary="%s"
-            android:entries="@array/nav_bar_buttons"
-            android:entryValues="@array/nav_bar_button_values" />
+    <Preference
+        android:key="keycode_left"
+        android:persistent="false"
+        android:title="@string/left_keycode" />
 
-        <Preference
-            android:key="keycode_left"
-            android:persistent="false"
-            android:title="@string/keycode" />
+    <com.android.systemui.tuner.RadioListPreference
+        android:key="icon_left"
+        android:persistent="false"
+        android:summary="%s"
+        android:title="@string/left_icon" />
 
-        <com.android.systemui.tuner.BetterListPreference
-            android:key="icon_left"
-            android:persistent="false"
-            android:summary="%s"
-            android:title="@string/icon" />
+    <com.android.systemui.tuner.RadioListPreference
+        android:key="type_right"
+        android:title="@string/right_nav_bar_button_type"
+        android:summary="%s"
+        android:persistent="false"
+        android:entries="@array/nav_bar_buttons"
+        android:entryValues="@array/nav_bar_button_values" />
 
-    </PreferenceCategory>
+    <Preference
+        android:key="keycode_right"
+        android:persistent="false"
+        android:title="@string/right_keycode" />
 
-    <PreferenceCategory
-        android:key="right"
-        android:title="@string/nav_bar_right">
-
-        <DropDownPreference
-            android:key="type_right"
-            android:title="@string/nav_bar_button_type"
-            android:summary="%s"
-            android:persistent="false"
-            android:entries="@array/nav_bar_buttons"
-            android:entryValues="@array/nav_bar_button_values" />
-
-        <Preference
-            android:key="keycode_right"
-            android:persistent="false"
-            android:title="@string/keycode" />
-
-        <com.android.systemui.tuner.BetterListPreference
-            android:key="icon_right"
-            android:persistent="false"
-            android:summary="%s"
-            android:title="@string/icon" />
-
-    </PreferenceCategory>
+    <com.android.systemui.tuner.RadioListPreference
+        android:key="icon_right"
+        android:persistent="false"
+        android:summary="%s"
+        android:title="@string/right_icon" />
 
 </PreferenceScreen>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 6198ab7..c354811 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -121,6 +121,7 @@
 
     </PreferenceScreen>
 
+    <!--
     <PreferenceScreen
       android:key="picture_in_picture"
       android:title="@string/picture_in_picture">
@@ -143,6 +144,7 @@
           sysui:defValue="false" />
 
     </PreferenceScreen>
+    -->
 
     <Preference
         android:key="nav_bar"
@@ -151,15 +153,10 @@
 
     <Preference
             android:key="lockscreen"
-            android:title="@string/accessibility_desc_lock_screen"
+            android:title="@string/tuner_lock_screen"
             android:fragment="com.android.systemui.tuner.LockscreenFragment" />
 
     <Preference
-            android:key="other"
-            android:title="@string/other"
-            android:fragment="com.android.systemui.tuner.OtherPrefs" />
-
-    <Preference
             android:key="plugins"
             android:title="@string/plugins"
             android:fragment="com.android.systemui.tuner.PluginFragment" />
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 273b5e3..f1e7d53 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -25,6 +25,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
@@ -74,6 +76,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.HashMap;
+import java.util.function.Consumer;
 
 /**
  * Class to handle ugly dependencies throughout sysui until we determine the
@@ -227,6 +230,9 @@
         mProviders.put(StatusBarIconController.class, () ->
                 new StatusBarIconControllerImpl(mContext));
 
+        mProviders.put(FragmentService.class, () ->
+                new FragmentService(mContext));
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
     }
@@ -282,17 +288,42 @@
         T createDependency();
     }
 
+    private <T> void destroyDependency(Class<T> cls, Consumer<T> destroy) {
+        T dep = (T) mDependencies.remove(cls);
+        if (dep != null && destroy != null) {
+            destroy.accept(dep);
+        }
+    }
+
     /**
      * Used in separate processes (like tuner settings) to init the dependencies.
      */
     public static void initDependencies(Context context) {
         if (sDependency != null) return;
         Dependency d = new Dependency();
-        d.mContext = context.getApplicationContext();
+        d.mContext = context;
         d.mComponents = new HashMap<>();
         d.start();
     }
 
+    /**
+     * Used in separate process teardown to ensure the context isn't leaked.
+     *
+     * TODO: Remove once PreferenceFragment doesn't reference getActivity()
+     * anymore and these context hacks are no longer needed.
+     */
+    public static void clearDependencies() {
+        sDependency = null;
+    }
+
+    /**
+     * Checks to see if a dependency is instantiated, if it is it removes it from
+     * the cache and calls the destroy callback.
+     */
+    public static <T> void destroy(Class<T> cls, Consumer<T> destroy) {
+        sDependency.destroyDependency(cls, destroy);
+    }
+
     public static <T> T get(Class<T> cls) {
         return sDependency.getDependency(cls);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 187b557..6caee5f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -67,7 +67,6 @@
      */
     private final Class<?>[] SERVICES = new Class[] {
             Dependency.class,
-            FragmentService.class,
             NotificationChannels.class,
             CommandQueue.CommandQueueStart.class,
             KeyguardViewMediator.class,
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 0c6bf52..57c75bf 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -32,6 +32,7 @@
 import android.view.View;
 
 import com.android.settingslib.applications.InterestingConfigChanges;
+import com.android.systemui.Dependency;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.PluginManager;
@@ -171,6 +172,10 @@
         return mPlugins;
     }
 
+    void destroy() {
+        mFragments.dispatchDestroy();
+    }
+
     public interface FragmentListener {
         void onFragmentViewCreated(String tag, Fragment fragment);
 
@@ -182,8 +187,7 @@
 
     public static FragmentHostManager get(View view) {
         try {
-            return ((SystemUIApplication) view.getContext().getApplicationContext())
-                    .getComponent(FragmentService.class).getFragmentHostManager(view);
+            return Dependency.get(FragmentService.class).getFragmentHostManager(view);
         } catch (ClassCastException e) {
             // TODO: Some auto handling here?
             throw e;
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index 85cde10..9a8512d 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -14,6 +14,7 @@
 
 package com.android.systemui.fragments;
 
+import android.content.Context;
 import android.content.res.Configuration;
 import android.os.Bundle;
 import android.os.Handler;
@@ -21,6 +22,7 @@
 import android.util.Log;
 import android.view.View;
 
+import com.android.systemui.ConfigurationChangedReceiver;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIApplication;
 
@@ -28,16 +30,16 @@
  * Holds a map of root views to FragmentHostStates and generates them as needed.
  * Also dispatches the configuration changes to all current FragmentHostStates.
  */
-public class FragmentService extends SystemUI {
+public class FragmentService implements ConfigurationChangedReceiver {
 
     private static final String TAG = "FragmentService";
 
     private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>();
     private final Handler mHandler = new Handler();
+    private final Context mContext;
 
-    @Override
-    public void start() {
-        putComponent(FragmentService.class, this);
+    public FragmentService(Context context) {
+        mContext = context;
     }
 
     public FragmentHostManager getFragmentHostManager(View view) {
@@ -50,8 +52,14 @@
         return state.getFragmentHostManager();
     }
 
+    public void destroyAll() {
+        for (FragmentHostState state : mHosts.values()) {
+            state.mFragmentHostManager.destroy();
+        }
+    }
+
     @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
+    public void onConfigurationChanged(Configuration newConfig) {
         for (FragmentHostState state : mHosts.values()) {
             state.sendConfigurationChange(newConfig);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index f2c3e61..4e30797 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -301,6 +301,7 @@
         if (position == mEditIndex) position--;
 
         move(mAccessibilityFromIndex, position, v);
+
         notifyDataSetChanged();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index ce72942..ec4ca7a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -102,12 +102,7 @@
             mTokenMap.remove(service.getToken());
             mTiles.remove(tile.getComponent());
             final String slot = tile.getComponent().getClassName();
-            mMainHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mHost.getIconController().removeIcon(slot);
-                }
-            });
+            mMainHandler.post(() -> mHost.getIconController().removeIcon(slot));
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 3bbaf99..3648a06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -22,7 +22,6 @@
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.ColorDrawable;
@@ -331,10 +330,11 @@
         boolean isPreL = Boolean.TRUE.equals(expandedIcon.getTag(R.id.icon_is_pre_L));
         boolean colorize = !isPreL || NotificationUtils.isGrayscale(expandedIcon,
                 NotificationColorUtil.getInstance(mContext));
+        int color = StatusBarIconView.NO_COLOR;
         if (colorize) {
-            int color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded());
-            expandedIcon.setImageTintList(ColorStateList.valueOf(color));
+            color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded());
         }
+        expandedIcon.setStaticDrawableColor(color);
     }
 
     private void updateLimits() {
@@ -1990,7 +1990,7 @@
         mAboveShelf = aboveShelf;
     }
 
-    public class NotificationViewState extends ExpandableViewState {
+    public static class NotificationViewState extends ExpandableViewState {
 
         private final StackScrollState mOverallState;
 
@@ -2011,8 +2011,11 @@
         @Override
         protected void onYTranslationAnimationFinished(View view) {
             super.onYTranslationAnimationFinished(view);
-            if (mHeadsupDisappearRunning) {
-                setHeadsUpAnimatingAway(false);
+            if (view instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+                if (row.isHeadsUpAnimatingAway()) {
+                    row.setHeadsUpAnimatingAway(false);
+                }
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 2425076..d4ed1dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.widget.CachingIconView;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.ViewInvertHelper;
@@ -414,7 +415,8 @@
                 transitionAmount);
         float shelfIconSize = icon.getHeight() * icon.getIconScale();
         float alpha = 1.0f;
-        if (!row.isShowingIcon()) {
+        boolean noIcon = !row.isShowingIcon();
+        if (noIcon) {
             // The view currently doesn't have an icon, lets transform it in!
             alpha = transitionAmount;
             notificationIconSize = shelfIconSize / 2.0f;
@@ -438,6 +440,13 @@
             if (row.isAboveShelf()) {
                 iconState.hidden = true;
             }
+            int shelfColor = icon.getStaticDrawableColor();
+            if (!noIcon && shelfColor != StatusBarIconView.NO_COLOR) {
+                int notificationColor = row.getNotificationHeader().getOriginalNotificationColor();
+                shelfColor = NotificationUtils.interpolateColors(notificationColor, shelfColor,
+                        iconState.iconAppearAmount);
+            }
+            iconState.iconColor = shelfColor;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 6283148..cfbb0a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -19,9 +19,11 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.app.Notification;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -37,7 +39,6 @@
 import android.util.Log;
 import android.util.Property;
 import android.util.TypedValue;
-import android.view.View;
 import android.view.ViewDebug;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.Interpolator;
@@ -50,6 +51,9 @@
 import java.text.NumberFormat;
 
 public class StatusBarIconView extends AnimatedImageView {
+    public static final int NO_COLOR = 0;
+    private final int ANIMATION_DURATION_FAST = 100;
+
     public static final int STATE_ICON = 0;
     public static final int STATE_DOT = 1;
     public static final int STATE_HIDDEN = 2;
@@ -104,6 +108,17 @@
     private ObjectAnimator mDotAnimator;
     private float mDotAppearAmount;
     private OnVisibilityChangedListener mOnVisibilityChangedListener;
+    private int mDrawableColor;
+    private int mIconColor;
+    private ValueAnimator mColorAnimator;
+    private int mCurrentSetColor = NO_COLOR;
+    private int mAnimationStartColor = NO_COLOR;
+    private final ValueAnimator.AnimatorUpdateListener mColorUpdater
+            = animation -> {
+        int newColor = NotificationUtils.interpolateColors(mAnimationStartColor, mIconColor,
+                animation.getAnimatedFraction());
+        setColorInternal(newColor);
+    };
 
     public StatusBarIconView(Context context, String slot, Notification notification) {
         this(context, slot, notification, false);
@@ -123,7 +138,7 @@
         setScaleType(ScaleType.CENTER);
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
         if (mNotification != null) {
-            setIconTint(getContext().getColor(
+            setDecorColor(getContext().getColor(
                     com.android.internal.R.color.notification_icon_default_color));
         }
         reloadDimens();
@@ -446,10 +461,66 @@
         return c.getString(R.string.accessibility_desc_notification_icon, appName, desc);
     }
 
-    public void setIconTint(int iconTint) {
+    /**
+     * Set the color that is used to draw decoration like the overflow dot. This will not be applied
+     * to the drawable.
+     */
+    public void setDecorColor(int iconTint) {
         mDotPaint.setColor(iconTint);
     }
 
+    /**
+     * Set the static color that should be used for the drawable of this icon if it's not
+     * transitioning this also immediately sets the color.
+     */
+    public void setStaticDrawableColor(int color) {
+        mDrawableColor = color;
+        setColorInternal(color);
+        mIconColor = color;
+    }
+
+    private void setColorInternal(int color) {
+        if (color != NO_COLOR) {
+            setImageTintList(ColorStateList.valueOf(color));
+        } else {
+            setImageTintList(null);
+        }
+        mCurrentSetColor = color;
+    }
+
+    public void setIconColor(int iconColor, boolean animate) {
+        if (mIconColor != iconColor) {
+            mIconColor = iconColor;
+            if (mColorAnimator != null) {
+                mColorAnimator.cancel();
+            }
+            if (mCurrentSetColor == iconColor) {
+                return;
+            }
+            if (animate && mCurrentSetColor != NO_COLOR) {
+                mAnimationStartColor = mCurrentSetColor;
+                mColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
+                mColorAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+                mColorAnimator.setDuration(ANIMATION_DURATION_FAST);
+                mColorAnimator.addUpdateListener(mColorUpdater);
+                mColorAnimator.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mColorAnimator = null;
+                        mAnimationStartColor = NO_COLOR;
+                    }
+                });
+                mColorAnimator.start();
+            } else {
+                setColorInternal(iconColor);
+            }
+        }
+    }
+
+    public int getStaticDrawableColor() {
+        return mDrawableColor;
+    }
+
     public void setVisibleState(int state) {
         setVisibleState(state, true /* animate */, null /* endRunnable */);
     }
@@ -482,7 +553,7 @@
                     mIconAppearAnimator = ObjectAnimator.ofFloat(this, ICON_APPEAR_AMOUNT,
                             currentAmount, targetAmount);
                     mIconAppearAnimator.setInterpolator(interpolator);
-                    mIconAppearAnimator.setDuration(100);
+                    mIconAppearAnimator.setDuration(ANIMATION_DURATION_FAST);
                     mIconAppearAnimator.addListener(new AnimatorListenerAdapter() {
                         @Override
                         public void onAnimationEnd(Animator animation) {
@@ -508,7 +579,7 @@
                     mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNT,
                             currentAmount, targetAmount);
                     mDotAnimator.setInterpolator(interpolator);
-                    mDotAnimator.setDuration(100);
+                    mDotAnimator.setDuration(ANIMATION_DURATION_FAST);
                     final boolean runRunnable = !runnableAdded;
                     mDotAnimator.addListener(new AnimatorListenerAdapter() {
                         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 6d7ab47..707997d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -1,7 +1,6 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Rect;
@@ -226,12 +225,13 @@
         for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
             StatusBarIconView v = (StatusBarIconView) mNotificationIcons.getChildAt(i);
             boolean isPreL = Boolean.TRUE.equals(v.getTag(R.id.icon_is_pre_L));
+            int color = StatusBarIconView.NO_COLOR;
             boolean colorize = !isPreL || NotificationUtils.isGrayscale(v, mNotificationColorUtil);
             if (colorize) {
-                v.setImageTintList(ColorStateList.valueOf(
-                        DarkIconDispatcher.getTint(mTintArea, v, mIconTint)));
+                color = DarkIconDispatcher.getTint(mTintArea, v, mIconTint);
             }
-            v.setIconTint(mIconTint);
+            v.setStaticDrawableColor(color);
+            v.setDecorColor(mIconTint);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 571ae26..dc5f98c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -446,6 +446,7 @@
         public boolean useFullTransitionAmount;
         public boolean useLinearTransitionAmount;
         public boolean translateContent;
+        public int iconColor = StatusBarIconView.NO_COLOR;
 
         @Override
         public void applyToView(View view) {
@@ -505,6 +506,7 @@
                     }
                 }
                 icon.setVisibleState(visibleState, animationsAllowed);
+                icon.setIconColor(iconColor, needsCannedAnimation && animationsAllowed);
                 if (animate) {
                     animateTo(icon, animationProperties);
                 } else {
@@ -515,6 +517,14 @@
             needsCannedAnimation = false;
         }
 
+        @Override
+        public void initFrom(View view) {
+            super.initFrom(view);
+            if (view instanceof StatusBarIconView) {
+                iconColor = ((StatusBarIconView) view).getStaticDrawableColor();
+            }
+        }
+
         protected void onYTranslationAnimationFinished(View view) {
             if (hidden) {
                 view.setVisibility(INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
new file mode 100644
index 0000000..e50fd5e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
@@ -0,0 +1,173 @@
+/*
+ * 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.systemui.tuner;
+
+import android.annotation.Nullable;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.support.v14.preference.ListPreferenceDialogFragment;
+import android.support.v7.preference.ListPreference;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class CustomListPreference extends ListPreference {
+
+    public CustomListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public CustomListPreference(Context context, AttributeSet attrs, int defStyleAttr,
+                                int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
+            OnClickListener listener) {
+    }
+
+    protected void onDialogClosed(boolean positiveResult) {
+    }
+
+    protected Dialog onDialogCreated(DialogFragment fragment, Dialog dialog) {
+        return dialog;
+    }
+
+    protected boolean isAutoClosePreference() {
+        return true;
+    }
+
+    /**
+     * Called when a user is about to choose the given value, to determine if we
+     * should show a confirmation dialog.
+     *
+     * @param value the value the user is about to choose
+     * @return the message to show in a confirmation dialog, or {@code null} to
+     *         not request confirmation
+     */
+    protected CharSequence getConfirmationMessage(String value) {
+        return null;
+    }
+
+    protected void onDialogStateRestored(DialogFragment fragment, Dialog dialog,
+            Bundle savedInstanceState) {
+    }
+
+    public static class CustomListPreferenceDialogFragment extends ListPreferenceDialogFragment {
+
+        private static final String KEY_CLICKED_ENTRY_INDEX
+                = "settings.CustomListPrefDialog.KEY_CLICKED_ENTRY_INDEX";
+
+        private int mClickedDialogEntryIndex;
+
+        public static ListPreferenceDialogFragment newInstance(String key) {
+            final ListPreferenceDialogFragment fragment = new CustomListPreferenceDialogFragment();
+            final Bundle b = new Bundle(1);
+            b.putString(ARG_KEY, key);
+            fragment.setArguments(b);
+            return fragment;
+        }
+
+        public CustomListPreference getCustomizablePreference() {
+            return (CustomListPreference) getPreference();
+        }
+
+        @Override
+        protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+            super.onPrepareDialogBuilder(builder);
+            mClickedDialogEntryIndex = getCustomizablePreference()
+                    .findIndexOfValue(getCustomizablePreference().getValue());
+            getCustomizablePreference().onPrepareDialogBuilder(builder, getOnItemClickListener());
+            if (!getCustomizablePreference().isAutoClosePreference()) {
+                builder.setPositiveButton(com.android.internal.R.string.ok, new OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        onItemConfirmed();
+                    }
+                });
+            }
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            Dialog dialog = super.onCreateDialog(savedInstanceState);
+            if (savedInstanceState != null) {
+                mClickedDialogEntryIndex = savedInstanceState.getInt(KEY_CLICKED_ENTRY_INDEX,
+                        mClickedDialogEntryIndex);
+            }
+            return getCustomizablePreference().onDialogCreated(this, dialog);
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+            super.onSaveInstanceState(outState);
+            outState.putInt(KEY_CLICKED_ENTRY_INDEX, mClickedDialogEntryIndex);
+        }
+
+        @Override
+        public void onActivityCreated(Bundle savedInstanceState) {
+            super.onActivityCreated(savedInstanceState);
+            getCustomizablePreference().onDialogStateRestored(this, getDialog(), savedInstanceState);
+        }
+
+        protected OnClickListener getOnItemClickListener() {
+            return new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    setClickedDialogEntryIndex(which);
+                    if (getCustomizablePreference().isAutoClosePreference()) {
+                        onItemConfirmed();
+                    }
+                }
+            };
+        }
+
+        protected void setClickedDialogEntryIndex(int which) {
+            mClickedDialogEntryIndex = which;
+        }
+
+        private String getValue() {
+            final ListPreference preference = getCustomizablePreference();
+            if (mClickedDialogEntryIndex >= 0 && preference.getEntryValues() != null) {
+                return preference.getEntryValues()[mClickedDialogEntryIndex].toString();
+            } else {
+                return null;
+            }
+        }
+
+        protected void onItemConfirmed() {
+            onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);
+            getDialog().dismiss();
+        }
+
+        @Override
+        public void onDialogClosed(boolean positiveResult) {
+            getCustomizablePreference().onDialogClosed(positiveResult);
+            final ListPreference preference = getCustomizablePreference();
+            final String value = getValue();
+            if (positiveResult && value != null) {
+                if (preference.callChangeListener(value)) {
+                    preference.setValue(value);
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
index 6f4a3a4..410d3d2 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -80,10 +80,8 @@
         mTunerService = Dependency.get(TunerService.class);
         mHandler = new Handler();
         addPreferencesFromResource(R.xml.lockscreen_settings);
-        setupGroup((PreferenceGroup) findPreference(KEY_LEFT), LOCKSCREEN_LEFT_BUTTON,
-                LOCKSCREEN_LEFT_UNLOCK);
-        setupGroup((PreferenceGroup) findPreference(KEY_RIGHT), LOCKSCREEN_RIGHT_BUTTON,
-                LOCKSCREEN_RIGHT_UNLOCK);
+        setupGroup(LOCKSCREEN_LEFT_BUTTON, LOCKSCREEN_LEFT_UNLOCK);
+        setupGroup(LOCKSCREEN_RIGHT_BUTTON, LOCKSCREEN_RIGHT_UNLOCK);
     }
 
     @Override
@@ -92,30 +90,14 @@
         mTunables.forEach(t -> mTunerService.removeTunable(t));
     }
 
-    private void setupGroup(PreferenceGroup group, String buttonSetting, String unlockKey) {
-        SwitchPreference customize = (SwitchPreference) group.findPreference(KEY_CUSTOMIZE);
-        Preference shortcut = group.findPreference(KEY_SHORTCUT);
-        SwitchPreference unlock = (SwitchPreference) group.findPreference(unlockKey);
+    private void setupGroup(String buttonSetting, String unlockKey) {
+        Preference shortcut = findPreference(buttonSetting);
+        SwitchPreference unlock = (SwitchPreference) findPreference(unlockKey);
         addTunable((k, v) -> {
-            boolean visible = v != null;
-            customize.setChecked(visible);
-            shortcut.setVisible(visible);
+            boolean visible = !TextUtils.isEmpty(v);
             unlock.setVisible(visible);
-            if (visible) {
-                setSummary(shortcut, v);
-            }
+            setSummary(shortcut, v);
         }, buttonSetting);
-        customize.setOnPreferenceChangeListener((preference, newValue) -> {
-            boolean hasSetting = mTunerService.getValue(buttonSetting) != null;
-            if (hasSetting != (boolean) newValue) {
-                mHandler.post(() -> mTunerService.setValue(buttonSetting, hasSetting ? null : ""));
-            }
-            return true;
-        });
-        shortcut.setOnPreferenceClickListener(preference -> {
-            showSelectDialog(buttonSetting);
-            return true;
-        });
     }
 
     private void showSelectDialog(String buttonSetting) {
@@ -129,24 +111,15 @@
             mTunerService.setValue(buttonSetting, item.getSettingValue());
             dialog.dismiss();
         });
-        LauncherApps apps = getContext().getSystemService(LauncherApps.class);
-        List<LauncherActivityInfo> activities = apps.getActivityList(null,
-                Process.myUserHandle());
-
-        activities.forEach(info -> {
-            App app = new App(getContext(), info);
-            try {
-                new ShortcutParser(getContext(), info.getComponentName()).getShortcuts().forEach(
-                        shortcut -> app.addChild(new StaticShortcut(getContext(), shortcut)));
-            } catch (NameNotFoundException e) {
-            }
-            adapter.addItem(app);
-        });
 
         v.setAdapter(adapter);
     }
 
     private void setSummary(Preference shortcut, String value) {
+        if (value == null) {
+            shortcut.setSummary(R.string.lockscreen_none);
+            return;
+        }
         if (value.contains("::")) {
             Shortcut info = getShortcutInfo(getContext(), value);
             shortcut.setSummary(info != null ? info.label : null);
@@ -155,7 +128,7 @@
             shortcut.setSummary(info != null ? info.loadLabel(getContext().getPackageManager())
                     : null);
         } else {
-            shortcut.setSummary(null);
+            shortcut.setSummary(R.string.lockscreen_none);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
index 28a0057..45abd45 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -33,6 +33,9 @@
 import android.content.DialogInterface.OnClickListener;
 import android.content.res.Resources;
 import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.FontMetricsInt;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
@@ -58,7 +61,7 @@
 
 import java.util.ArrayList;
 
-public class NavBarTuner extends PreferenceFragment {
+public class NavBarTuner extends TunerPreferenceFragment {
 
     private static final String LAYOUT = "layout";
     private static final String LEFT = "left";
@@ -68,13 +71,13 @@
     private static final String KEYCODE = "keycode";
     private static final String ICON = "icon";
 
-    private static final int[] ICONS = new int[]{
-            R.drawable.ic_qs_circle,
-            R.drawable.ic_add,
-            R.drawable.ic_remove,
-            R.drawable.ic_left,
-            R.drawable.ic_right,
-            R.drawable.ic_menu,
+    private static final int[][] ICONS = new int[][]{
+            {R.drawable.ic_qs_circle, R.string.tuner_circle},
+            {R.drawable.ic_add, R.string.tuner_plus},
+            {R.drawable.ic_remove, R.string.tuner_minus},
+            {R.drawable.ic_left, R.string.tuner_left},
+            {R.drawable.ic_right, R.string.tuner_right},
+            {R.drawable.ic_menu, R.string.tuner_menu},
     };
 
     private final ArrayList<Tunable> mTunables = new ArrayList<>();
@@ -96,10 +99,8 @@
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         addPreferencesFromResource(R.xml.nav_bar_tuner);
         bindLayout((ListPreference) findPreference(LAYOUT));
-        bindButton((PreferenceCategory) findPreference(LEFT),
-                NAV_BAR_LEFT, NAVSPACE);
-        bindButton((PreferenceCategory) findPreference(RIGHT),
-                NAV_BAR_RIGHT, MENU_IME);
+        bindButton(NAV_BAR_LEFT, NAVSPACE, LEFT);
+        bindButton(NAV_BAR_RIGHT, MENU_IME, RIGHT);
     }
 
     @Override
@@ -129,9 +130,8 @@
         });
     }
 
-    private void bindButton(PreferenceCategory parent, String setting, String def) {
-        String k = parent.getKey();
-        DropDownPreference type = (DropDownPreference) findPreference(TYPE + "_" + k);
+    private void bindButton(String setting, String def, String k) {
+        ListPreference type = (ListPreference) findPreference(TYPE + "_" + k);
         Preference keycode = findPreference(KEYCODE + "_" + k);
         ListPreference icon = (ListPreference) findPreference(ICON + "_" + k);
         setupIcons(icon);
@@ -195,8 +195,14 @@
                     .loadDrawable(getContext());
             d.setTint(Color.BLACK);
             d.setBounds(0, 0, size, size);
-            ImageSpan span = new ImageSpan(d);
+            ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
             builder.append("  ", span, 0);
+            builder.append(" ");
+            for (int i = 0; i < ICONS.length; i++) {
+                if (ICONS[i][0] == id) {
+                    builder.append(getString(ICONS[i][1]));
+                }
+            }
             icon.setSummary(builder);
         } catch (Exception e) {
             Log.d("NavButton", "Problem with summary", e);
@@ -204,7 +210,7 @@
         }
     }
 
-    private void setValue(String setting, DropDownPreference type, Preference keycode,
+    private void setValue(String setting, ListPreference type, Preference keycode,
             ListPreference icon) {
         String button = type.getValue();
         if (KEY.equals(button)) {
@@ -226,14 +232,16 @@
                 getContext().getResources().getDisplayMetrics());
         for (int i = 0; i < ICONS.length; i++) {
             SpannableStringBuilder builder = new SpannableStringBuilder();
-            Drawable d = Icon.createWithResource(getContext().getPackageName(), ICONS[i])
+            Drawable d = Icon.createWithResource(getContext().getPackageName(), ICONS[i][0])
                     .loadDrawable(getContext());
             d.setTint(Color.BLACK);
             d.setBounds(0, 0, size, size);
-            ImageSpan span = new ImageSpan(d);
+            ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
             builder.append("  ", span, 0);
+            builder.append(" ");
+            builder.append(getString(ICONS[i][1]));
             labels[i] = builder;
-            values[i] = getContext().getPackageName() + "/" + ICONS[i];
+            values[i] = getContext().getPackageName() + "/" + ICONS[i][0];
         }
         icon.setEntries(labels);
         icon.setEntryValues(values);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
new file mode 100644
index 0000000..dc0d8bf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
@@ -0,0 +1,145 @@
+/*
+ * 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.systemui.tuner;
+
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toolbar;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.R;
+
+import libcore.util.Objects;
+
+public class RadioListPreference extends CustomListPreference {
+
+    private OnClickListener mOnClickListener;
+    private CharSequence mSummary;
+
+    public RadioListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(Builder builder, OnClickListener listener) {
+        mOnClickListener = listener;
+    }
+
+    @Override
+    public void setSummary(CharSequence summary) {
+        super.setSummary(summary);
+        mSummary = summary;
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        if (mSummary == null || mSummary.toString().contains("%s")) {
+            return super.getSummary();
+        }
+        return mSummary;
+    }
+
+    @Override
+    protected Dialog onDialogCreated(DialogFragment fragment, Dialog dialog) {
+        Dialog d = new Dialog(getContext(), android.R.style.Theme_DeviceDefault_Settings);
+        Toolbar t = (Toolbar) d.findViewById(com.android.internal.R.id.action_bar);
+        View v = new View(getContext());
+        v.setId(R.id.content);
+        d.setContentView(v);
+        t.setTitle(getTitle());
+        t.setNavigationIcon(Utils.getDrawable(d.getContext(), android.R.attr.homeAsUpIndicator));
+        t.setNavigationOnClickListener(view -> d.dismiss());
+
+        RadioFragment f = new RadioFragment();
+        f.setPreference(this);
+        FragmentHostManager.get(v).getFragmentManager()
+                .beginTransaction()
+                .add(android.R.id.content, f)
+                .commit();
+        return d;
+    }
+
+    @Override
+    protected void onDialogStateRestored(DialogFragment fragment, Dialog dialog,
+            Bundle savedInstanceState) {
+        super.onDialogStateRestored(fragment, dialog, savedInstanceState);
+        View view = dialog.findViewById(R.id.content);
+        RadioFragment radioFragment = (RadioFragment) FragmentHostManager.get(view)
+                .getFragmentManager().findFragmentById(R.id.content);
+        if (radioFragment != null) {
+            radioFragment.setPreference(this);
+        }
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        super.onDialogClosed(positiveResult);
+    }
+
+    public static class RadioFragment extends TunerPreferenceFragment {
+        private RadioListPreference mListPref;
+
+        @Override
+        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+            Context context = getPreferenceManager().getContext();
+            PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(context);
+            setPreferenceScreen(screen);
+            if (mListPref != null) {
+                update();
+            }
+        }
+
+        private void update() {
+            Context context = getPreferenceManager().getContext();
+
+            CharSequence[] entries = mListPref.getEntries();
+            CharSequence[] values = mListPref.getEntryValues();
+            CharSequence current = mListPref.getValue();
+            for (int i = 0; i < entries.length; i++) {
+                CharSequence entry = entries[i];
+                SelectablePreference pref = new SelectablePreference(context);
+                getPreferenceScreen().addPreference(pref);
+                pref.setTitle(entry);
+                pref.setChecked(Objects.equal(current, values[i]));
+                pref.setKey(String.valueOf(i));
+            }
+        }
+
+        @Override
+        public boolean onPreferenceTreeClick(Preference preference) {
+            mListPref.mOnClickListener.onClick(null, Integer.parseInt(preference.getKey()));
+            return true;
+        }
+
+        public void setPreference(RadioListPreference radioListPreference) {
+            mListPref = radioListPreference;
+            if (getPreferenceManager() != null) {
+                update();
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
new file mode 100644
index 0000000..1d15708
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
@@ -0,0 +1,45 @@
+/*
+ * 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.systemui.tuner;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.support.v7.preference.CheckBoxPreference;
+import android.util.TypedValue;
+
+import com.android.systemui.statusbar.ScalingDrawableWrapper;
+
+public class SelectablePreference extends CheckBoxPreference {
+    private final int mSize;
+
+    public SelectablePreference(Context context) {
+        super(context);
+        setWidgetLayoutResource(com.android.systemui.R.layout.preference_widget_radiobutton);
+        setSelectable(true);
+        mSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32,
+                context.getResources().getDisplayMetrics());
+    }
+
+    @Override
+    public void setIcon(Drawable icon) {
+        super.setIcon(new ScalingDrawableWrapper(icon,
+                mSize / (float) icon.getIntrinsicWidth()));
+    }
+
+    @Override
+    public String toString() {
+        return "";
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
new file mode 100644
index 0000000..533388a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
@@ -0,0 +1,200 @@
+/*
+ * 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.systemui.tuner;
+
+import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
+
+import android.content.Context;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.os.Process;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.PreferenceViewHolder;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.tuner.ShortcutParser.Shortcut;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ShortcutPicker extends PreferenceFragment implements Tunable {
+
+    private final ArrayList<SelectablePreference> mSelectablePreferences = new ArrayList<>();
+    private String mKey;
+    private SelectablePreference mNonePreference;
+    private TunerService mTunerService;
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        Context context = getPreferenceManager().getContext();
+        PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(context);
+        screen.setOrderingAsAdded(true);
+        PreferenceCategory otherApps = new PreferenceCategory(context);
+        otherApps.setTitle(R.string.tuner_other_apps);
+
+        mNonePreference = new SelectablePreference(context);
+        mSelectablePreferences.add(mNonePreference);
+        mNonePreference.setTitle(R.string.lockscreen_none);
+        mNonePreference.setIcon(R.drawable.ic_remove_circle);
+        screen.addPreference(mNonePreference);
+
+        LauncherApps apps = getContext().getSystemService(LauncherApps.class);
+        List<LauncherActivityInfo> activities = apps.getActivityList(null,
+                Process.myUserHandle());
+
+        screen.addPreference(otherApps);
+        activities.forEach(info -> {
+            try {
+                List<Shortcut> shortcuts = new ShortcutParser(getContext(),
+                        info.getComponentName()).getShortcuts();
+                AppPreference appPreference = new AppPreference(context, info);
+                mSelectablePreferences.add(appPreference);
+                if (shortcuts.size() != 0) {
+                    //PreferenceCategory category = new PreferenceCategory(context);
+                    //screen.addPreference(category);
+                    //category.setTitle(info.getLabel());
+                    screen.addPreference(appPreference);
+                    shortcuts.forEach(shortcut -> {
+                        ShortcutPreference shortcutPref = new ShortcutPreference(context, shortcut,
+                                info.getLabel());
+                        mSelectablePreferences.add(shortcutPref);
+                        screen.addPreference(shortcutPref);
+                    });
+                    return;
+                }
+                otherApps.addPreference(appPreference);
+            } catch (NameNotFoundException e) {
+            }
+        });
+        // Move other apps to the bottom.
+        screen.removePreference(otherApps);
+        for (int i = 0; i < otherApps.getPreferenceCount(); i++) {
+            Preference p = otherApps.getPreference(0);
+            otherApps.removePreference(p);
+            p.setOrder(Preference.DEFAULT_ORDER);
+            screen.addPreference(p);
+        }
+        //screen.addPreference(otherApps);
+
+        setPreferenceScreen(screen);
+        mKey = getArguments().getString(ARG_PREFERENCE_ROOT);
+        mTunerService = Dependency.get(TunerService.class);
+        mTunerService.addTunable(this, mKey);
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(Preference preference) {
+        mTunerService.setValue(mKey, preference.toString());
+        getActivity().onBackPressed();
+        return true;
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        if (LOCKSCREEN_LEFT_BUTTON.equals(mKey)) {
+            getActivity().setTitle(R.string.lockscreen_shortcut_left);
+        } else {
+            getActivity().setTitle(R.string.lockscreen_shortcut_right);
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mTunerService.removeTunable(this);
+    }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        String v = newValue != null ? newValue : "";
+        mSelectablePreferences.forEach(p -> p.setChecked(v.equals(p.toString())));
+    }
+
+    private static class AppPreference extends SelectablePreference {
+        private final LauncherActivityInfo mInfo;
+        private boolean mBinding;
+
+        public AppPreference(Context context, LauncherActivityInfo info) {
+            super(context);
+            mInfo = info;
+            setTitle(context.getString(R.string.tuner_launch_app, info.getLabel()));
+            setSummary(context.getString(R.string.tuner_app, info.getLabel()));
+        }
+
+        @Override
+        public void onBindViewHolder(PreferenceViewHolder holder) {
+            mBinding = true;
+            if (getIcon() == null) {
+                setIcon(mInfo.getBadgedIcon(
+                        getContext().getResources().getConfiguration().densityDpi));
+            }
+            mBinding = false;
+            super.onBindViewHolder(holder);
+        }
+
+        @Override
+        protected void notifyChanged() {
+            if (mBinding) return;
+            super.notifyChanged();
+        }
+
+        @Override
+        public String toString() {
+            return mInfo.getComponentName().flattenToString();
+        }
+    }
+
+    private static class ShortcutPreference extends SelectablePreference {
+        private final Shortcut mShortcut;
+        private boolean mBinding;
+
+        public ShortcutPreference(Context context, Shortcut shortcut, CharSequence appLabel) {
+            super(context);
+            mShortcut = shortcut;
+            setTitle(shortcut.label);
+            setSummary(context.getString(R.string.tuner_app, appLabel));
+        }
+
+        @Override
+        public void onBindViewHolder(PreferenceViewHolder holder) {
+            mBinding = true;
+            if (getIcon() == null) {
+                setIcon(mShortcut.icon.loadDrawable(getContext()));
+            }
+            mBinding = false;
+            super.onBindViewHolder(holder);
+        }
+
+        @Override
+        protected void notifyChanged() {
+            if (mBinding) return;
+            super.notifyChanged();
+        }
+
+        @Override
+        public String toString() {
+            return mShortcut.toString();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 74280a3..4eb1db6 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -22,10 +22,12 @@
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 import android.util.Log;
+import android.view.MenuItem;
 
 import com.android.settingslib.drawer.SettingsDrawerActivity;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.fragments.FragmentService;
 
 public class TunerActivity extends SettingsDrawerActivity implements
         PreferenceFragment.OnPreferenceStartFragmentCallback,
@@ -51,6 +53,22 @@
     }
 
     @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        Dependency.destroy(FragmentService.class, s -> s.destroyAll());
+        Dependency.clearDependencies();
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        if (item.getItemId() == android.R.id.home) {
+            onBackPressed();
+            return true;
+        }
+        return super.onMenuItemSelected(featureId, item);
+    }
+
+    @Override
     public void onBackPressed() {
         if (!getFragmentManager().popBackStackImmediate()) {
             super.onBackPressed();
@@ -62,6 +80,9 @@
         try {
             Class<?> cls = Class.forName(pref.getFragment());
             Fragment fragment = (Fragment) cls.newInstance();
+            final Bundle b = new Bundle(1);
+            b.putString(PreferenceFragment.ARG_PREFERENCE_ROOT, pref.getKey());
+            fragment.setArguments(b);
             FragmentTransaction transaction = getFragmentManager().beginTransaction();
             setTitle(pref.getTitle());
             transaction.replace(R.id.content_frame, fragment);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
new file mode 100644
index 0000000..06d40da
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
@@ -0,0 +1,36 @@
+/*
+ * 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.systemui.tuner;
+
+import android.app.DialogFragment;
+import android.os.Bundle;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+
+public abstract class TunerPreferenceFragment extends PreferenceFragment {
+
+    @Override
+    public void onDisplayPreferenceDialog(Preference preference) {
+        DialogFragment f = null;
+        if (preference instanceof CustomListPreference) {
+            f = CustomListPreference.CustomListPreferenceDialogFragment
+                    .newInstance(preference.getKey());
+        } else {
+            super.onDisplayPreferenceDialog(preference);
+        }
+        f.setTargetFragment(this, 0);
+        f.show(getFragmentManager(), "dialog_preference");
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 4146cb81..70c7d3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -18,26 +18,32 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
 
+import static org.mockito.Mockito.mock;
+
 import android.content.ComponentName;
-import android.content.Context;
 import android.os.Looper;
 import android.service.quicksettings.Tile;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.systemui.SysUIRunner;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.policy.DataSaverController;
-import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import java.util.ArrayList;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.utils.TestableLooper;
+import com.android.systemui.utils.TestableLooper.RunWithLooper;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
+import java.util.ArrayList;
+
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(SysUIRunner.class)
+@RunWithLooper(setAsMainLooper = true)
 public class TileServicesTest extends SysuiTestCase {
     private static int NUM_FAKES = TileServices.DEFAULT_MAX_BOUND * 2;
 
@@ -46,16 +52,24 @@
 
     @Before
     public void setUp() throws Exception {
+        TestableLooper.get(this).setAsMainLooper();
         mManagers = new ArrayList<>();
-        QSTileHost host = new QSTileHost(mContext, null, null);
+        QSTileHost host = new QSTileHost(mContext, null,
+                mock(StatusBarIconController.class));
         mTileService = new TestTileServices(host, Looper.getMainLooper());
     }
 
+    @After
+    public void tearDown() throws Exception {
+        mTileService.getHost().destroy();
+        TestableLooper.get(this).processAllMessages();
+    }
+
     @Test
     public void testRecalculateBindAllowance() {
         // Add some fake tiles.
         for (int i = 0; i < NUM_FAKES; i++) {
-            mTileService.getTileWrapper(Mockito.mock(CustomTile.class));
+            mTileService.getTileWrapper(mock(CustomTile.class));
         }
         assertEquals(NUM_FAKES, mManagers.size());
 
@@ -91,7 +105,7 @@
     @Test
     public void testCalcFew() {
         for (int i = 0; i < TileServices.DEFAULT_MAX_BOUND - 1; i++) {
-            mTileService.getTileWrapper(Mockito.mock(CustomTile.class));
+            mTileService.getTileWrapper(mock(CustomTile.class));
         }
         mTileService.recalculateBindAllowance();
 
@@ -115,7 +129,7 @@
 
         @Override
         protected TileServiceManager onCreateTileService(ComponentName component, Tile qsTile) {
-            TileServiceManager manager = Mockito.mock(TileServiceManager.class);
+            TileServiceManager manager = mock(TileServiceManager.class);
             mManagers.add(manager);
             return manager;
         }
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 14abb53..40499c9 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -351,7 +351,7 @@
     }
 
     public List<R> queryIntentFromList(Intent intent, String resolvedType, boolean defaultOnly,
-            boolean visibleToEphemeral, boolean isEphemeral, ArrayList<F[]> listCut, int userId) {
+            ArrayList<F[]> listCut, int userId) {
         ArrayList<R> resultList = new ArrayList<R>();
 
         final boolean debug = localLOGV ||
@@ -361,8 +361,8 @@
         final String scheme = intent.getScheme();
         int N = listCut.size();
         for (int i = 0; i < N; ++i) {
-            buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
-                    isEphemeral, resolvedType, scheme, listCut.get(i), resultList, userId);
+            buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme,
+                    listCut.get(i), resultList, userId);
         }
         filterResults(resultList);
         sortResults(resultList);
@@ -370,7 +370,7 @@
     }
 
     public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
-            boolean visibleToEphemeral, boolean isEphemeral, int userId) {
+            int userId) {
         String scheme = intent.getScheme();
 
         ArrayList<R> finalList = new ArrayList<R>();
@@ -443,20 +443,20 @@
 
         FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
         if (firstTypeCut != null) {
-            buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
-                    isEphemeral, resolvedType, scheme, firstTypeCut, finalList, userId);
+            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
+                    scheme, firstTypeCut, finalList, userId);
         }
         if (secondTypeCut != null) {
-            buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
-                    isEphemeral, resolvedType, scheme, secondTypeCut, finalList, userId);
+            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
+                    scheme, secondTypeCut, finalList, userId);
         }
         if (thirdTypeCut != null) {
-            buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
-                    isEphemeral, resolvedType, scheme, thirdTypeCut, finalList, userId);
+            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
+                    scheme, thirdTypeCut, finalList, userId);
         }
         if (schemeCut != null) {
-            buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
-                    isEphemeral, resolvedType, scheme, schemeCut, finalList, userId);
+            buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
+                    scheme, schemeCut, finalList, userId);
         }
         filterResults(finalList);
         sortResults(finalList);
@@ -694,8 +694,8 @@
     }
 
     private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
-            boolean debug, boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral,
-            String resolvedType, String scheme, F[] src, List<R> dest, int userId) {
+            boolean debug, boolean defaultOnly, String resolvedType, String scheme,
+            F[] src, List<R> dest, int userId) {
         final String action = intent.getAction();
         final Uri data = intent.getData();
         final String packageName = intent.getPackage();
@@ -735,15 +735,6 @@
                 continue;
             }
 
-            // throw out filters that aren't visible to ephemeral apps
-            if (visibleToEphemeral && !filter.isVisibleToEphemeral()) {
-                continue;
-            }
-            // throw out ephemeral filters if we're not explicitly requesting them
-            if (!isEphemeral && filter.isEphemeral()) {
-                continue;
-            }
-
             // Are we verified ?
             if (filter.getAutoVerify()) {
                 if (localVerificationLOGV || debug) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a73eb18..d9123f4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -293,6 +293,7 @@
 import android.service.voice.VoiceInteractionManagerInternal;
 import android.service.voice.VoiceInteractionSession;
 import android.telecom.TelecomManager;
+import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.text.format.Time;
 import android.text.style.SuggestionSpan;
@@ -3776,6 +3777,11 @@
             app.requiredAbi = requiredAbi;
             app.instructionSet = instructionSet;
 
+            // the per-user SELinux context must be set
+            if (TextUtils.isEmpty(app.info.seInfoUser)) {
+                throw new IllegalStateException("SELinux tag not defined");
+            }
+            final String seInfo = app.info.seInfo + app.info.seInfoUser;
             // Start the process.  It will either succeed and return a result containing
             // the PID of the new process, or else throw a RuntimeException.
             boolean isActivityProcess = (entryPoint == null);
@@ -3787,12 +3793,12 @@
             if (hostingType.equals("webview_service")) {
                 startResult = Process.startWebView(entryPoint,
                         app.processName, uid, uid, gids, debugFlags, mountExternal,
-                        app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, entryPointArgs);
             } else {
                 startResult = Process.start(entryPoint,
                         app.processName, uid, uid, gids, debugFlags, mountExternal,
-                        app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, invokeWith, entryPointArgs);
             }
             checkTime(startTime, "startProcess: returned from zygote!");
@@ -3808,7 +3814,7 @@
 
             try {
                 AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,
-                        app.info.seinfo, app.info.sourceDir, startResult.pid);
+                        seInfo, app.info.sourceDir, startResult.pid);
             } catch (RemoteException ex) {
                 // Ignore
             }
@@ -18774,8 +18780,7 @@
                     }
                     List<BroadcastFilter> registeredReceiversForUser =
                             mReceiverResolver.queryIntent(intent,
-                                    resolvedType, false, false /*visibleToEphemeral*/,
-                                    false /*isInstant*/, users[i]);
+                                    resolvedType, false /*defaultOnly*/, users[i]);
                     if (registeredReceivers == null) {
                         registeredReceivers = registeredReceiversForUser;
                     } else if (registeredReceiversForUser != null) {
@@ -18784,8 +18789,7 @@
                 }
             } else {
                 registeredReceivers = mReceiverResolver.queryIntent(intent,
-                        resolvedType, false, false /*visibleToEphemeral*/,
-                        false /*isInstant*/, userId);
+                        resolvedType, false /*defaultOnly*/, userId);
             }
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 95734a4..2f84486 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1196,7 +1196,7 @@
     ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
         try {
             return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
-                    PackageManager.MATCH_DEFAULT_ONLY | flags
+                    PackageManager.MATCH_INSTANT | PackageManager.MATCH_DEFAULT_ONLY | flags
                     | ActivityManagerService.STOCK_PM_FLAGS, userId);
         } catch (RemoteException e) {
         }
diff --git a/services/core/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java
index 93c14b9..376a864 100644
--- a/services/core/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/core/java/com/android/server/firewall/IntentFirewall.java
@@ -151,8 +151,7 @@
         // For the first pass, find all the rules that have at least one intent-filter or
         // component-filter that matches this intent
         List<Rule> candidateRules;
-        candidateRules = resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/,
-                false /*visibleToEphemeral*/, false /*isInstant*/, 0);
+        candidateRules = resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, 0);
         if (candidateRules == null) {
             candidateRules = new ArrayList<Rule>();
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 67acdaf..f2b5564 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3887,14 +3887,18 @@
     private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete, int reason) {
         final String canceledKey = r.getKey();
 
-        // Remove from either list
-        boolean wasPosted;
-        if (mNotificationList.remove(r)) {
-            mNotificationsByKey.remove(r.sbn.getKey());
+        // Remove from both lists, either list could have a separate Record for what is effectively
+        // the same notification.
+        boolean wasPosted = false;
+        NotificationRecord recordInList = null;
+        if ((recordInList = findNotificationByListLocked(mNotificationList, r.getKey())) != null) {
+            mNotificationList.remove(recordInList);
+            mNotificationsByKey.remove(recordInList.sbn.getKey());
             wasPosted = true;
-        } else {
-            mEnqueuedNotifications.remove(r);
-            wasPosted = false;
+        }
+        if ((recordInList = findNotificationByListLocked(mEnqueuedNotifications, r.getKey()))
+                != null) {
+            mEnqueuedNotifications.remove(recordInList);
         }
 
         // Record caller.
@@ -4322,17 +4326,12 @@
     // TODO: need to combine a bunch of these getters with slightly different behavior.
     // TODO: Should enqueuing just add to mNotificationsByKey instead?
     private NotificationRecord findNotificationByKeyLocked(String key) {
-        final int N = mNotificationList.size();
-        for (int i = 0; i < N; i++) {
-            if (key.equals(mNotificationList.get(i).getKey())) {
-                return mNotificationList.get(i);
-            }
+        NotificationRecord r;
+        if ((r = findNotificationByListLocked(mNotificationList, key)) != null) {
+            return r;
         }
-        final int M = mEnqueuedNotifications.size();
-        for (int i = 0; i < M; i++) {
-            if (key.equals(mEnqueuedNotifications.get(i).getKey())) {
-                return mEnqueuedNotifications.get(i);
-            }
+        if ((r = findNotificationByListLocked(mEnqueuedNotifications, key)) != null) {
+            return r;
         }
         return null;
     }
@@ -4350,8 +4349,7 @@
     }
 
     private NotificationRecord findNotificationByListLocked(ArrayList<NotificationRecord> list,
-            String pkg, String tag, int id, int userId)
-    {
+            String pkg, String tag, int id, int userId) {
         final int len = list.size();
         for (int i = 0; i < len; i++) {
             NotificationRecord r = list.get(i);
@@ -4363,6 +4361,18 @@
         return null;
     }
 
+    private NotificationRecord findNotificationByListLocked(ArrayList<NotificationRecord> list,
+            String key)
+    {
+        final int N = list.size();
+        for (int i = 0; i < N; i++) {
+            if (key.equals(list.get(i).getKey())) {
+                return list.get(i);
+            }
+        }
+        return null;
+    }
+
     // lock on mNotificationList
     int indexOfNotificationLocked(String key) {
         final int N = mNotificationList.size();
diff --git a/services/core/java/com/android/server/pm/EphemeralResolver.java b/services/core/java/com/android/server/pm/EphemeralResolver.java
index 3c55422..d99a1b6 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolver.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolver.java
@@ -234,8 +234,7 @@
                     }
                 }
                 List<EphemeralResponse> matchedResolveInfoList = ephemeralResolver.queryIntent(
-                        intent, resolvedType, false /*defaultOnly*/, false /*visibleToEphemeral*/,
-                        false /*isInstant*/, userId);
+                        intent, resolvedType, false /*defaultOnly*/, userId);
                 if (!matchedResolveInfoList.isEmpty()) {
                     return matchedResolveInfoList.get(0);
                 }
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index 42934a4..23925ad 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -217,7 +217,7 @@
             propagateInstantAppPermissionsIfNeeded(pkg.packageName, userId);
 
             // Track instant apps
-            if (pkg.applicationInfo.isInstantApp()) {
+            if (ps.getInstantApp(userId)) {
                 addInstantAppLPw(userId, ps.appId);
             }
 
@@ -257,7 +257,7 @@
                 continue;
             }
 
-            if (pkg.applicationInfo.isInstantApp()) {
+            if (ps.getInstantApp(userId)) {
                 // Add a record for an uninstalled instant app
                 addUninstalledInstantAppLPw(pkg, userId);
                 removeInstantAppLPw(userId, ps.appId);
@@ -533,11 +533,12 @@
 
         final int packageCount = mService.mPackages.size();
         for (int i = 0; i < packageCount; i++) {
-            PackageParser.Package pkg = mService.mPackages.valueAt(i);
-            if (!pkg.applicationInfo.isInstantApp()) {
+            final PackageParser.Package pkg = mService.mPackages.valueAt(i);
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (ps == null || !ps.getInstantApp(userId)) {
                 continue;
             }
-            InstantAppInfo info = createInstantAppInfoForPackage(
+            final InstantAppInfo info = createInstantAppInfoForPackage(
                     pkg, userId, true);
             if (info == null) {
                 continue;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index efd3132..0df4570 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -683,9 +683,9 @@
         File stageDir = null;
         String stageCid = null;
         if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
-            final boolean isEphemeral =
-                    (params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
-            stageDir = buildStageDir(params.volumeUuid, sessionId, isEphemeral);
+            final boolean isInstant =
+                    (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
+            stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
         } else {
             stageCid = buildExternalStageCid(sessionId);
         }
@@ -787,9 +787,6 @@
     }
 
     private File buildStagingDir(String volumeUuid, boolean isEphemeral) {
-        if (isEphemeral) {
-            return Environment.getDataAppEphemeralDirectory(volumeUuid);
-        }
         return Environment.getDataAppDirectory(volumeUuid);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 067a136..463cfac 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -704,7 +704,7 @@
             final ApkLite apk;
             try {
                 int flags = PackageParser.PARSE_COLLECT_CERTIFICATES;
-                if ((params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
+                if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
                     flags |= PackageParser.PARSE_IS_EPHEMERAL;
                 }
                 apk = PackageParser.parseApkLite(addedFile, flags);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0d63f72..8ef472e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -41,7 +41,7 @@
 import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
-import static android.content.pm.PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID;
+import static android.content.pm.PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
@@ -164,6 +164,7 @@
 import android.content.pm.PermissionInfo;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
+import android.content.pm.SELinuxUtil;
 import android.content.pm.ServiceInfo;
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.Signature;
@@ -421,8 +422,11 @@
     static final int SCAN_CHECK_ONLY = 1<<13;
     static final int SCAN_DONT_KILL_APP = 1<<14;
     static final int SCAN_IGNORE_FROZEN = 1<<15;
-    static final int REMOVE_CHATTY = 1<<16;
-    static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1<<17;
+    static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1<<16;
+    static final int SCAN_AS_INSTANT_APP = 1<<17;
+    static final int SCAN_AS_FULL_APP = 1<<18;
+    /** Should not be with the scan flags */
+    static final int FLAGS_REMOVE_CHATTY = 1<<31;
 
     private static final String STATIC_SHARED_LIB_DELIMITER = "_";
 
@@ -626,7 +630,6 @@
 
     /** Directory where installed third-party apps stored */
     final File mAppInstallDir;
-    final File mEphemeralInstallDir;
 
     /**
      * Directory to which applications installed internally have their
@@ -1779,28 +1782,32 @@
             // the first time vs. those who are seeing an update.
             int[] firstUsers = EMPTY_INT_ARRAY;
             int[] updateUsers = EMPTY_INT_ARRAY;
-            if (res.origUsers == null || res.origUsers.length == 0) {
-                firstUsers = res.newUsers;
-            } else {
-                for (int newUser : res.newUsers) {
-                    boolean isNew = true;
-                    for (int origUser : res.origUsers) {
-                        if (origUser == newUser) {
-                            isNew = false;
-                            break;
-                        }
+            final boolean allNewUsers = res.origUsers == null || res.origUsers.length == 0;
+            final PackageSetting ps = (PackageSetting) res.pkg.mExtras;
+            for (int newUser : res.newUsers) {
+                if (ps.getInstantApp(newUser)) {
+                    continue;
+                }
+                if (allNewUsers) {
+                    firstUsers = ArrayUtils.appendInt(firstUsers, newUser);
+                    continue;
+                }
+                boolean isNew = true;
+                for (int origUser : res.origUsers) {
+                    if (origUser == newUser) {
+                        isNew = false;
+                        break;
                     }
-                    if (isNew) {
-                        firstUsers = ArrayUtils.appendInt(firstUsers, newUser);
-                    } else {
-                        updateUsers = ArrayUtils.appendInt(updateUsers, newUser);
-                    }
+                }
+                if (isNew) {
+                    firstUsers = ArrayUtils.appendInt(firstUsers, newUser);
+                } else {
+                    updateUsers = ArrayUtils.appendInt(updateUsers, newUser);
                 }
             }
 
-            // Send installed broadcasts if the install/update is not ephemeral
-            // and the package is not a static shared lib.
-            if (!isEphemeral(res.pkg) && res.pkg.staticSharedLibName == null) {
+            // Send installed broadcasts if the package is not a static shared lib.
+            if (res.pkg.staticSharedLibName == null) {
                 mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath);
 
                 // Send added for users that see the package for the first time
@@ -1887,16 +1894,14 @@
                 }
             }
 
-            if (!isEphemeral(res.pkg)) {
-                // Notify DexManager that the package was installed for new users.
-                // The updated users should already be indexed and the package code paths
-                // should not change.
-                // Don't notify the manager for ephemeral apps as they are not expected to
-                // survive long enough to benefit of background optimizations.
-                for (int userId : firstUsers) {
-                    PackageInfo info = getPackageInfo(packageName, /*flags*/ 0, userId);
-                    mDexManager.notifyPackageInstalled(info, userId);
-                }
+            // Notify DexManager that the package was installed for new users.
+            // The updated users should already be indexed and the package code paths
+            // should not change.
+            // Don't notify the manager for ephemeral apps as they are not expected to
+            // survive long enough to benefit of background optimizations.
+            for (int userId : firstUsers) {
+                PackageInfo info = getPackageInfo(packageName, /*flags*/ 0, userId);
+                mDexManager.notifyPackageInstalled(info, userId);
             }
         }
 
@@ -2285,7 +2290,6 @@
             File dataDir = Environment.getDataDirectory();
             mAppInstallDir = new File(dataDir, "app");
             mAppLib32InstallDir = new File(dataDir, "app-lib");
-            mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
             mAsecInternalPath = new File(dataDir, "app-asec").getPath();
             mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
             sUserManager = new UserManagerService(context, this,
@@ -2589,10 +2593,6 @@
                         | PackageParser.PARSE_FORWARD_LOCK,
                         scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
-                scanDirLI(mEphemeralInstallDir, mDefParseFlags
-                        | PackageParser.PARSE_IS_EPHEMERAL,
-                        scanFlags | SCAN_REQUIRE_KNOWN, 0);
-
                 /**
                  * Remove disable package settings for any updated system
                  * apps that were removed via an OTA. If they're not a
@@ -3335,14 +3335,14 @@
                 && callingAppId != Process.ROOT_UID
                 && checkUidPermission(Manifest.permission.ACCESS_INSTANT_APPS,
                         Binder.getCallingUid()) != PackageManager.PERMISSION_GRANTED) {
-            final String ephemeralPackageName = getEphemeralPackageName(Binder.getCallingUid());
-            if (ephemeralPackageName != null) {
+            final String instantAppPackageName = getInstantAppPackageName(Binder.getCallingUid());
+            if (instantAppPackageName != null) {
                 // ephemeral apps can only get information on themselves
-                if (!ephemeralPackageName.equals(p.packageName)) {
+                if (!instantAppPackageName.equals(p.packageName)) {
                     return null;
                 }
             } else {
-                if (p.applicationInfo.isInstantApp()) {
+                if (ps.getInstantApp(userId)) {
                     // only get access to the ephemeral app if we've been granted access
                     if (!mInstantAppRegistry.isInstantAccessGranted(
                             userId, callingAppId, ps.appId)) {
@@ -3953,17 +3953,17 @@
             flags |= PackageManager.MATCH_SYSTEM_ONLY;
         }
         final int callingUid = Binder.getCallingUid();
-        if (callingUid == Process.SYSTEM_UID || callingUid == 0) {
-            // The system sees all components
-            flags |= PackageManager.MATCH_EPHEMERAL;
-        } else if (getEphemeralPackageName(callingUid) != null) {
+        if (getInstantAppPackageName(callingUid) != null) {
             // But, ephemeral apps see both ephemeral and exposed, non-ephemeral components
-            flags |= PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY;
-            flags |= PackageManager.MATCH_EPHEMERAL;
+            flags |= PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
+            flags |= PackageManager.MATCH_INSTANT;
         } else {
             // Otherwise, prevent leaking ephemeral components
-            flags &= ~PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY;
-            flags &= ~PackageManager.MATCH_EPHEMERAL;
+            flags &= ~PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
+            if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
+                // Unless called from the system process
+                flags &= ~PackageManager.MATCH_INSTANT;
+            }
         }
         return updateFlagsForComponent(flags, userId, cookie);
     }
@@ -4692,7 +4692,8 @@
                 return;
             }
 
-            if (pkg.applicationInfo.isInstantApp() && !bp.isInstant()) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps.getInstantApp(userId) && !bp.isInstant()) {
                 throw new SecurityException("Cannot grant non-ephemeral permission"
                         + name + " for package " + packageName);
             }
@@ -5741,8 +5742,7 @@
         List<PersistentPreferredActivity> pprefs = ppir != null
                 ? ppir.queryIntent(intent, resolvedType,
                         (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                        (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
-                        (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId)
+                        userId)
                 : null;
         if (pprefs != null && pprefs.size() > 0) {
             final int M = pprefs.size();
@@ -5814,8 +5814,7 @@
             List<PreferredActivity> prefs = pir != null
                     ? pir.queryIntent(intent, resolvedType,
                             (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                            (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
-                            (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId)
+                            userId)
                     : null;
             if (prefs != null && prefs.size() > 0) {
                 boolean changed = false;
@@ -5986,8 +5985,7 @@
             String resolvedType, int userId) {
         CrossProfileIntentResolver resolver = mSettings.mCrossProfileIntentResolvers.get(userId);
         if (resolver != null) {
-            return resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/,
-                    false /*visibleToEphemeral*/, false /*isInstant*/, userId);
+            return resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId);
         }
         return null;
     }
@@ -6006,16 +6004,17 @@
     }
 
     /**
-     * Returns the package name of the calling Uid if it's an ephemeral app. If it isn't
-     * ephemeral, returns {@code null}.
+     * Returns the package name of the calling Uid if it's an instant app. If it isn't
+     * instant, returns {@code null}.
      */
-    private String getEphemeralPackageName(int callingUid) {
+    private String getInstantAppPackageName(int callingUid) {
         final int appId = UserHandle.getAppId(callingUid);
         synchronized (mPackages) {
             final Object obj = mSettings.getUserIdLPr(appId);
             if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
-                return ps.pkg.applicationInfo.isInstantApp() ? ps.pkg.packageName : null;
+                final boolean isInstantApp = ps.getInstantApp(UserHandle.getUserId(callingUid));
+                return isInstantApp ? ps.pkg.packageName : null;
             }
         }
         return null;
@@ -6024,7 +6023,7 @@
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        final String ephemeralPkgName = getEphemeralPackageName(Binder.getCallingUid());
+        final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
         flags = updateFlagsForResolve(flags, userId, intent);
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */,
@@ -6046,14 +6045,14 @@
                 // an ephemeral application or 2) the calling package is ephemeral and the
                 // activity is not visible to ephemeral applications.
                 boolean matchEphemeral =
-                        (flags & PackageManager.MATCH_EPHEMERAL) != 0;
+                        (flags & PackageManager.MATCH_INSTANT) != 0;
                 boolean ephemeralVisibleOnly =
-                        (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
+                        (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
                 boolean blockResolution =
-                        (!matchEphemeral && ephemeralPkgName == null
+                        (!matchEphemeral && instantAppPkgName == null
                                 && (ai.applicationInfo.privateFlags
-                                        & ApplicationInfo.PRIVATE_FLAG_EPHEMERAL) != 0)
-                        || (ephemeralVisibleOnly && ephemeralPkgName != null
+                                        & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0)
+                        || (ephemeralVisibleOnly && instantAppPkgName != null
                                 && (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0);
                 if (!blockResolution) {
                     final ResolveInfo ri = new ResolveInfo();
@@ -6080,7 +6079,7 @@
                     List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1);
                     xpResult.add(xpResolveInfo);
                     return filterForEphemeral(
-                            filterIfNotSystemUser(xpResult, userId), ephemeralPkgName);
+                            filterIfNotSystemUser(xpResult, userId), instantAppPkgName);
                 }
 
                 // Check for results in the current profile.
@@ -6120,13 +6119,13 @@
                             // And we are not going to add emphemeral app, so we can return the
                             // result straight away.
                             result.add(xpDomainInfo.resolveInfo);
-                            return filterForEphemeral(result, ephemeralPkgName);
+                            return filterForEphemeral(result, instantAppPkgName);
                         }
                     } else if (result.size() <= 1 && !addEphemeral) {
                         // No result in parent user and <= 1 result in current profile, and we
                         // are not going to add emphemeral app, so we can return the result without
                         // further processing.
-                        return filterForEphemeral(result, ephemeralPkgName);
+                        return filterForEphemeral(result, instantAppPkgName);
                     }
                     // We have more than one candidate (combining results from current and parent
                     // profile), so we need filtering and sorting.
@@ -6140,7 +6139,7 @@
                     result = filterForEphemeral(filterIfNotSystemUser(
                             mActivities.queryIntentForPackage(
                                     intent, resolvedType, flags, pkg.activities, userId),
-                            userId), ephemeralPkgName);
+                            userId), instantAppPkgName);
                 } else {
                     // the caller wants to resolve for a particular package; however, there
                     // were no installed results, so, try to find an ephemeral result
@@ -6178,7 +6177,7 @@
         if (sortResult) {
             Collections.sort(result, mResolvePrioritySorter);
         }
-        return filterForEphemeral(result, ephemeralPkgName);
+        return filterForEphemeral(result, instantAppPkgName);
     }
 
     private static class CrossProfileDomainInfo {
@@ -7142,9 +7141,9 @@
             return false;
         }
         synchronized (mPackages) {
-            PackageParser.Package pkg = mPackages.get(packageName);
-            if (pkg != null) {
-                return pkg.applicationInfo.isInstantApp();
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps != null) {
+                return ps.getInstantApp(userId);
             }
         }
         return false;
@@ -7647,7 +7646,7 @@
      *  @throws PackageManagerException on a parse error.
      */
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg, File scanFile,
-            final int policyFlags, int scanFlags, long currentTime, UserHandle user)
+            final int policyFlags, int scanFlags, long currentTime, @Nullable UserHandle user)
             throws PackageManagerException {
         // If the package has children and this is the first dive in the function
         // we scan the package with the SCAN_CHECK_ONLY flag set to see whether all
@@ -7687,7 +7686,7 @@
      *  @throws PackageManagerException on a parse error.
      */
     private PackageParser.Package scanPackageInternalLI(PackageParser.Package pkg, File scanFile,
-            int policyFlags, int scanFlags, long currentTime, UserHandle user)
+            int policyFlags, int scanFlags, long currentTime, @Nullable UserHandle user)
             throws PackageManagerException {
         PackageSetting ps = null;
         PackageSetting updatedPkg;
@@ -7923,6 +7922,11 @@
         pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
         pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
 
+        final int userId = ((user == null) ? 0 : user.getIdentifier());
+        if (ps != null && ps.getInstantApp(userId)) {
+            scanFlags |= SCAN_AS_INSTANT_APP;
+        }
+
         // Note that we invoke the following method only if we are about to unpack an application
         PackageParser.Package scannedPkg = scanPackageLI(pkg, policyFlags, scanFlags
                 | SCAN_UPDATE_SIGNATURE, currentTime, user);
@@ -8860,7 +8864,7 @@
     }
 
     private PackageParser.Package scanPackageTracedLI(PackageParser.Package pkg,
-            final int policyFlags, int scanFlags, long currentTime, UserHandle user)
+            final int policyFlags, int scanFlags, long currentTime, @Nullable UserHandle user)
                     throws PackageManagerException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
         // If the package has children and this is the first dive in the function
@@ -8899,7 +8903,8 @@
     }
 
     private PackageParser.Package scanPackageLI(PackageParser.Package pkg, final int policyFlags,
-            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
+            int scanFlags, long currentTime, @Nullable UserHandle user)
+                    throws PackageManagerException {
         boolean success = false;
         try {
             final PackageParser.Package res = scanPackageDirtyLI(pkg, policyFlags, scanFlags,
@@ -8965,7 +8970,7 @@
     }
 
     private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
-            final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
+            final int policyFlags, final int scanFlags, long currentTime, @Nullable UserHandle user)
                     throws PackageManagerException {
         if (DEBUG_PACKAGE_SCANNING) {
             if ((policyFlags & PackageParser.PARSE_CHATTY) != 0)
@@ -9103,16 +9108,16 @@
             if (pkgSetting == null) {
                 final String parentPackageName = (pkg.parentPackage != null)
                         ? pkg.parentPackage.packageName : null;
-
+                final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
                 // REMOVE SharedUserSetting from method; update in a separate call
                 pkgSetting = Settings.createNewSetting(pkg.packageName, origPackage,
                         disabledPkgSetting, realName, suid, destCodeFile, destResourceFile,
                         pkg.applicationInfo.nativeLibraryRootDir, pkg.applicationInfo.primaryCpuAbi,
                         pkg.applicationInfo.secondaryCpuAbi, pkg.mVersionCode,
                         pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, user,
-                        true /*allowInstall*/, parentPackageName, pkg.getChildPackageNames(),
-                        UserManagerService.getInstance(), usesStaticLibraries,
-                        pkg.usesStaticLibrariesVersions);
+                        true /*allowInstall*/, instantApp, parentPackageName,
+                        pkg.getChildPackageNames(), UserManagerService.getInstance(),
+                        usesStaticLibraries, pkg.usesStaticLibrariesVersions);
                 // SIDE EFFECTS; updates system state; move elsewhere
                 if (origPackage != null) {
                     mSettings.addRenamedPackageLPw(pkg.packageName, origPackage.name);
@@ -9179,9 +9184,8 @@
             }
 
             if (mFoundPolicyFile) {
-                SELinuxMMAC.assignSeinfoValue(pkg);
+                SELinuxMMAC.assignSeInfoValue(pkg);
             }
-
             pkg.applicationInfo.uid = pkgSetting.appId;
             pkg.mExtras = pkgSetting;
 
@@ -9416,11 +9420,11 @@
                 }
             }
         } else {
+            final int userId = user == null ? 0 : user.getIdentifier();
             // Modify state for the given package setting
             commitPackageSettings(pkg, pkgSetting, user, scanFlags,
                     (policyFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/);
-            if (isEphemeral(pkg)) {
-                final int userId = user == null ? 0 : user.getIdentifier();
+            if (pkgSetting.getInstantApp(userId)) {
                 mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId);
             }
         }
@@ -9535,10 +9539,10 @@
                             "Packages declaring static-shared libs must target O SDK or higher");
                 }
 
-                // Package declaring static a shared lib cannot be ephemeral
-                if (pkg.applicationInfo.isInstantApp()) {
+                // Package declaring static a shared lib cannot be instant apps
+                if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
                     throw new PackageManagerException(
-                            "Packages declaring static-shared libs cannot be ephemeral");
+                            "Packages declaring static-shared libs cannot be instant apps");
                 }
 
                 // Package declaring static a shared lib cannot be renamed since the package
@@ -9781,7 +9785,6 @@
                     mPlatformPackage = pkg;
                     pkg.mVersionCode = mSdkVersion;
                     mAndroidApplication = pkg.applicationInfo;
-
                     if (!mResolverReplaced) {
                         mResolveActivity.applicationInfo = mAndroidApplication;
                         mResolveActivity.name = ResolverActivity.class.getName();
@@ -10070,10 +10073,10 @@
                 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
                 final String curPackageName = cur == null ? null : cur.info.packageName;
                 // Dont allow ephemeral apps to define new permission groups.
-                if (pkg.applicationInfo.isInstantApp()) {
+                if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
                     Slog.w(TAG, "Permission group " + pg.info.name + " from package "
                             + pg.info.packageName
-                            + " ignored: ephemeral apps cannot define new permission groups.");
+                            + " ignored: instant apps cannot define new permission groups.");
                     continue;
                 }
                 final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
@@ -10115,10 +10118,10 @@
                 PackageParser.Permission p = pkg.permissions.get(i);
 
                 // Dont allow ephemeral apps to define new permissions.
-                if (pkg.applicationInfo.isInstantApp()) {
+                if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
                     Slog.w(TAG, "Permission " + p.info.name + " from package "
                             + p.info.packageName
-                            + " ignored: ephemeral apps cannot define new permissions.");
+                            + " ignored: instant apps cannot define new permissions.");
                     continue;
                 }
 
@@ -11740,13 +11743,10 @@
     final class ActivityIntentResolver
             extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral, int userId) {
+                boolean defaultOnly, int userId) {
             if (!sUserManager.exists(userId)) return null;
-            mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0)
-                    | (visibleToEphemeral ? PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY : 0)
-                    | (isEphemeral ? PackageManager.MATCH_EPHEMERAL : 0);
-            return super.queryIntent(intent, resolvedType, defaultOnly, visibleToEphemeral,
-                    isEphemeral, userId);
+            mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
         }
 
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
@@ -11755,8 +11755,7 @@
             mFlags = flags;
             return super.queryIntent(intent, resolvedType,
                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
-                    (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId);
+                    userId);
         }
 
         public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
@@ -11767,9 +11766,6 @@
             }
             mFlags = flags;
             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final boolean vislbleToEphemeral =
-                    (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
-            final boolean isEphemeral = (flags & PackageManager.MATCH_EPHEMERAL) != 0;
             final int N = packageActivities.size();
             ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
                 new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
@@ -11784,8 +11780,7 @@
                     listCut.add(array);
                 }
             }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly,
-                    vislbleToEphemeral, isEphemeral, listCut, userId);
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
         }
 
         /**
@@ -12197,11 +12192,24 @@
             if (ps == null) {
                 return null;
             }
+            final PackageUserState userState = ps.readUserState(userId);
             ActivityInfo ai = PackageParser.generateActivityInfo(activity, mFlags,
-                    ps.readUserState(userId), userId);
+                    userState, userId);
             if (ai == null) {
                 return null;
             }
+            final boolean matchVisibleToInstantApp =
+                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            // throw out filters that aren't visible to ephemeral apps
+            if (matchVisibleToInstantApp
+                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+                return null;
+            }
+            // throw out ephemeral filters if we're not explicitly requesting them
+            if (!isInstantApp && userState.instantApp) {
+                return null;
+            }
             final ResolveInfo res = new ResolveInfo();
             res.activityInfo = ai;
             if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
@@ -12270,10 +12278,9 @@
     private final class ServiceIntentResolver
             extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral, int userId) {
+                boolean defaultOnly, int userId) {
             mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly, visibleToEphemeral,
-                    isEphemeral, userId);
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
         }
 
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
@@ -12282,8 +12289,7 @@
             mFlags = flags;
             return super.queryIntent(intent, resolvedType,
                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
-                    (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId);
+                    userId);
         }
 
         public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
@@ -12294,9 +12300,6 @@
             }
             mFlags = flags;
             final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final boolean vislbleToEphemeral =
-                    (flags&PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
-            final boolean isEphemeral = (flags&PackageManager.MATCH_EPHEMERAL) != 0;
             final int N = packageServices.size();
             ArrayList<PackageParser.ServiceIntentInfo[]> listCut =
                 new ArrayList<PackageParser.ServiceIntentInfo[]>(N);
@@ -12311,8 +12314,7 @@
                     listCut.add(array);
                 }
             }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly,
-                    vislbleToEphemeral, isEphemeral, listCut, userId);
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
         }
 
         public final void addService(PackageParser.Service s) {
@@ -12487,10 +12489,9 @@
     private final class ProviderIntentResolver
             extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral, int userId) {
+                boolean defaultOnly, int userId) {
             mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly, visibleToEphemeral,
-                    isEphemeral, userId);
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
         }
 
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
@@ -12500,8 +12501,7 @@
             mFlags = flags;
             return super.queryIntent(intent, resolvedType,
                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    (flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
-                    (flags & PackageManager.MATCH_EPHEMERAL) != 0, userId);
+                    userId);
         }
 
         public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
@@ -12513,9 +12513,6 @@
             }
             mFlags = flags;
             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final boolean isEphemeral = (flags&PackageManager.MATCH_EPHEMERAL) != 0;
-            final boolean vislbleToEphemeral =
-                    (flags&PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
             final int N = packageProviders.size();
             ArrayList<PackageParser.ProviderIntentInfo[]> listCut =
                     new ArrayList<PackageParser.ProviderIntentInfo[]>(N);
@@ -12530,8 +12527,7 @@
                     listCut.add(array);
                 }
             }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly,
-                    vislbleToEphemeral, isEphemeral, listCut, userId);
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
         }
 
         public final void addProvider(PackageParser.Provider p) {
@@ -13072,7 +13068,7 @@
             String installerPackageName, int installerUid, UserHandle user,
             Certificate[][] certificates) {
         if (DEBUG_EPHEMERAL) {
-            if ((sessionParams.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
+            if ((sessionParams.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
                 Slog.d(TAG, "Ephemeral install of " + packageName);
             }
         }
@@ -13287,7 +13283,8 @@
      * @hide
      */
     @Override
-    public int installExistingPackageAsUser(String packageName, int userId, int installReason) {
+    public int installExistingPackageAsUser(String packageName, int userId, int installFlags,
+            int installReason) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
                 null);
         PackageSetting pkgSetting;
@@ -13302,6 +13299,10 @@
         long callingId = Binder.clearCallingIdentity();
         try {
             boolean installed = false;
+            final boolean instantApp =
+                    (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
+            final boolean fullApp =
+                    (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
 
             // writer
             synchronized (mPackages) {
@@ -13316,7 +13317,11 @@
                     mSettings.writePackageRestrictionsLPr(userId);
                     mSettings.writeKernelMappingLPr(pkgSetting);
                     installed = true;
+                } else if (fullApp && pkgSetting.getInstantApp(userId)) {
+                    // upgrade app from instant to full; we don't allow app downgrade
+                    installed = true;
                 }
+                setInstantAppForUser(pkgSetting, userId, instantApp, fullApp);
             }
 
             if (installed) {
@@ -13338,6 +13343,29 @@
         return PackageManager.INSTALL_SUCCEEDED;
     }
 
+    void setInstantAppForUser(PackageSetting pkgSetting, int userId,
+            boolean instantApp, boolean fullApp) {
+        // no state specified; do nothing
+        if (!instantApp && !fullApp) {
+            return;
+        }
+        if (userId != UserHandle.USER_ALL) {
+            if (instantApp && !pkgSetting.getInstantApp(userId)) {
+                pkgSetting.setInstantApp(true /*instantApp*/, userId);
+            } else if (fullApp && pkgSetting.getInstantApp(userId)) {
+                pkgSetting.setInstantApp(false /*instantApp*/, userId);
+            }
+        } else {
+            for (int currentUserId : sUserManager.getUserIds()) {
+                if (instantApp && !pkgSetting.getInstantApp(currentUserId)) {
+                    pkgSetting.setInstantApp(true /*instantApp*/, currentUserId);
+                } else if (fullApp && pkgSetting.getInstantApp(currentUserId)) {
+                    pkgSetting.setInstantApp(false /*instantApp*/, currentUserId);
+                }
+            }
+        }
+    }
+
     boolean isUserRestricted(int userId, String restrictionKey) {
         Bundle restrictions = sUserManager.getUserRestrictions(userId);
         if (restrictions.getBoolean(restrictionKey, false)) {
@@ -13696,7 +13724,7 @@
             return false;
         }
         // Ephemeral apps don't get the full verification treatment
-        if ((installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
+        if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
             if (DEBUG_EPHEMERAL) {
                 Slog.d(TAG, "INSTALL_EPHEMERAL so skipping verification");
             }
@@ -14488,7 +14516,7 @@
 
             final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
             final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
-            final boolean ephemeral = (installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
+            final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
             PackageInfoLite pkgLite = null;
 
             if (onInt && onSd) {
@@ -14572,7 +14600,7 @@
                             if (DEBUG_EPHEMERAL) {
                                 Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");
                             }
-                            installFlags |= PackageManager.INSTALL_EPHEMERAL;
+                            installFlags |= PackageManager.INSTALL_INSTANT_APP;
                             installFlags &= ~(PackageManager.INSTALL_EXTERNAL
                                     |PackageManager.INSTALL_INTERNAL);
                         } else {
@@ -14906,7 +14934,7 @@
         }
 
         protected boolean isEphemeral() {
-            return (installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
+            return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
         }
 
         UserHandle getUser() {
@@ -14986,7 +15014,7 @@
             }
 
             try {
-                final boolean isEphemeral = (installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
+                final boolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
                 final File tempDir =
                         mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
                 codeFile = tempDir;
@@ -15813,7 +15841,7 @@
     private void replacePackageLIF(PackageParser.Package pkg, final int policyFlags, int scanFlags,
             UserHandle user, String installerPackageName, PackageInstalledInfo res,
             int installReason) {
-        final boolean isEphemeral = (policyFlags & PackageParser.PARSE_IS_EPHEMERAL) != 0;
+        final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
 
         final PackageParser.Package oldPackage;
         final String pkgName = pkg.packageName;
@@ -15837,17 +15865,17 @@
                 return;
             }
 
+            final PackageSetting ps = mSettings.mPackages.get(pkgName);
+
             // don't allow an upgrade from full to ephemeral
-            final boolean oldIsEphemeral = oldPackage.applicationInfo.isInstantApp();
-            if (isEphemeral && !oldIsEphemeral) {
-                // can't downgrade from full to ephemeral
-                Slog.w(TAG, "Can't replace app with ephemeral: " + pkgName);
-                res.setReturnCode(PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID);
+            if (isInstantApp && !ps.getInstantApp(user.getIdentifier())) {
+                // can't downgrade from full to instant
+                Slog.w(TAG, "Can't replace app with instant app: " + pkgName);
+                res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
                 return;
             }
 
             // verify signatures are valid
-            final PackageSetting ps = mSettings.mPackages.get(pkgName);
             if (shouldCheckUpgradeKeySetLP(ps, scanFlags)) {
                 if (!checkUpgradeKeySetLP(ps, pkg)) {
                     res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
@@ -16049,6 +16077,10 @@
                         childPs.oldCodePaths = ps.oldCodePaths;
                     }
                 }
+                // set instant app status, but, only if it's explicitly specified
+                final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
+                final boolean fullApp = (scanFlags & SCAN_AS_FULL_APP) != 0;
+                setInstantAppForUser(ps, user.getIdentifier(), instantApp, fullApp);
                 prepareAppDataAfterInstallLIF(newPackage);
                 addedPkg = true;
             } catch (PackageManagerException e) {
@@ -16520,7 +16552,8 @@
         final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
         final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
                 || (args.volumeUuid != null));
-        final boolean ephemeral = ((installFlags & PackageManager.INSTALL_EPHEMERAL) != 0);
+        final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
+        final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
         final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0);
         boolean replace = false;
         int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
@@ -16531,6 +16564,12 @@
         if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
             scanFlags |= SCAN_DONT_KILL_APP;
         }
+        if (instantApp) {
+            scanFlags |= SCAN_AS_INSTANT_APP;
+        }
+        if (fullApp) {
+            scanFlags |= SCAN_AS_FULL_APP;
+        }
 
         // Result object to be returned
         res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
@@ -16538,10 +16577,10 @@
         if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);
 
         // Sanity check
-        if (ephemeral && (forwardLocked || onExternal)) {
+        if (instantApp && (forwardLocked || onExternal)) {
             Slog.i(TAG, "Incompatible ephemeral install; fwdLocked=" + forwardLocked
                     + " external=" + onExternal);
-            res.setReturnCode(PackageManager.INSTALL_FAILED_EPHEMERAL_INVALID);
+            res.setReturnCode(PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID);
             return;
         }
 
@@ -16550,7 +16589,7 @@
                 | PackageParser.PARSE_ENFORCE_CODE
                 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
                 | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)
-                | (ephemeral ? PackageParser.PARSE_IS_EPHEMERAL : 0)
+                | (instantApp ? PackageParser.PARSE_IS_EPHEMERAL : 0)
                 | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0);
         PackageParser pp = new PackageParser();
         pp.setSeparateProcesses(mSeparateProcesses);
@@ -16569,7 +16608,7 @@
 
 //        // Ephemeral apps must have target SDK >= O.
 //        // TODO: Update conditional and error message when O gets locked down
-//        if (ephemeral && pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
+//        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;
@@ -16812,10 +16851,10 @@
                 res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                         "Cannot install updates to system apps on sdcard");
                 return;
-            } else if (ephemeral) {
-                // Abort update; system app can't be replaced with an ephemeral app
-                res.setError(INSTALL_FAILED_EPHEMERAL_INVALID,
-                        "Cannot update a system app with an ephemeral app");
+            } else if (instantApp) {
+                // Abort update; system app can't be replaced with an instant app
+                res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
+                        "Cannot update a system app with an instant app");
                 return;
             }
         }
@@ -17062,14 +17101,6 @@
         return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
     }
 
-    private static boolean isEphemeral(PackageParser.Package pkg) {
-        return pkg.applicationInfo.isInstantApp();
-    }
-
-    private static boolean isEphemeral(PackageSetting ps) {
-        return ps.pkg != null && isEphemeral(ps.pkg);
-    }
-
     private static boolean isSystemApp(PackageParser.Package pkg) {
         return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
@@ -17092,9 +17123,6 @@
 
     private int packageFlagsToInstallFlags(PackageSetting ps) {
         int installFlags = 0;
-        if (isEphemeral(ps)) {
-            installFlags |= PackageManager.INSTALL_EPHEMERAL;
-        }
         if (isExternal(ps) && TextUtils.isEmpty(ps.volumeUuid)) {
             // This existing package was an external ASEC install when we have
             // the external flag without a UUID
@@ -17496,7 +17524,7 @@
             try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser,
                     deleteFlags, "deletePackageX")) {
                 res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
-                        deleteFlags | REMOVE_CHATTY, info, true, null);
+                        deleteFlags | FLAGS_REMOVE_CHATTY, info, true, null);
             }
             synchronized (mPackages) {
                 if (res) {
@@ -17646,7 +17674,7 @@
             }
         }
 
-        removePackageLI(ps, (flags & REMOVE_CHATTY) != 0);
+        removePackageLI(ps, (flags & FLAGS_REMOVE_CHATTY) != 0);
 
         if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
             final PackageParser.Package resolvedPkg;
@@ -18205,11 +18233,18 @@
                 Slog.d(TAG, "Marking package:" + ps.name + " uninstalled for user:" + nextUserId);
             }
             ps.setUserState(nextUserId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
-                    false /*installed*/, true /*stopped*/, true /*notLaunched*/,
-                    false /*hidden*/, false /*suspended*/, null, null, null,
+                    false /*installed*/,
+                    true /*stopped*/,
+                    true /*notLaunched*/,
+                    false /*hidden*/,
+                    false /*suspended*/,
+                    false /*instantApp*/,
+                    null /*lastDisableAppCaller*/,
+                    null /*enabledComponents*/,
+                    null /*disabledComponents*/,
                     false /*blockUninstall*/,
-                    ps.readUserState(nextUserId).domainVerificationStatus, 0,
-                    PackageManager.INSTALL_REASON_UNKNOWN);
+                    ps.readUserState(nextUserId).domainVerificationStatus,
+                    0, PackageManager.INSTALL_REASON_UNKNOWN);
         }
         mSettings.writeKernelMappingLPr(ps);
     }
@@ -21691,12 +21726,12 @@
         final ApplicationInfo app = pkg.applicationInfo;
         final int appId = UserHandle.getAppId(app.uid);
 
-        Preconditions.checkNotNull(app.seinfo);
+        Preconditions.checkNotNull(app.seInfo);
 
         long ceDataInode = -1;
         try {
             ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
-                    appId, app.seinfo, app.targetSdkVersion);
+                    appId, app.seInfo, app.targetSdkVersion);
         } catch (InstallerException e) {
             if (app.isSystemApp()) {
                 logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName
@@ -21704,7 +21739,7 @@
                 destroyAppDataLeafLIF(pkg, userId, flags);
                 try {
                     ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
-                            appId, app.seinfo, app.targetSdkVersion);
+                            appId, app.seInfo, app.targetSdkVersion);
                     logCriticalInfo(Log.DEBUG, "Recovery succeeded!");
                 } catch (InstallerException e2) {
                     logCriticalInfo(Log.DEBUG, "Recovery failed!");
@@ -22006,7 +22041,7 @@
             installerPackageName = ps.installerPackageName;
             packageAbiOverride = ps.cpuAbiOverrideString;
             appId = UserHandle.getAppId(pkg.applicationInfo.uid);
-            seinfo = pkg.applicationInfo.seinfo;
+            seinfo = pkg.applicationInfo.seInfo;
             label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
             targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
             freezer = freezePackage(packageName, "movePackageInternal");
@@ -22815,8 +22850,8 @@
         @Override
         public boolean isPackageEphemeral(int userId, String packageName) {
             synchronized (mPackages) {
-                PackageParser.Package p = mPackages.get(packageName);
-                return p != null ? p.applicationInfo.isInstantApp() : false;
+                final PackageSetting ps = mSettings.mPackages.get(packageName);
+                return ps != null ? ps.getInstantApp(userId) : false;
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 1203e4d..a7349fc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -39,6 +39,7 @@
 import android.content.pm.PermissionInfo;
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageInstaller.SessionParams;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.VersionedPackage;
 import android.content.res.AssetManager;
@@ -116,6 +117,8 @@
                     return runInstallRemove();
                 case "install-write":
                     return runInstallWrite();
+                case "install-existing":
+                    return runInstallExisting();
                 case "compile":
                     return runCompile();
                 case "reconcile-secondary-dex-files":
@@ -301,6 +304,51 @@
         return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
     }
 
+    private int runInstallExisting() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        int userId = UserHandle.USER_SYSTEM;
+        int installFlags = 0;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                case "--ephemeral":
+                case "--instant":
+                    installFlags |= PackageManager.INSTALL_INSTANT_APP;
+                    installFlags &= ~PackageManager.INSTALL_FULL_APP;
+                    break;
+                case "--full":
+                    installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
+                    installFlags |= PackageManager.INSTALL_FULL_APP;
+                    break;
+                default:
+                    pw.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+
+        final String packageName = getNextArg();
+        if (packageName == null) {
+            pw.println("Error: package name not specified");
+            return 1;
+        }
+
+        try {
+            final int res = mInterface.installExistingPackageAsUser(packageName, userId,
+                    installFlags, PackageManager.INSTALL_REASON_UNKNOWN);
+            if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
+                throw new NameNotFoundException("Package " + packageName + " doesn't exist");
+            }
+            pw.println("Package " + packageName + " installed for user: " + userId);
+            return 0;
+        } catch (RemoteException | NameNotFoundException e) {
+            pw.println(e.toString());
+            return 1;
+        }
+    }
+
     private int runCompile() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         boolean checkProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
@@ -1145,8 +1193,12 @@
                     sessionParams.abiOverride = checkAbiArgument(getNextArg());
                     break;
                 case "--ephemeral":
+                case "--instantapp":
                     sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);
                     break;
+                case "--full":
+                    sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
+                    break;
                 case "--user":
                     params.userId = UserHandle.parseUserArg(getNextArgRequired());
                     break;
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 0e11b0c..601377d6 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -397,11 +397,19 @@
         modifyUserState(userId).blockUninstall = blockUninstall;
     }
 
+    boolean getInstantApp(int userId) {
+        return readUserState(userId).instantApp;
+    }
+
+    void setInstantApp(boolean instantApp, int userId) {
+        modifyUserState(userId).instantApp = instantApp;
+    }
+
     void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
-            boolean notLaunched, boolean hidden, boolean suspended,
+            boolean notLaunched, boolean hidden, boolean suspended, boolean instantApp,
             String lastDisableAppCaller, ArraySet<String> enabledComponents,
-            ArraySet<String> disabledComponents, boolean blockUninstall, int domainVerifState,
-            int linkGeneration, int installReason) {
+            ArraySet<String> disabledComponents, boolean blockUninstall,
+            int domainVerifState, int linkGeneration, int installReason) {
         PackageUserState state = modifyUserState(userId);
         state.ceDataInode = ceDataInode;
         state.enabled = enabled;
@@ -417,6 +425,7 @@
         state.domainVerificationStatus = domainVerifState;
         state.appLinkGeneration = linkGeneration;
         state.installReason = installReason;
+        state.instantApp = instantApp;
     }
 
     ArraySet<String> getEnabledComponents(int userId) {
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 7e7de21..188e66f 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -17,6 +17,8 @@
 package com.android.server.pm;
 
 import android.content.pm.PackageParser;
+import android.content.pm.PackageUserState;
+import android.content.pm.SELinuxUtil;
 import android.content.pm.Signature;
 import android.os.Environment;
 import android.util.Slog;
@@ -69,9 +71,6 @@
     // Append v2 to existing seinfo label
     private static final String SANDBOX_V2_STR = ":v2";
 
-    // Append ephemeral to existing seinfo label
-    private static final String EPHEMERAL_APP_STR = ":ephemeralapp";
-
     // Append targetSdkVersion=n to existing seinfo label where n is the app's targetSdkVersion
     private static final String TARGETSDKVERSION_STR = ":targetSdkVersion=";
 
@@ -279,31 +278,28 @@
      *
      * @param pkg object representing the package to be labeled.
      */
-    public static void assignSeinfoValue(PackageParser.Package pkg) {
+    public static void assignSeInfoValue(PackageParser.Package pkg) {
         synchronized (sPolicies) {
             for (Policy policy : sPolicies) {
-                String seinfo = policy.getMatchedSeinfo(pkg);
-                if (seinfo != null) {
-                    pkg.applicationInfo.seinfo = seinfo;
+                String seInfo = policy.getMatchedSeInfo(pkg);
+                if (seInfo != null) {
+                    pkg.applicationInfo.seInfo = seInfo;
                     break;
                 }
             }
         }
 
-        if (pkg.applicationInfo.isInstantApp())
-            pkg.applicationInfo.seinfo += EPHEMERAL_APP_STR;
-
         if (pkg.applicationInfo.targetSandboxVersion == 2)
-            pkg.applicationInfo.seinfo += SANDBOX_V2_STR;
+            pkg.applicationInfo.seInfo += SANDBOX_V2_STR;
 
         if (pkg.applicationInfo.isPrivilegedApp())
-            pkg.applicationInfo.seinfo += PRIVILEGED_APP_STR;
+            pkg.applicationInfo.seInfo += PRIVILEGED_APP_STR;
 
-        pkg.applicationInfo.seinfo += TARGETSDKVERSION_STR + pkg.applicationInfo.targetSdkVersion;
+        pkg.applicationInfo.seInfo += TARGETSDKVERSION_STR + pkg.applicationInfo.targetSdkVersion;
 
         if (DEBUG_POLICY_INSTALL) {
             Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " +
-                    "seinfo=" + pkg.applicationInfo.seinfo);
+                    "seinfo=" + pkg.applicationInfo.seInfo);
         }
     }
 }
@@ -438,7 +434,7 @@
      * @return A string representing the seinfo matched during policy lookup.
      *         A value of null can also be returned if no match occured.
      */
-    public String getMatchedSeinfo(PackageParser.Package pkg) {
+    public String getMatchedSeInfo(PackageParser.Package pkg) {
         // Check for exact signature matches across all certs.
         Signature[] certs = mCerts.toArray(new Signature[0]);
         if (!Signature.areExactMatch(certs, pkg.mSignatures)) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6156802..a8a5ff0 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -219,6 +219,7 @@
     private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
     private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
     private static final String ATTR_INSTALL_REASON = "install-reason";
+    private static final String ATTR_INSTANT_APP = "instant-app";
 
     private static final String ATTR_PACKAGE_NAME = "packageName";
     private static final String ATTR_FINGERPRINT = "fingerprint";
@@ -687,7 +688,7 @@
             PackageSetting disabledPkg, String realPkgName, SharedUserSetting sharedUser,
             File codePath, File resourcePath, String legacyNativeLibraryPath, String primaryCpuAbi,
             String secondaryCpuAbi, int versionCode, int pkgFlags, int pkgPrivateFlags,
-            UserHandle installUser, boolean allowInstall, String parentPkgName,
+            UserHandle installUser, boolean allowInstall, boolean instantApp, String parentPkgName,
             List<String> childPkgNames, UserManagerService userManager,
             String[] usesStaticLibraries, int[] usesStaticLibrariesVersions) {
         final PackageSetting pkgSetting;
@@ -745,14 +746,17 @@
                                 || installUserId == user.id;
                         pkgSetting.setUserState(user.id, 0, COMPONENT_ENABLED_STATE_DEFAULT,
                                 installed,
-                                true, // stopped,
-                                true, // notLaunched
-                                false, // hidden
-                                false, // suspended
-                                null, null, null,
-                                false, // blockUninstall
-                                INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
-                                PackageManager.INSTALL_REASON_UNKNOWN);
+                                true /*stopped*/,
+                                true /*notLaunched*/,
+                                false /*hidden*/,
+                                false /*suspended*/,
+                                instantApp,
+                                null /*lastDisableAppCaller*/,
+                                null /*enabledComponents*/,
+                                null /*disabledComponents*/,
+                                false /*blockUninstall*/,
+                                INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED,
+                                0, PackageManager.INSTALL_REASON_UNKNOWN);
                     }
                 }
             }
@@ -1643,15 +1647,18 @@
                     // consider all applications to be installed.
                     for (PackageSetting pkg : mPackages.values()) {
                         pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
-                                true,   // installed
-                                false,  // stopped
-                                false,  // notLaunched
-                                false,  // hidden
-                                false,  // suspended
-                                null, null, null,
-                                false, // blockUninstall
-                                INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
-                                PackageManager.INSTALL_REASON_UNKNOWN);
+                                true  /*installed*/,
+                                false /*stopped*/,
+                                false /*notLaunched*/,
+                                false /*hidden*/,
+                                false /*suspended*/,
+                                false /*instantApp*/,
+                                null /*lastDisableAppCaller*/,
+                                null /*enabledComponents*/,
+                                null /*disabledComponents*/,
+                                false /*blockUninstall*/,
+                                INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED,
+                                0, PackageManager.INSTALL_REASON_UNKNOWN);
                     }
                     return;
                 }
@@ -1718,6 +1725,8 @@
                             false);
                     final boolean blockUninstall = XmlUtils.readBooleanAttribute(parser,
                             ATTR_BLOCK_UNINSTALL, false);
+                    final boolean instantApp = XmlUtils.readBooleanAttribute(parser,
+                            ATTR_INSTANT_APP, false);
                     final int enabled = XmlUtils.readIntAttribute(parser, ATTR_ENABLED,
                             COMPONENT_ENABLED_STATE_DEFAULT);
                     final String enabledCaller = parser.getAttributeValue(null,
@@ -1754,8 +1763,9 @@
                     }
 
                     ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
-                            hidden, suspended, enabledCaller, enabledComponents, disabledComponents,
-                            blockUninstall, verifState, linkGeneration, installReason);
+                            hidden, suspended, instantApp, enabledCaller, enabledComponents,
+                            disabledComponents, blockUninstall, verifState, linkGeneration,
+                            installReason);
                 } else if (tagName.equals("preferred-activities")) {
                     readPreferredActivitiesLPw(parser, userId);
                 } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
@@ -2025,6 +2035,9 @@
                 if (ustate.blockUninstall) {
                     serializer.attribute(null, ATTR_BLOCK_UNINSTALL, "true");
                 }
+                if (ustate.instantApp) {
+                    serializer.attribute(null, ATTR_INSTANT_APP, "true");
+                }
                 if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
                     serializer.attribute(null, ATTR_ENABLED,
                             Integer.toString(ustate.enabled));
@@ -2682,7 +2695,7 @@
                 sb.append(isDebug ? " 1 " : " 0 ");
                 sb.append(dataPath);
                 sb.append(" ");
-                sb.append(ai.seinfo);
+                sb.append(ai.seInfo);
                 sb.append(" ");
                 if (gids != null && gids.length > 0) {
                     sb.append(gids[0]);
@@ -4140,7 +4153,7 @@
                 volumeUuids[i] = ps.volumeUuid;
                 names[i] = ps.name;
                 appIds[i] = ps.appId;
-                seinfos[i] = ps.pkg.applicationInfo.seinfo;
+                seinfos[i] = ps.pkg.applicationInfo.seInfo;
                 targetSdkVersions[i] = ps.pkg.applicationInfo.targetSdkVersion;
             }
         }
@@ -4429,7 +4442,7 @@
         ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE, "DEFAULT_TO_DEVICE_PROTECTED_STORAGE",
         ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE, "DIRECT_BOOT_AWARE",
         ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE, "PARTIALLY_DIRECT_BOOT_AWARE",
-        ApplicationInfo.PRIVATE_FLAG_EPHEMERAL, "EPHEMERAL",
+        ApplicationInfo.PRIVATE_FLAG_INSTANT, "EPHEMERAL",
         ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
         ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET, "RESIZEABLE_ACTIVITIES_EXPLICITLY_SET",
         ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION, "RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION",
@@ -4502,6 +4515,7 @@
                 pw.print(ps.getSuspended(user.id) ? "SU" : "su");
                 pw.print(ps.getStopped(user.id) ? "S" : "s");
                 pw.print(ps.getNotLaunched(user.id) ? "l" : "L");
+                pw.print(ps.getInstantApp(user.id) ? "IA" : "ia");
                 pw.print(",");
                 pw.print(ps.getEnabled(user.id));
                 String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
@@ -4755,6 +4769,8 @@
             pw.print(ps.getNotLaunched(user.id));
             pw.print(" enabled=");
             pw.println(ps.getEnabled(user.id));
+            pw.print(" instant=");
+            pw.println(ps.getInstantApp(user.id));
             String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
             if (lastDisabledAppCaller != null) {
                 pw.print(prefix); pw.print("    lastDisabledCaller: ");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2b2bb48..ba8f7e9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -7863,7 +7863,7 @@
                 // Install the profile owner if not present.
                 if (!mIPackageManager.isPackageAvailable(adminPkg, userHandle)) {
                     mIPackageManager.installExistingPackageAsUser(adminPkg, userHandle,
-                            PackageManager.INSTALL_REASON_POLICY);
+                            0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY);
                 }
             } catch (RemoteException e) {
                 Slog.e(LOG_TAG, "Failed to make remote calls for createAndManageUser, "
@@ -8182,7 +8182,7 @@
 
                 // Install the app.
                 mIPackageManager.installExistingPackageAsUser(packageName, userId,
-                        PackageManager.INSTALL_REASON_POLICY);
+                        0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY);
 
             } catch (RemoteException re) {
                 // shouldn't happen
@@ -8224,7 +8224,7 @@
                             if (isSystemApp(mIPackageManager, packageName, parentUserId)) {
                                 numberOfAppsInstalled++;
                                 mIPackageManager.installExistingPackageAsUser(packageName, userId,
-                                        PackageManager.INSTALL_REASON_POLICY);
+                                        0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY);
                             } else {
                                 Slog.d(LOG_TAG, "Not enabling " + packageName + " since is not a"
                                         + " system app");
diff --git a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
index 3fa72dc..90c58d0 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
@@ -104,7 +104,7 @@
         }
         try {
             mPackageManager.installExistingPackageAsUser(packageName, userId,
-                    PackageManager.INSTALL_REASON_UNKNOWN);
+                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } finally {
@@ -175,4 +175,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index db010b8..88f1a53 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -280,6 +280,21 @@
 
     @Test
     @UiThreadTest
+    public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
+        mBinderService.enqueueNotificationWithTag(mContext.getPackageName(), "opPkg", "tag", 0,
+                generateNotificationRecord(null).getNotification(), new int[1], 0);
+        waitForIdle();
+        mBinderService.enqueueNotificationWithTag(mContext.getPackageName(), "opPkg", "tag", 0,
+                generateNotificationRecord(null).getNotification(), new int[1], 0);
+        mBinderService.cancelNotificationWithTag(mContext.getPackageName(), "tag", 0, 0);
+        waitForIdle();
+        StatusBarNotification[] notifs =
+                mBinderService.getActiveNotifications(mContext.getPackageName());
+        assertEquals(0, notifs.length);
+    }
+
+    @Test
+    @UiThreadTest
     public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), "opPkg", "tag",
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index e2e1844..100338e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -1053,7 +1053,7 @@
             ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
         }
         if (mEphemeralPackages.contains(PackageWithUser.of(userId, packageName))) {
-            ret.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_EPHEMERAL;
+            ret.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
         }
         if (mSystemPackages.contains(packageName)) {
             ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index baf60c5..325d99a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -388,6 +388,7 @@
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
                 null /*installUser*/,
                 false /*allowInstall*/,
+                false /*instantApp*/,
                 null /*parentPkgName*/,
                 null /*childPkgNames*/,
                 UserManagerService.getInstance(),
@@ -428,6 +429,7 @@
                 0 /*pkgPrivateFlags*/,
                 UserHandle.SYSTEM /*installUser*/,
                 true /*allowInstall*/,
+                false /*instantApp*/,
                 null /*parentPkgName*/,
                 null /*childPkgNames*/,
                 UserManagerService.getInstance(),
@@ -471,6 +473,7 @@
                 0 /*pkgPrivateFlags*/,
                 null /*installUser*/,
                 false /*allowInstall*/,
+                false /*instantApp*/,
                 null /*parentPkgName*/,
                 null /*childPkgNames*/,
                 UserManagerService.getInstance(),
@@ -514,6 +517,7 @@
                 0 /*pkgPrivateFlags*/,
                 null /*installUser*/,
                 false /*allowInstall*/,
+                false /*instantApp*/,
                 null /*parentPkgName*/,
                 null /*childPkgNames*/,
                 UserManagerService.getInstance(),
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index e5640c7..5591029 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -380,7 +380,7 @@
         assertTrue(Arrays.equals(a.splitSourceDirs, that.splitSourceDirs));
         assertTrue(Arrays.equals(a.splitPublicSourceDirs, that.splitPublicSourceDirs));
         assertTrue(Arrays.equals(a.resourceDirs, that.resourceDirs));
-        assertEquals(a.seinfo, that.seinfo);
+        assertEquals(a.seInfo, that.seInfo);
         assertTrue(Arrays.equals(a.sharedLibraryFiles, that.sharedLibraryFiles));
         assertEquals(a.dataDir, that.dataDir);
         assertEquals(a.deviceProtectedDataDir, that.deviceProtectedDataDir);
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
index 346dc42..a8c39c4 100644
--- a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
@@ -104,7 +104,7 @@
                     null, null);
             // Verify that we try to install the package in system user.
             verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
-                    PackageManager.INSTALL_REASON_UNKNOWN);
+                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
         }
         assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
                 "1",
@@ -141,7 +141,7 @@
                     null, null);
             // Verify that we try to install the package in system user.
             verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
-                    PackageManager.INSTALL_REASON_UNKNOWN);
+                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
         }
         assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
                 "1",