Move hidden ApplicationInfo flags into a separate field.

The public API field android.content.pm.ApplicationInfo.flags can
support only 32 flags. This limit has been reached. As a short term
workaround to enable new public flags to be added, this CL moves flags
which are not public API into a separate new field privateFlags and
renames the affected flags constants accordingly (e.g., FLAG_PRIVILEGED
is now PRIVATE_FLAG_PRIVILEGED).

The new privateFlags field is not public API and should not be used
for flags that are public API.

The flags that are moved out of ApplicationInfo.flags are:
* FLAG_HIDDEN,
* FLAG_CANT_SAVE_STATE,
* FLAG_FORWARD_LOCK, and
* FLAG_PRIVILEGED.

NOTE: This changes the format of packages.xml. Prior to this CL flags
were stored in the "flags" attribute. With this CL, the public flags
are stored in a new "publicFlags" attribute and private flags are
stored in a new "privateFlags" attribute. The old "flags" attribute
is interpreted by using the old values of hidden/private flags.

Change-Id: Ie23eb8ddd5129de3c6e008c5261b639e22182ee5
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index e07edba..e822708 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -334,44 +334,6 @@
     public static final int FLAG_FULL_BACKUP_ONLY = 1<<26;
 
     /**
-     * Value for {@link #flags}: true if the application is hidden via restrictions and for
-     * most purposes is considered as not installed.
-     * {@hide}
-     */
-    public static final int FLAG_HIDDEN = 1<<27;
-
-    /**
-     * Value for {@link #flags}: set to <code>true</code> if the application
-     * has reported that it is heavy-weight, and thus can not participate in
-     * the normal application lifecycle.
-     *
-     * <p>Comes from the
-     * android.R.styleable#AndroidManifestApplication_cantSaveState
-     * attribute of the &lt;application&gt; tag.
-     *
-     * {@hide}
-     */
-    public static final int FLAG_CANT_SAVE_STATE = 1<<28;
-
-    /**
-     * Value for {@link #flags}: Set to true if the application has been
-     * installed using the forward lock option.
-     *
-     * NOTE: DO NOT CHANGE THIS VALUE!  It is saved in packages.xml.
-     * 
-     * {@hide}
-     */
-    public static final int FLAG_FORWARD_LOCK = 1<<29;
-
-    /**
-     * Value for {@link #flags}: set to {@code true} if the application
-     * is permitted to hold privileged permissions.
-     *
-     * {@hide}
-     */
-    public static final int FLAG_PRIVILEGED = 1<<30;
-
-    /**
      * Value for {@link #flags}: true if code from this application will need to be
      * loaded into other applications' processes. On devices that support multiple
      * instruction sets, this implies the code might be loaded into a process that's
@@ -395,11 +357,60 @@
      * {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_SUPPORTS_XLARGE_SCREENS},
      * {@link #FLAG_RESIZEABLE_FOR_SCREENS},
      * {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE},
-     * {@link #FLAG_INSTALLED}, {@link #FLAG_IS_GAME}.
+     * {@link #FLAG_ALLOW_BACKUP}, {@link #FLAG_KILL_AFTER_RESTORE},
+     * {@link #FLAG_RESTORE_ANY_VERSION}, {@link #FLAG_EXTERNAL_STORAGE},
+     * {@link #FLAG_LARGE_HEAP}, {@link #FLAG_STOPPED},
+     * {@link #FLAG_SUPPORTS_RTL}, {@link #FLAG_INSTALLED},
+     * {@link #FLAG_IS_DATA_ONLY}, {@link #FLAG_IS_GAME},
+     * {@link #FLAG_FULL_BACKUP_ONLY}, {@link #FLAG_MULTIARCH}.
      */
     public int flags = 0;
 
     /**
+     * Value for {@link #privateFlags}: true if the application is hidden via restrictions and for
+     * most purposes is considered as not installed.
+     * {@hide}
+     */
+    public static final int PRIVATE_FLAG_HIDDEN = 1<<0;
+
+    /**
+     * Value for {@link #privateFlags}: set to <code>true</code> if the application
+     * has reported that it is heavy-weight, and thus can not participate in
+     * the normal application lifecycle.
+     *
+     * <p>Comes from the
+     * android.R.styleable#AndroidManifestApplication_cantSaveState
+     * attribute of the &lt;application&gt; tag.
+     *
+     * {@hide}
+     */
+    public static final int PRIVATE_FLAG_CANT_SAVE_STATE = 1<<1;
+
+    /**
+     * Value for {@link #privateFlags}: Set to true if the application has been
+     * installed using the forward lock option.
+     *
+     * NOTE: DO NOT CHANGE THIS VALUE!  It is saved in packages.xml.
+     *
+     * {@hide}
+     */
+    public static final int PRIVATE_FLAG_FORWARD_LOCK = 1<<2;
+
+    /**
+     * Value for {@link #privateFlags}: set to {@code true} if the application
+     * is permitted to hold privileged permissions.
+     *
+     * {@hide}
+     */
+    public static final int PRIVATE_FLAG_PRIVILEGED = 1<<3;
+
+    /**
+     * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
+     * {@hide}
+     */
+    public int privateFlags;
+
+    /**
      * The required smallest screen width the application can run on.  If 0,
      * nothing has been specified.  Comes from
      * {@link android.R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp
@@ -598,6 +609,7 @@
         pw.println(prefix + "processName=" + processName);
         pw.println(prefix + "taskAffinity=" + taskAffinity);
         pw.println(prefix + "uid=" + uid + " flags=0x" + Integer.toHexString(flags)
+                + " privateFlags=0x" + Integer.toHexString(privateFlags)
                 + " theme=0x" + Integer.toHexString(theme));
         pw.println(prefix + "requiresSmallestWidthDp=" + requiresSmallestWidthDp
                 + " compatibleWidthLimitDp=" + compatibleWidthLimitDp
@@ -680,6 +692,7 @@
         className = orig.className;
         theme = orig.theme;
         flags = orig.flags;
+        privateFlags = orig.privateFlags;
         requiresSmallestWidthDp = orig.requiresSmallestWidthDp;
         compatibleWidthLimitDp = orig.compatibleWidthLimitDp;
         largestWidthLimitDp = orig.largestWidthLimitDp;
@@ -730,6 +743,7 @@
         dest.writeString(className);
         dest.writeInt(theme);
         dest.writeInt(flags);
+        dest.writeInt(privateFlags);
         dest.writeInt(requiresSmallestWidthDp);
         dest.writeInt(compatibleWidthLimitDp);
         dest.writeInt(largestWidthLimitDp);
@@ -779,6 +793,7 @@
         className = source.readString();
         theme = source.readInt();
         flags = source.readInt();
+        privateFlags = source.readInt();
         requiresSmallestWidthDp = source.readInt();
         compatibleWidthLimitDp = source.readInt();
         largestWidthLimitDp = source.readInt();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c37534a..b37713a 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -111,6 +111,8 @@
 
     int getFlagsForUid(int uid);
 
+    int getPrivateFlagsForUid(int uid);
+
     boolean isUidPrivileged(int uid);
 
     String[] getAppOpPermissionPackages(String permissionName);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ca4ff6a..131ca39 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -784,6 +784,7 @@
                 pkg.splitNames = lite.splitNames;
                 pkg.splitCodePaths = lite.splitCodePaths;
                 pkg.splitFlags = new int[num];
+                pkg.splitPrivateFlags = new int[num];
 
                 for (int i = 0; i < num; i++) {
                     parseSplitApk(pkg, i, assets, flags);
@@ -1391,7 +1392,7 @@
 
         /* Set the global "forward lock" flag */
         if ((flags & PARSE_FORWARD_LOCK) != 0) {
-            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
+            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
         }
 
         /* Set the global "on SD card" flag */
@@ -2594,7 +2595,7 @@
                 if (sa.getBoolean(
                         com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
                         false)) {
-                    ai.flags |= ApplicationInfo.FLAG_CANT_SAVE_STATE;
+                    ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
 
                     // A heavy-weight application can not be in a custom process.
                     // We can do direct compare because we intern all strings.
@@ -3149,7 +3150,8 @@
 
         sa.recycle();
 
-        if (receiver && (owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
+        if (receiver && (owner.applicationInfo.privateFlags
+                &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
             // A heavy-weight application can not have receives in its main process
             // We can do direct compare because we intern all strings.
             if (a.info.processName == owner.packageName) {
@@ -3502,7 +3504,8 @@
 
         sa.recycle();
 
-        if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
+        if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
+                != 0) {
             // A heavy-weight application can not have providers in its main process
             // We can do direct compare because we intern all strings.
             if (p.info.processName == owner.packageName) {
@@ -3777,7 +3780,8 @@
 
         sa.recycle();
 
-        if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
+        if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
+                != 0) {
             // A heavy-weight application can not have services in its main process
             // We can do direct compare because we intern all strings.
             if (s.info.processName == owner.packageName) {
@@ -4189,6 +4193,13 @@
         /** Flags of any split APKs; ordered by parsed splitName */
         public int[] splitFlags;
 
+        /**
+         * Private flags of any split APKs; ordered by parsed splitName.
+         *
+         * {@hide}
+         */
+        public int[] splitPrivateFlags;
+
         public boolean baseHardwareAccelerated;
 
         // For now we only support one application per package.
@@ -4624,9 +4635,9 @@
             ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
         }
         if (state.hidden) {
-            ai.flags |= ApplicationInfo.FLAG_HIDDEN;
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
         } else {
-            ai.flags &= ~ApplicationInfo.FLAG_HIDDEN;
+            ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
         }
         if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
             ai.enabled = true;
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
index 518a874..cc018e9 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
@@ -104,7 +104,7 @@
             try {
                 ai = pm.getApplicationInfo(
                         ri.activityInfo.packageName, PackageManager.GET_META_DATA);
-                if ((ai.flags & ApplicationInfo.FLAG_PRIVILEGED) == 0) {
+                if ((ai.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) == 0) {
                     // The application isn't privileged (/system/priv-app).
                     // The enrollment application needs to be a privileged system app.
                     Slog.w(TAG, ai.packageName + "is not a privileged system app");
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 3a80309..1530bb2 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -419,7 +419,7 @@
             if (rLoc == INSTALL_LOC_INT) {
                 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
                     assertTrue("The application should be installed forward locked",
-                            (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
+                            (info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0);
                     assertStartsWith("The APK path should point to the ASEC",
                             SECURE_CONTAINERS_PREFIX, srcPath);
                     assertStartsWith("The public APK path should point to the ASEC",
@@ -435,7 +435,8 @@
                         fail("compat check: Can't read " + info.dataDir + "/lib");
                     }
                 } else {
-                    assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
+                    assertFalse(
+                            (info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0);
                     assertEquals(srcPath, appInstallPath);
                     assertEquals(publicSrcPath, appInstallPath);
                     assertStartsWith("Native library should point to shared lib directory",
@@ -462,16 +463,16 @@
             } else if (rLoc == INSTALL_LOC_SD) {
                 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
                     assertTrue("The application should be installed forward locked",
-                            (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
+                            (info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0);
                 } else {
                     assertFalse("The application should not be installed forward locked",
-                            (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
+                            (info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0);
                 }
                 assertTrue("Application flags (" + info.flags
                         + ") should contain FLAG_EXTERNAL_STORAGE",
                         (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                 // Might need to check:
-                // ((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0)
+                // ((info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0)
                 assertStartsWith("The APK path should point to the ASEC",
                         SECURE_CONTAINERS_PREFIX, srcPath);
                 assertStartsWith("The public APK path should point to the ASEC",
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index fea1a7a..a55f55d 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1855,7 +1855,8 @@
     boolean tryBindTransport(ServiceInfo info) {
         try {
             PackageInfo packInfo = mPackageManager.getPackageInfo(info.packageName, 0);
-            if ((packInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
+            if ((packInfo.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
+                    != 0) {
                 return bindTransport(info);
             } else {
                 Slog.w(TAG, "Transport package " + info.packageName + " not privileged");
@@ -3107,7 +3108,7 @@
                     final boolean isSharedStorage = pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
                     final boolean sendApk = mIncludeApks
                             && !isSharedStorage
-                            && ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0)
+                            && ((app.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) == 0)
                             && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
                                 (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
 
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index c3465d1..f8eac37 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -803,7 +803,8 @@
                                 .getApplicationInfo(packageName, 0, UserHandle.getUserId(uid));
                         if (appInfo != null) {
                             pkgUid = appInfo.uid;
-                            isPrivileged = (appInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0;
+                            isPrivileged = (appInfo.privateFlags
+                                    & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
                         } else {
                             if ("media".equals(packageName)) {
                                 pkgUid = Process.MEDIA_UID;
@@ -985,7 +986,8 @@
                     ApplicationInfo appInfo = ActivityThread.getPackageManager()
                             .getApplicationInfo(pkgName, 0, UserHandle.getUserId(uid));
                     if (appInfo != null) {
-                        isPrivileged = (appInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0;
+                        isPrivileged = (appInfo.privateFlags
+                                & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
                     }
                 } else {
                     // Could not load data, don't add to cache so it will be loaded later.
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d480f68..ce02845 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3052,7 +3052,8 @@
             try {
                 PackageInfo packageInfo = userPackageManager.getPackageInfo(name, 0 /* flags */);
                 if (packageInfo != null
-                        && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
+                        && (packageInfo.applicationInfo.privateFlags
+                                & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
                     return true;
                 }
             } catch (PackageManager.NameNotFoundException e) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 6f5866a..e7e1c5e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -857,7 +857,8 @@
             final long origId = Binder.clearCallingIdentity();
 
             if (aInfo != null &&
-                    (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
+                    (aInfo.applicationInfo.privateFlags
+                            &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                 // This may be a heavy-weight process!  Check to see if we already
                 // have another, different heavy-weight process running.
                 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
@@ -1028,8 +1029,8 @@
                     aInfo = mService.getActivityInfoForUser(aInfo, userId);
 
                     if (aInfo != null &&
-                            (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
-                                    != 0) {
+                            (aInfo.applicationInfo.privateFlags
+                                    & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)  != 0) {
                         throw new IllegalArgumentException(
                                 "FLAG_CANT_SAVE_STATE not supported here");
                     }
@@ -1160,7 +1161,7 @@
                     results, newIntents, !andResume, mService.isNextTransitionForward(),
                     profilerInfo);
 
-            if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
+            if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                 // This may be a heavy-weight process!  Note that the package
                 // manager will ensure that only activity can run in the main
                 // process of the .apk, which is the only thing that will be
diff --git a/services/core/java/com/android/server/firewall/SenderFilter.java b/services/core/java/com/android/server/firewall/SenderFilter.java
index c0eee69..0074119 100644
--- a/services/core/java/com/android/server/firewall/SenderFilter.java
+++ b/services/core/java/com/android/server/firewall/SenderFilter.java
@@ -45,7 +45,8 @@
 
         IPackageManager pm = AppGlobals.getPackageManager();
         try {
-            return (pm.getFlagsForUid(callerUid) & ApplicationInfo.FLAG_PRIVILEGED) != 0;
+            return (pm.getPrivateFlagsForUid(callerUid) & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
+                    != 0;
         } catch (RemoteException ex) {
             Slog.e(IntentFirewall.TAG, "Remote exception while retrieving uid flags",
                     ex);
diff --git a/services/core/java/com/android/server/pm/GrantedPermissions.java b/services/core/java/com/android/server/pm/GrantedPermissions.java
index 14258a4..c752349 100644
--- a/services/core/java/com/android/server/pm/GrantedPermissions.java
+++ b/services/core/java/com/android/server/pm/GrantedPermissions.java
@@ -22,13 +22,15 @@
 
 class GrantedPermissions {
     int pkgFlags;
+    int pkgPrivateFlags;
 
     HashSet<String> grantedPermissions = new HashSet<String>();
 
     int[] gids;
 
-    GrantedPermissions(int pkgFlags) {
+    GrantedPermissions(int pkgFlags, int pkgPrivateFlags) {
         setFlags(pkgFlags);
+        setPrivateFlags(pkgPrivateFlags);
     }
 
     @SuppressWarnings("unchecked")
@@ -44,8 +46,12 @@
     void setFlags(int pkgFlags) {
         this.pkgFlags = pkgFlags
                 & (ApplicationInfo.FLAG_SYSTEM
-                        | ApplicationInfo.FLAG_PRIVILEGED
-                        | ApplicationInfo.FLAG_FORWARD_LOCK
                         | ApplicationInfo.FLAG_EXTERNAL_STORAGE);
     }
+
+    void setPrivateFlags(int pkgPrivateFlags) {
+        this.pkgPrivateFlags = pkgPrivateFlags
+                & (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
+                        | ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK);
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2564962..856135f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1282,17 +1282,17 @@
         mMetrics = new DisplayMetrics();
         mSettings = new Settings(context);
         mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
-                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
-                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
-                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
-                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
-                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
-                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
 
         String separateProcesses = SystemProperties.get("debug.separate_processes");
         if (separateProcesses != null && separateProcesses.length() > 0) {
@@ -2097,6 +2097,7 @@
                 pkg = new PackageParser.Package(packageName);
                 pkg.applicationInfo.packageName = packageName;
                 pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
+                pkg.applicationInfo.privateFlags = ps.pkgPrivateFlags;
                 pkg.applicationInfo.dataDir =
                         getDataPathForPackage(packageName, 0).getPath();
                 pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString;
@@ -2907,7 +2908,7 @@
         }
         // reader
         synchronized (mPackages) {
-            final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, false);
+            final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, 0, false);
             if (suid == null) {
                 return -1;
             }
@@ -2931,6 +2932,21 @@
     }
 
     @Override
+    public int getPrivateFlagsForUid(int uid) {
+        synchronized (mPackages) {
+            Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
+            if (obj instanceof SharedUserSetting) {
+                final SharedUserSetting sus = (SharedUserSetting) obj;
+                return sus.pkgPrivateFlags;
+            } else if (obj instanceof PackageSetting) {
+                final PackageSetting ps = (PackageSetting) obj;
+                return ps.pkgPrivateFlags;
+            }
+        }
+        return 0;
+    }
+
+    @Override
     public boolean isUidPrivileged(int uid) {
         uid = UserHandle.getAppId(uid);
         // reader
@@ -4228,9 +4244,9 @@
             // If new package is not located in "/system/priv-app" (e.g. due to an OTA),
             // it needs to drop FLAG_PRIVILEGED.
             if (locationIsPrivileged(scanFile)) {
-                updatedPkg.pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
+                updatedPkg.pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
             } else {
-                updatedPkg.pkgFlags &= ~ApplicationInfo.FLAG_PRIVILEGED;
+                updatedPkg.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
             }
 
             if (ps != null && !ps.codePath.equals(scanFile)) {
@@ -4294,7 +4310,7 @@
 
             // An updated privileged app will not have the PARSE_IS_PRIVILEGED
             // flag set initially
-            if ((updatedPkg.pkgFlags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
+            if ((updatedPkg.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
                 parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
             }
         }
@@ -5190,7 +5206,7 @@
         }
 
         if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
-            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_PRIVILEGED;
+            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
         }
 
         if (mCustomResolverComponentName != null &&
@@ -5264,7 +5280,7 @@
         // writer
         synchronized (mPackages) {
             if (pkg.mSharedUserId != null) {
-                suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
+                suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, true);
                 if (suid == null) {
                     throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                             "Creating application package " + pkg.packageName
@@ -5338,7 +5354,8 @@
                     destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
                     pkg.applicationInfo.primaryCpuAbi,
                     pkg.applicationInfo.secondaryCpuAbi,
-                    pkg.applicationInfo.flags, user, false);
+                    pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,
+                    user, false);
             if (pkgSetting == null) {
                 throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                         "Creating application package " + pkg.packageName + " failed");
@@ -10174,7 +10191,8 @@
         boolean disabledSystem = false;
         boolean updatedSettings = false;
         parseFlags |= PackageParser.PARSE_IS_SYSTEM;
-        if ((deletedPackage.applicationInfo.flags&ApplicationInfo.FLAG_PRIVILEGED) != 0) {
+        if ((deletedPackage.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
+                != 0) {
             parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
         }
         String packageName = deletedPackage.packageName;
@@ -10510,15 +10528,15 @@
     }
 
     private static boolean isForwardLocked(PackageParser.Package pkg) {
-        return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
+        return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
     }
 
     private static boolean isForwardLocked(ApplicationInfo info) {
-        return (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
+        return (info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
     }
 
     private boolean isForwardLocked(PackageSetting ps) {
-        return (ps.pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
+        return (ps.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
     }
 
     private static boolean isMultiArch(PackageSetting ps) {
@@ -10546,7 +10564,7 @@
     }
 
     private static boolean isPrivilegedApp(PackageParser.Package pkg) {
-        return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0;
+        return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
     }
 
     private static boolean isSystemApp(ApplicationInfo info) {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 696aa34..8ea0bee 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -32,10 +32,10 @@
     PackageSetting(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString,
-            int pVersionCode, int pkgFlags) {
+            int pVersionCode, int pkgFlags, int privateFlags) {
         super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
                 primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
-                pVersionCode, pkgFlags);
+                pVersionCode, pkgFlags, privateFlags);
     }
 
     /**
@@ -62,6 +62,6 @@
     }
 
     public boolean isPrivileged() {
-        return (pkgFlags & ApplicationInfo.FLAG_PRIVILEGED) != 0;
+        return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index bf13fd9..1275941 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -112,8 +112,8 @@
     PackageSettingBase(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString,
-            int pVersionCode, int pkgFlags) {
-        super(pkgFlags);
+            int pVersionCode, int pkgFlags, int pkgPrivateFlags) {
+        super(pkgFlags, pkgPrivateFlags);
         this.name = name;
         this.realName = realName;
         init(codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString,
diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java
index 5d30e76..bb0dba1 100644
--- a/services/core/java/com/android/server/pm/PendingPackage.java
+++ b/services/core/java/com/android/server/pm/PendingPackage.java
@@ -24,10 +24,10 @@
     PendingPackage(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString, int sharedId,
-            int pVersionCode, int pkgFlags) {
+            int pVersionCode, int pkgFlags, int pkgPrivateFlags) {
         super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
                 primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
-                pVersionCode, pkgFlags);
+                pVersionCode, pkgFlags, pkgPrivateFlags);
         this.sharedId = sharedId;
     }
 }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 7de56c8..144477e 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -273,11 +273,11 @@
     PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,
-            int pkgFlags, UserHandle user, boolean add) {
+            int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add) {
         final String name = pkg.packageName;
         PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
                 resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi,
-                pkg.mVersionCode, pkgFlags, user, add, true /* allowInstall */);
+                pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /* allowInstall */);
         return p;
     }
 
@@ -303,13 +303,13 @@
     }
 
     SharedUserSetting getSharedUserLPw(String name,
-            int pkgFlags, boolean create) {
+            int pkgFlags, int pkgPrivateFlags, boolean create) {
         SharedUserSetting s = mSharedUsers.get(name);
         if (s == null) {
             if (!create) {
                 return null;
             }
-            s = new SharedUserSetting(name, pkgFlags);
+            s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
             s.userId = newUserIdLPw(s);
             Log.i(PackageManagerService.TAG, "New shared user " + name + ": id=" + s.userId);
             // < 0 means we couldn't assign a userid; fall out and return
@@ -365,7 +365,7 @@
         PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
                 p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
                 p.secondaryCpuAbiString, p.secondaryCpuAbiString,
-                p.appId, p.versionCode, p.pkgFlags);
+                p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags);
         mDisabledSysPackages.remove(name);
         return ret;
     }
@@ -380,7 +380,7 @@
 
     PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString,
-            String cpuAbiOverrideString, int uid, int vc, int pkgFlags) {
+            String cpuAbiOverrideString, int uid, int vc, int pkgFlags, int pkgPrivateFlags) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
             if (p.appId == uid) {
@@ -392,7 +392,7 @@
         }
         p = new PackageSetting(name, realName, codePath, resourcePath,
                 legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
-                cpuAbiOverrideString, vc, pkgFlags);
+                cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags);
         p.appId = uid;
         if (addUserIdLPw(uid, p, name)) {
             mPackages.put(name, p);
@@ -401,7 +401,7 @@
         return null;
     }
 
-    SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags) {
+    SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
         SharedUserSetting s = mSharedUsers.get(name);
         if (s != null) {
             if (s.userId == uid) {
@@ -411,7 +411,7 @@
                     "Adding duplicate shared user, keeping first: " + name);
             return null;
         }
-        s = new SharedUserSetting(name, pkgFlags);
+        s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
         s.userId = uid;
         if (addUserIdLPw(uid, s, name)) {
             mSharedUsers.put(name, s);
@@ -461,7 +461,7 @@
     private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString,
-            int vc, int pkgFlags, UserHandle installUser, boolean add,
+            int vc, int pkgFlags, int pkgPrivateFlags, UserHandle installUser, boolean add,
             boolean allowInstall) {
         PackageSetting p = mPackages.get(name);
         UserManagerService userManager = UserManagerService.getInstance();
@@ -503,9 +503,8 @@
                 // If what we are scanning is a system (and possibly privileged) package,
                 // then make it so, regardless of whether it was previously installed only
                 // in the data partition.
-                final int sysPrivFlags = pkgFlags
-                        & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_PRIVILEGED);
-                p.pkgFlags |= sysPrivFlags;
+                p.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
+                p.pkgPrivateFlags |= pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
             }
         }
         if (p == null) {
@@ -513,7 +512,7 @@
                 // We are consuming the data from an existing package.
                 p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
                         legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
-                        null /* cpuAbiOverrideString */, vc, pkgFlags);
+                        null /* cpuAbiOverrideString */, vc, pkgFlags, pkgPrivateFlags);
                 if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
                         + name + " is adopting original package " + origPackage.name);
                 // Note that we will retain the new package's signature so
@@ -531,7 +530,7 @@
             } else {
                 p = new PackageSetting(name, realName, codePath, resourcePath,
                         legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
-                        null /* cpuAbiOverrideString */, vc, pkgFlags);
+                        null /* cpuAbiOverrideString */, vc, pkgFlags, pkgPrivateFlags);
                 p.setTimeStamp(codePath.lastModified());
                 p.sharedUser = sharedUser;
                 // If this is not a system app, it starts out stopped.
@@ -1810,7 +1809,8 @@
             serializer.attribute(null, "cpuAbiOverride", pkg.cpuAbiOverrideString);
         }
 
-        serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags));
+        serializer.attribute(null, "publicFlags", Integer.toString(pkg.pkgFlags));
+        serializer.attribute(null, "privateFlags", Integer.toString(pkg.pkgPrivateFlags));
         serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
         serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
         serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
@@ -2119,8 +2119,8 @@
                 PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
                         (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
                         pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString,
-                        pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags, null,
-                        true /* add */, false /* allowInstall */);
+                        pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags, pp.pkgPrivateFlags,
+                        null, true /* add */, false /* allowInstall */);
                 if (p == null) {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Unable to create application package for " + pp.name);
@@ -2588,14 +2588,15 @@
         }
 
         int pkgFlags = 0;
+        int pkgPrivateFlags = 0;
         pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
         final File codePathFile = new File(codePathStr);
         if (PackageManagerService.locationIsPrivileged(codePathFile)) {
-            pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
+            pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
         }
         PackageSetting ps = new PackageSetting(name, realName, codePathFile,
                 new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr,
-                secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags);
+                secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags, pkgPrivateFlags);
         String timeStampStr = parser.getAttributeValue(null, "ft");
         if (timeStampStr != null) {
             try {
@@ -2654,6 +2655,11 @@
         mDisabledSysPackages.put(name, ps);
     }
 
+    private static int PRE_M_APP_INFO_FLAG_HIDDEN = 1<<27;
+    private static int PRE_M_APP_INFO_FLAG_CANT_SAVE_STATE = 1<<28;
+    private static int PRE_M_APP_INFO_FLAG_FORWARD_LOCK = 1<<29;
+    private static int PRE_M_APP_INFO_FLAG_PRIVILEGED = 1<<30;
+
     private void readPackageLPw(XmlPullParser parser) throws XmlPullParserException, IOException {
         String name = null;
         String realName = null;
@@ -2670,6 +2676,7 @@
         String installerPackageName = null;
         String uidError = null;
         int pkgFlags = 0;
+        int pkgPrivateFlags = 0;
         long timeStamp = 0;
         long firstInstallTime = 0;
         long lastUpdateTime = 0;
@@ -2705,22 +2712,54 @@
             }
             installerPackageName = parser.getAttributeValue(null, "installer");
 
-            systemStr = parser.getAttributeValue(null, "flags");
+            systemStr = parser.getAttributeValue(null, "publicFlags");
             if (systemStr != null) {
                 try {
                     pkgFlags = Integer.parseInt(systemStr);
                 } catch (NumberFormatException e) {
                 }
-            } else {
-                // For backward compatibility
-                systemStr = parser.getAttributeValue(null, "system");
+                systemStr = parser.getAttributeValue(null, "privateFlags");
                 if (systemStr != null) {
-                    pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM
-                            : 0;
+                    try {
+                        pkgPrivateFlags = Integer.parseInt(systemStr);
+                    } catch (NumberFormatException e) {
+                    }
+                }
+            } else {
+                // Pre-M -- both public and private flags were stored in one "flags" field.
+                systemStr = parser.getAttributeValue(null, "flags");
+                if (systemStr != null) {
+                    try {
+                        pkgFlags = Integer.parseInt(systemStr);
+                    } catch (NumberFormatException e) {
+                    }
+                    if ((pkgFlags & PRE_M_APP_INFO_FLAG_HIDDEN) != 0) {
+                        pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
+                    }
+                    if ((pkgFlags & PRE_M_APP_INFO_FLAG_CANT_SAVE_STATE) != 0) {
+                        pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
+                    }
+                    if ((pkgFlags & PRE_M_APP_INFO_FLAG_FORWARD_LOCK) != 0) {
+                        pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
+                    }
+                    if ((pkgFlags & PRE_M_APP_INFO_FLAG_PRIVILEGED) != 0) {
+                        pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+                    }
+                    pkgFlags &= ~(PRE_M_APP_INFO_FLAG_HIDDEN
+                            | PRE_M_APP_INFO_FLAG_CANT_SAVE_STATE
+                            | PRE_M_APP_INFO_FLAG_FORWARD_LOCK
+                            | PRE_M_APP_INFO_FLAG_PRIVILEGED);
                 } else {
-                    // Old settings that don't specify system... just treat
-                    // them as system, good enough.
-                    pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
+                    // For backward compatibility
+                    systemStr = parser.getAttributeValue(null, "system");
+                    if (systemStr != null) {
+                        pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM
+                                : 0;
+                    } else {
+                        // Old settings that don't specify system... just treat
+                        // them as system, good enough.
+                        pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
+                    }
                 }
             }
             String timeStampStr = parser.getAttributeValue(null, "ft");
@@ -2773,7 +2812,8 @@
             } else if (userId > 0) {
                 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
                         new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
-                        secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags);
+                        secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags,
+                        pkgPrivateFlags);
                 if (PackageManagerService.DEBUG_SETTINGS)
                     Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
                             + userId + " pkg=" + packageSetting);
@@ -2792,7 +2832,7 @@
                     packageSetting = new PendingPackage(name.intern(), realName, new File(
                             codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
                             primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
-                            userId, versionCode, pkgFlags);
+                            userId, versionCode, pkgFlags, pkgPrivateFlags);
                     packageSetting.setTimeStamp(timeStamp);
                     packageSetting.firstInstallTime = firstInstallTime;
                     packageSetting.lastUpdateTime = lastUpdateTime;
@@ -2959,6 +2999,7 @@
         String name = null;
         String idStr = null;
         int pkgFlags = 0;
+        int pkgPrivateFlags = 0;
         SharedUserSetting su = null;
         try {
             name = parser.getAttributeValue(null, ATTR_NAME);
@@ -2977,7 +3018,8 @@
                                 + " has bad userId " + idStr + " at "
                                 + parser.getPositionDescription());
             } else {
-                if ((su = addSharedUserLPw(name.intern(), userId, pkgFlags)) == null) {
+                if ((su = addSharedUserLPw(name.intern(), userId, pkgFlags, pkgPrivateFlags))
+                        == null) {
                     PackageManagerService
                             .reportSettingsProblem(Log.ERROR, "Occurred while parsing settings at "
                                     + parser.getPositionDescription());
@@ -3294,9 +3336,12 @@
         ApplicationInfo.FLAG_RESTORE_ANY_VERSION, "RESTORE_ANY_VERSION",
         ApplicationInfo.FLAG_EXTERNAL_STORAGE, "EXTERNAL_STORAGE",
         ApplicationInfo.FLAG_LARGE_HEAP, "LARGE_HEAP",
-        ApplicationInfo.FLAG_PRIVILEGED, "PRIVILEGED",
-        ApplicationInfo.FLAG_FORWARD_LOCK, "FORWARD_LOCK",
-        ApplicationInfo.FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
+    };
+
+    static final Object[] PRIVATE_FLAG_DUMP_SPEC = new Object[] {
+        ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
+        ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
+        ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
     };
 
     void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, PackageSetting ps,
@@ -3370,6 +3415,8 @@
                 pw.println(ps.pkg.applicationInfo.toString());
             pw.print(prefix); pw.print("  flags="); printFlags(pw, ps.pkg.applicationInfo.flags,
                     FLAG_DUMP_SPEC); pw.println();
+            pw.print(prefix); pw.print("  priavateFlags="); printFlags(pw,
+                    ps.pkg.applicationInfo.privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println();
             pw.print(prefix); pw.print("  dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
             if (ps.pkg.mOperationPending) {
                 pw.print(prefix); pw.println("  mOperationPending=true");
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index ca1eeea..b0b95cf 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -28,14 +28,16 @@
 
     // flags that are associated with this uid, regardless of any package flags
     int uidFlags;
+    int uidPrivateFlags;
 
     final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
 
     final PackageSignatures signatures = new PackageSignatures();
 
-    SharedUserSetting(String _name, int _pkgFlags) {
-        super(_pkgFlags);
+    SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags) {
+        super(_pkgFlags, _pkgPrivateFlags);
         uidFlags =  _pkgFlags;
+        uidPrivateFlags = _pkgPrivateFlags;
         name = _name;
     }
 
@@ -55,12 +57,20 @@
                 }
                 setFlags(aggregatedFlags);
             }
+            if ((this.pkgPrivateFlags & packageSetting.pkgPrivateFlags) != 0) {
+                int aggregatedPrivateFlags = uidPrivateFlags;
+                for (PackageSetting ps : packages) {
+                    aggregatedPrivateFlags |= ps.pkgPrivateFlags;
+                }
+                setPrivateFlags(aggregatedPrivateFlags);
+            }
         }
     }
 
     void addPackage(PackageSetting packageSetting) {
         if (packages.add(packageSetting)) {
             setFlags(this.pkgFlags | packageSetting.pkgFlags);
+            setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags);
         }
     }
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 0cf22493..21726ff 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1588,7 +1588,8 @@
                 try {
                     for (ApplicationInfo appInfo : apps) {
                         if ((appInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0
-                                && (appInfo.flags & ApplicationInfo.FLAG_HIDDEN) != 0) {
+                                && (appInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HIDDEN)
+                                        != 0) {
                             mPm.setApplicationHiddenSettingAsUser(appInfo.packageName, false,
                                     userHandle);
                         }