Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88c3301c authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android Git Automerger
Browse files

am 2d9d5905: am 25945302: Merge "Persist version data on a per-volume basis." into mnc-dev

* commit '2d9d5905':
  Persist version data on a per-volume basis.
parents 8046c22d 2d9d5905
Loading
Loading
Loading
Loading
+65 −49
Original line number Diff line number Diff line
@@ -224,6 +224,7 @@ import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.pm.PermissionsState.PermissionState;
import com.android.server.pm.Settings.DatabaseVersion;
import com.android.server.pm.Settings.VersionInfo;
import com.android.server.storage.DeviceStorageMonitorInternal;
import org.xmlpull.v1.XmlPullParser;
@@ -1654,6 +1655,11 @@ public class PackageManagerService extends IPackageManager.Stub {
        @Override
        public void onVolumeForgotten(String fsUuid) {
            if (TextUtils.isEmpty(fsUuid)) {
                Slog.w(TAG, "Forgetting internal storage is probably a mistake; ignoring");
                return;
            }
            // Remove any apps installed on the forgotten volume
            synchronized (mPackages) {
                final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(fsUuid);
@@ -1663,6 +1669,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                            UserHandle.USER_OWNER, PackageManager.DELETE_ALL_USERS);
                }
                mSettings.onVolumeForgotten(fsUuid);
                mSettings.writeLPr();
            }
        }
@@ -2239,17 +2246,16 @@ public class PackageManagerService extends IPackageManager.Stub {
            // cases get permissions that the user didn't initially explicitly
            // allow...  it would be nice to have some better way to handle
            // this situation.
            final boolean regrantPermissions = mSettings.mInternalSdkPlatform
                    != mSdkVersion;
            if (regrantPermissions) Slog.i(TAG, "Platform changed from "
                    + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
                    + "; regranting permissions for internal storage");
            mSettings.mInternalSdkPlatform = mSdkVersion;
            updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
                    | (regrantPermissions
                            ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
                            : 0));
            final VersionInfo ver = mSettings.getInternalVersion();
            int updateFlags = UPDATE_PERMISSIONS_ALL;
            if (ver.sdkVersion != mSdkVersion) {
                Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
                        + mSdkVersion + "; regranting permissions for internal storage");
                updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
            }
            updatePermissionsLPw(null, null, updateFlags);
            ver.sdkVersion = mSdkVersion;
            // If this is the first boot, and it is a normal boot, then
            // we need to initialize the default preferred apps.
@@ -2261,20 +2267,22 @@ public class PackageManagerService extends IPackageManager.Stub {
            // If this is first boot after an OTA, and a normal boot, then
            // we need to clear code cache directories.
            mIsUpgrade = !Build.FINGERPRINT.equals(mSettings.mFingerprint);
            mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
            if (mIsUpgrade && !onlyCore) {
                Slog.i(TAG, "Build fingerprint changed; clearing code caches");
                for (int i = 0; i < mSettings.mPackages.size(); i++) {
                    final PackageSetting ps = mSettings.mPackages.valueAt(i);
                    if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
                        deleteCodeCacheDirsLI(ps.volumeUuid, ps.name);
                    }
                mSettings.mFingerprint = Build.FINGERPRINT;
                }
                ver.fingerprint = Build.FINGERPRINT;
            }
            checkDefaultBrowser();
            // All the changes are done during package scanning.
            mSettings.updateInternalDatabaseVersion();
            ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
            // can downgrade to reader
            mSettings.writeLPr();
@@ -3919,10 +3927,8 @@ public class PackageManagerService extends IPackageManager.Stub {
     * were updated, return true.
     */
    private boolean isCompatSignatureUpdateNeeded(PackageParser.Package scannedPkg) {
        return (isExternal(scannedPkg) && mSettings.isExternalDatabaseVersionOlderThan(
                DatabaseVersion.SIGNATURE_END_ENTITY))
                || (!isExternal(scannedPkg) && mSettings.isInternalDatabaseVersionOlderThan(
                        DatabaseVersion.SIGNATURE_END_ENTITY));
        final VersionInfo ver = getSettingsVersionForPackage(scannedPkg);
        return ver.databaseVersion < DatabaseVersion.SIGNATURE_END_ENTITY;
    }
    /**
@@ -3969,13 +3975,8 @@ public class PackageManagerService extends IPackageManager.Stub {
    }
    private boolean isRecoverSignatureUpdateNeeded(PackageParser.Package scannedPkg) {
        if (isExternal(scannedPkg)) {
            return mSettings.isExternalDatabaseVersionOlderThan(
                    DatabaseVersion.SIGNATURE_MALFORMED_RECOVER);
        } else {
            return mSettings.isInternalDatabaseVersionOlderThan(
                    DatabaseVersion.SIGNATURE_MALFORMED_RECOVER);
        }
        final VersionInfo ver = getSettingsVersionForPackage(scannedPkg);
        return ver.databaseVersion < DatabaseVersion.SIGNATURE_MALFORMED_RECOVER;
    }
    private int compareSignaturesRecover(PackageSignatures existingSigs,
@@ -12491,6 +12492,18 @@ public class PackageManagerService extends IPackageManager.Stub {
        return installFlags;
    }
    private VersionInfo getSettingsVersionForPackage(PackageParser.Package pkg) {
        if (isExternal(pkg)) {
            if (TextUtils.isEmpty(pkg.volumeUuid)) {
                return mSettings.getExternalVersion();
            } else {
                return mSettings.findOrCreateVersion(pkg.volumeUuid);
            }
        } else {
            return mSettings.getInternalVersion();
        }
    }
    private void deleteTempPackageFiles() {
        final FilenameFilter filter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
@@ -14756,16 +14769,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                    if (dumpState.onTitlePrinted())
                        pw.println();
                    pw.println("Database versions:");
                    pw.print("  SDK Version:");
                    pw.print(" internal=");
                    pw.print(mSettings.mInternalSdkPlatform);
                    pw.print(" external=");
                    pw.println(mSettings.mExternalSdkPlatform);
                    pw.print("  DB Version:");
                    pw.print(" internal=");
                    pw.print(mSettings.mInternalDatabaseVersion);
                    pw.print(" external=");
                    pw.println(mSettings.mExternalDatabaseVersion);
                    mSettings.dumpVersionLPr(new IndentingPrintWriter(pw, "  "));
                }
            }
@@ -15412,20 +15416,18 @@ public class PackageManagerService extends IPackageManager.Stub {
            // cases get permissions that the user didn't initially explicitly
            // allow... it would be nice to have some better way to handle
            // this situation.
            final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion;
            if (regrantPermissions)
                Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to "
                        + mSdkVersion + "; regranting permissions for external storage");
            mSettings.mExternalSdkPlatform = mSdkVersion;
            final VersionInfo ver = mSettings.getExternalVersion();
            // Make sure group IDs have been assigned, and any permission
            // changes in other apps are accounted for
            updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
                    | (regrantPermissions
                            ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
                            : 0));
            int updateFlags = UPDATE_PERMISSIONS_ALL;
            if (ver.sdkVersion != mSdkVersion) {
                logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to "
                        + mSdkVersion + "; regranting permissions for external");
                updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
            }
            updatePermissionsLPw(null, null, updateFlags);
            mSettings.updateExternalDatabaseVersion();
            // Yay, everything is now upgraded
            ver.forceCurrent();
            // can downgrade to reader
            // Persist settings
@@ -15517,6 +15519,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE;
        synchronized (mInstallLock) {
        synchronized (mPackages) {
            final VersionInfo ver = mSettings.findOrCreateVersion(vol.fsUuid);
            final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid);
            for (PackageSetting ps : packages) {
                final PackageParser.Package pkg;
@@ -15526,9 +15529,22 @@ public class PackageManagerService extends IPackageManager.Stub {
                } catch (PackageManagerException e) {
                    Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());
                }
                if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
                    deleteCodeCacheDirsLI(ps.volumeUuid, ps.name);
                }
            }
            int updateFlags = UPDATE_PERMISSIONS_ALL;
            if (ver.sdkVersion != mSdkVersion) {
                logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to "
                        + mSdkVersion + "; regranting permissions for " + vol.fsUuid);
                updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
            }
            updatePermissionsLPw(null, null, updateFlags);
            // TODO: regrant any permissions that changed based since original install
            // Yay, everything is now upgraded
            ver.forceCurrent();
            mSettings.writeLPr();
        }
+140 −101
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
@@ -129,7 +130,7 @@ final class Settings {
     * Note that care should be taken to make sure all database upgrades are
     * idempotent.
     */
    private static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_MALFORMED_RECOVER;
    public static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_MALFORMED_RECOVER;

    /**
     * This class contains constants that can be referred to from upgrade code.
@@ -177,11 +178,12 @@ final class Settings {
            "persistent-preferred-activities";
    static final String TAG_CROSS_PROFILE_INTENT_FILTERS =
            "crossProfile-intent-filters";
    public static final String TAG_DOMAIN_VERIFICATION = "domain-verification";
    public static final String TAG_DEFAULT_APPS= "default-apps";
    public static final String TAG_ALL_INTENT_FILTER_VERIFICATION =
    private static final String TAG_DOMAIN_VERIFICATION = "domain-verification";
    private static final String TAG_DEFAULT_APPS = "default-apps";
    private static final String TAG_ALL_INTENT_FILTER_VERIFICATION =
            "all-intent-filter-verifications";
    public static final String TAG_DEFAULT_BROWSER= "default-browser";
    private static final String TAG_DEFAULT_BROWSER = "default-browser";
    private static final String TAG_VERSION = "version";

    private static final String ATTR_NAME = "name";
    private static final String ATTR_USER = "user";
@@ -202,6 +204,9 @@ final class Settings {
    private static final String ATTR_PACKAGE_NAME = "packageName";
    private static final String ATTR_FINGERPRINT = "fingerprint";
    private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
    private static final String ATTR_VOLUME_UUID = "volumeUuid";
    private static final String ATTR_SDK_VERSION = "sdkVersion";
    private static final String ATTR_DATABASE_VERSION = "databaseVersion";

    private final Object mLock;

@@ -226,27 +231,43 @@ final class Settings {

    private static int mFirstAvailableUid = 0;

    // TODO: store SDK versions and fingerprint for each volume UUID
    /** Map from volume UUID to {@link VersionInfo} */
    private ArrayMap<String, VersionInfo> mVersion = new ArrayMap<>();

    // These are the last platform API version we were using for
    // the apps installed on internal and external storage.  It is
    // used to grant newer permissions one time during a system upgrade.
    int mInternalSdkPlatform;
    int mExternalSdkPlatform;
    /**
     * Version details for a storage volume that may hold apps.
     */
    public static class VersionInfo {
        /**
         * These are the last platform API version we were using for the apps
         * installed on internal and external storage. It is used to grant newer
         * permissions one time during a system upgrade.
         */
        int sdkVersion;

        /**
         * The current database version for apps on internal storage. This is
     * used to upgrade the format of the packages.xml database not necessarily
     * tied to an SDK version.
         * used to upgrade the format of the packages.xml database not
         * necessarily tied to an SDK version.
         */
    int mInternalDatabaseVersion;
    int mExternalDatabaseVersion;
        int databaseVersion;

        /**
     * Last known value of {@link Build#FINGERPRINT}. Used to determine when an
     * system update has occurred, meaning we need to clear code caches.
         * Last known value of {@link Build#FINGERPRINT}. Used to determine when
         * an system update has occurred, meaning we need to clear code caches.
         */
    String mFingerprint;
        String fingerprint;

        /**
         * Force all version information to match current system values,
         * typically after resolving any required upgrade steps.
         */
        public void forceCurrent() {
            sdkVersion = Build.VERSION.SDK_INT;
            databaseVersion = CURRENT_DATABASE_VERSION;
            fingerprint = Build.FINGERPRINT;
        }
    }

    Boolean mReadExternalStorageEnforced;

@@ -1188,38 +1209,26 @@ final class Settings {
                .onDefaultRuntimePermissionsGrantedLPr(userId);
    }

    /**
     * Returns whether the current database has is older than {@code version}
     * for apps on internal storage.
     */
    public boolean isInternalDatabaseVersionOlderThan(int version) {
        return mInternalDatabaseVersion < version;
    public VersionInfo findOrCreateVersion(String volumeUuid) {
        VersionInfo ver = mVersion.get(volumeUuid);
        if (ver == null) {
            ver = new VersionInfo();
            ver.forceCurrent();
            mVersion.put(volumeUuid, ver);
        }
        return ver;
    }

    /**
     * Returns whether the current database has is older than {@code version}
     * for apps on external storage.
     */
    public boolean isExternalDatabaseVersionOlderThan(int version) {
        return mExternalDatabaseVersion < version;
    public VersionInfo getInternalVersion() {
        return mVersion.get(StorageManager.UUID_PRIVATE_INTERNAL);
    }

    /**
     * Updates the database version for apps on internal storage. Called after
     * call the updates to the database format are done for apps on internal
     * storage after the initial start-up scan.
     */
    public void updateInternalDatabaseVersion() {
        mInternalDatabaseVersion = CURRENT_DATABASE_VERSION;
    public VersionInfo getExternalVersion() {
        return mVersion.get(StorageManager.UUID_PRIMARY_PHYSICAL);
    }

    /**
     * Updates the database version for apps on internal storage. Called after
     * call the updates to the database format are done for apps on internal
     * storage after the initial start-up scan.
     */
    public void updateExternalDatabaseVersion() {
        mExternalDatabaseVersion = CURRENT_DATABASE_VERSION;
    public void onVolumeForgotten(String fsUuid) {
        mVersion.remove(fsUuid);
    }

    /**
@@ -2060,16 +2069,17 @@ final class Settings {

            serializer.startTag(null, "packages");

            serializer.startTag(null, "last-platform-version");
            serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
            serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
            serializer.attribute(null, "fingerprint", mFingerprint);
            serializer.endTag(null, "last-platform-version");
            for (int i = 0; i < mVersion.size(); i++) {
                final String volumeUuid = mVersion.keyAt(i);
                final VersionInfo ver = mVersion.valueAt(i);

            serializer.startTag(null, "database-version");
            serializer.attribute(null, "internal", Integer.toString(mInternalDatabaseVersion));
            serializer.attribute(null, "external", Integer.toString(mExternalDatabaseVersion));
            serializer.endTag(null, "database-version");
                serializer.startTag(null, TAG_VERSION);
                XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid);
                XmlUtils.writeIntAttribute(serializer, ATTR_SDK_VERSION, ver.sdkVersion);
                XmlUtils.writeIntAttribute(serializer, ATTR_DATABASE_VERSION, ver.databaseVersion);
                XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint);
                serializer.endTag(null, TAG_VERSION);
            }

            if (mVerifierDeviceIdentity != null) {
                serializer.startTag(null, "verifier");
@@ -2499,8 +2509,10 @@ final class Settings {
                    mReadMessages.append("No settings file found\n");
                    PackageManagerService.reportSettingsProblem(Log.INFO,
                            "No settings file; creating initial state");
                    mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion;
                    mFingerprint = Build.FINGERPRINT;
                    // It's enough to just touch version details to create them
                    // with default values
                    findOrCreateVersion(StorageManager.UUID_PRIVATE_INTERNAL);
                    findOrCreateVersion(StorageManager.UUID_PRIMARY_PHYSICAL);
                    return false;
                }
                str = new FileInputStream(mSettingsFilename);
@@ -2584,48 +2596,27 @@ final class Settings {
                } else if (tagName.equals("restored-ivi")) {
                    readRestoredIntentFilterVerifications(parser);
                } else if (tagName.equals("last-platform-version")) {
                    mInternalSdkPlatform = mExternalSdkPlatform = 0;
                    try {
                        String internal = parser.getAttributeValue(null, "internal");
                        if (internal != null) {
                            mInternalSdkPlatform = Integer.parseInt(internal);
                        }
                        String external = parser.getAttributeValue(null, "external");
                        if (external != null) {
                            mExternalSdkPlatform = Integer.parseInt(external);
                        }
                    } catch (NumberFormatException e) {
                    }
                    mFingerprint = parser.getAttributeValue(null, "fingerprint");
                    // Upgrade from older XML schema
                    final VersionInfo internal = findOrCreateVersion(
                            StorageManager.UUID_PRIVATE_INTERNAL);
                    final VersionInfo external = findOrCreateVersion(
                            StorageManager.UUID_PRIMARY_PHYSICAL);

                    internal.sdkVersion = XmlUtils.readIntAttribute(parser, "internal", 0);
                    external.sdkVersion = XmlUtils.readIntAttribute(parser, "external", 0);
                    internal.fingerprint = external.fingerprint =
                            XmlUtils.readStringAttribute(parser, "fingerprint");

                    // If the build is setup to drop runtime permissions
                    // on update drop the files before loading them.
                    if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) {
                        if (!Build.FINGERPRINT.equals(mFingerprint)) {
                            if (users == null) {
                                mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(
                                        UserHandle.USER_OWNER);
                            } else {
                                for (UserInfo user : users) {
                                    mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(
                                            user.id);
                                }
                            }
                        }
                    }
                } else if (tagName.equals("database-version")) {
                    mInternalDatabaseVersion = mExternalDatabaseVersion = 0;
                    try {
                        String internalDbVersionString = parser.getAttributeValue(null, "internal");
                        if (internalDbVersionString != null) {
                            mInternalDatabaseVersion = Integer.parseInt(internalDbVersionString);
                        }
                        String externalDbVersionString = parser.getAttributeValue(null, "external");
                        if (externalDbVersionString != null) {
                            mExternalDatabaseVersion = Integer.parseInt(externalDbVersionString);
                        }
                    } catch (NumberFormatException ignored) {
                    }
                    // Upgrade from older XML schema
                    final VersionInfo internal = findOrCreateVersion(
                            StorageManager.UUID_PRIVATE_INTERNAL);
                    final VersionInfo external = findOrCreateVersion(
                            StorageManager.UUID_PRIMARY_PHYSICAL);

                    internal.databaseVersion = XmlUtils.readIntAttribute(parser, "internal", 0);
                    external.databaseVersion = XmlUtils.readIntAttribute(parser, "external", 0);

                } else if (tagName.equals("verifier")) {
                    final String deviceIdentity = parser.getAttributeValue(null, "device");
                    try {
@@ -2639,6 +2630,14 @@ final class Settings {
                    mReadExternalStorageEnforced = "1".equals(enforcement);
                } else if (tagName.equals("keyset-settings")) {
                    mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs);
                } else if (TAG_VERSION.equals(tagName)) {
                    final String volumeUuid = XmlUtils.readStringAttribute(parser,
                            ATTR_VOLUME_UUID);
                    final VersionInfo ver = findOrCreateVersion(volumeUuid);
                    ver.sdkVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION);
                    ver.databaseVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION);
                    ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);

                } else {
                    Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
                            + parser.getName());
@@ -2659,6 +2658,23 @@ final class Settings {
            Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
        }

        // If the build is setup to drop runtime permissions
        // on update drop the files before loading them.
        if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) {
            final VersionInfo internal = getInternalVersion();
            if (!Build.FINGERPRINT.equals(internal.fingerprint)) {
                if (users == null) {
                    mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(
                            UserHandle.USER_OWNER);
                } else {
                    for (UserInfo user : users) {
                        mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(
                                user.id);
                    }
                }
            }
        }

        final int N = mPendingPackages.size();

        for (int i = 0; i < N; i++) {
@@ -3902,6 +3918,29 @@ final class Settings {
        ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
    };

    void dumpVersionLPr(IndentingPrintWriter pw) {
        pw.increaseIndent();
        for (int i= 0; i < mVersion.size(); i++) {
            final String volumeUuid = mVersion.keyAt(i);
            final VersionInfo ver = mVersion.valueAt(i);
            if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, volumeUuid)) {
                pw.println("Internal:");
            } else if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) {
                pw.println("External:");
            } else {
                pw.println("UUID " + volumeUuid + ":");
            }
            pw.increaseIndent();
            pw.printPair("sdkVersion", ver.sdkVersion);
            pw.printPair("databaseVersion", ver.databaseVersion);
            pw.println();
            pw.printPair("fingerprint", ver.fingerprint);
            pw.println();
            pw.decreaseIndent();
        }
        pw.decreaseIndent();
    }

    void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag,
            ArraySet<String> permissionNames, PackageSetting ps, SimpleDateFormat sdf,
            Date date, List<UserInfo> users) {