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

Commit 294c46cd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "[pm] revert changes to mAppIds" into tm-dev am: 4b33343b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17147171

Change-Id: If413c85b1bc13799bd39c2530ecfe6453683ac66
parents 26949d1b 4b33343b
Loading
Loading
Loading
Loading
+111 −26
Original line number Diff line number Diff line
@@ -17,46 +17,131 @@
package com.android.server.pm;

import android.os.Process;
import android.util.Log;

import com.android.server.utils.WatchedArrayList;
import com.android.server.utils.WatchedSparseArray;
import com.android.server.utils.Watcher;

/**
 * A wrapper over {@link WatchedSparseArray} that tracks the current maximum App ID.
 * A wrapper over {@link WatchedArrayList} that tracks the current (app ID -> SettingBase) mapping
 * for non-system apps. Also tracks system app settings in an {@link WatchedSparseArray}.
 */
public class AppIdSettingMap extends WatchedSparseArray<SettingBase> {
    private int mCurrentMaxAppId;
final class AppIdSettingMap {
    /**
     * We use an ArrayList instead of an SparseArray for non system apps because the number of apps
     * might be big, and only ArrayList gives us a constant lookup time. For a given app ID, the
     * index to the corresponding SettingBase object is (appId - FIRST_APPLICATION_ID). If an app ID
     * doesn't exist (i.e., app is not installed), we fill the corresponding entry with null.
     */
    private WatchedArrayList<SettingBase> mNonSystemSettings = new WatchedArrayList<>();
    private WatchedSparseArray<SettingBase> mSystemSettings = new WatchedSparseArray<>();
    private int mFirstAvailableAppId = Process.FIRST_APPLICATION_UID;

    @Override
    public void put(int key, SettingBase value) {
        if (key > mCurrentMaxAppId) {
            mCurrentMaxAppId = key;
    /** Returns true if the requested AppID was valid and not already registered. */
    public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            int size = mNonSystemSettings.size();
            final int index = appId - Process.FIRST_APPLICATION_UID;
            // fill the array until our index becomes valid
            while (index >= size) {
                mNonSystemSettings.add(null);
                size++;
            }
            if (mNonSystemSettings.get(index) != null) {
                PackageManagerService.reportSettingsProblem(Log.WARN,
                        "Adding duplicate app id: " + appId
                                + " name=" + name);
                return false;
            }
            mNonSystemSettings.set(index, setting);
        } else {
            if (mSystemSettings.get(appId) != null) {
                PackageManagerService.reportSettingsProblem(Log.WARN,
                        "Adding duplicate shared id: " + appId
                                + " name=" + name);
                return false;
            }
        super.put(key, value);
            mSystemSettings.put(appId, setting);
        }
        return true;
    }

    @Override
    public AppIdSettingMap snapshot() {
        AppIdSettingMap l = new AppIdSettingMap();
        snapshot(l, this);
        return l;
    public SettingBase getSetting(int appId) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            final int size = mNonSystemSettings.size();
            final int index = appId - Process.FIRST_APPLICATION_UID;
            return index < size ? mNonSystemSettings.get(index) : null;
        } else {
            return mSystemSettings.get(appId);
        }
    }

    /**
     * @return the maximum of all the App IDs that have been added to the map. 0 if map is empty.
     */
    public int getCurrentMaxAppId() {
        return mCurrentMaxAppId;
    public void removeSetting(int appId) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            final int size = mNonSystemSettings.size();
            final int index = appId - Process.FIRST_APPLICATION_UID;
            if (index < size) {
                mNonSystemSettings.set(index, null);
            }
        } else {
            mSystemSettings.remove(appId);
        }
        setFirstAvailableAppId(appId + 1);
    }

    /**
     * @return the next available App ID that has not been added to the map
     */
    public int getNextAvailableAppId() {
        if (mCurrentMaxAppId == 0) {
            // No app id has been added yet
            return Process.FIRST_APPLICATION_UID;
    // This should be called (at least) whenever an application is removed
    private void setFirstAvailableAppId(int uid) {
        if (uid > mFirstAvailableAppId) {
            mFirstAvailableAppId = uid;
        }
    }

    public void replaceSetting(int appId, SettingBase setting) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            final int size = mNonSystemSettings.size();
            final int index = appId - Process.FIRST_APPLICATION_UID;
            if (index < size) {
                mNonSystemSettings.set(index, setting);
            } else {
            return mCurrentMaxAppId + 1;
                PackageManagerService.reportSettingsProblem(Log.WARN,
                        "Error in package manager settings: calling replaceAppIdLpw to"
                                + " replace SettingBase at appId=" + appId
                                + " but nothing is replaced.");
            }
        } else {
            mSystemSettings.put(appId, setting);
        }
    }

    /** Returns a new AppID or -1 if we could not find an available AppID to assign */
    public int acquireAndRegisterNewAppId(SettingBase obj) {
        final int size = mNonSystemSettings.size();
        for (int i = mFirstAvailableAppId - Process.FIRST_APPLICATION_UID; i < size; i++) {
            if (mNonSystemSettings.get(i) == null) {
                mNonSystemSettings.set(i, obj);
                return Process.FIRST_APPLICATION_UID + i;
            }
        }

        // None left?
        if (size > (Process.LAST_APPLICATION_UID - Process.FIRST_APPLICATION_UID)) {
            return -1;
        }

        mNonSystemSettings.add(obj);
        return Process.FIRST_APPLICATION_UID + size;
    }

    public AppIdSettingMap snapshot() {
        AppIdSettingMap l = new AppIdSettingMap();
        mNonSystemSettings.snapshot(l.mNonSystemSettings, mNonSystemSettings);
        mSystemSettings.snapshot(l.mSystemSettings, mSystemSettings);
        return l;
    }

    public void registerObserver(Watcher observer) {
        mNonSystemSettings.registerObserver(observer);
        mSystemSettings.registerObserver(observer);
    }
}
+11 −97
Original line number Diff line number Diff line
@@ -62,7 +62,6 @@ import android.os.Handler;
import android.os.Message;
import android.os.PatternMatcher;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.SELinux;
import android.os.SystemClock;
import android.os.Trace;
@@ -408,8 +407,6 @@ public final class Settings implements Watchable, Snappable {
        int[] excludedUserIds;
    }

    private static int mFirstAvailableUid = Process.FIRST_APPLICATION_UID;

    /** Map from volume UUID to {@link VersionInfo} */
    @Watched
    private final WatchedArrayMap<String, VersionInfo> mVersion = new WatchedArrayMap<>();
@@ -472,10 +469,8 @@ public final class Settings implements Watchable, Snappable {

    @Watched
    final WatchedArrayMap<String, SharedUserSetting> mSharedUsers = new WatchedArrayMap<>();
    @Watched
    @Watched(manual = true)
    private final AppIdSettingMap mAppIds;
    @Watched
    private final AppIdSettingMap mOtherAppIds;

    // For reading/writing settings file.
    @Watched
@@ -565,7 +560,6 @@ public final class Settings implements Watchable, Snappable {
        mCrossProfileIntentResolvers.registerObserver(mObserver);
        mSharedUsers.registerObserver(mObserver);
        mAppIds.registerObserver(mObserver);
        mOtherAppIds.registerObserver(mObserver);
        mRenamedPackages.registerObserver(mObserver);
        mNextAppLinkGeneration.registerObserver(mObserver);
        mDefaultBrowserApp.registerObserver(mObserver);
@@ -592,7 +586,6 @@ public final class Settings implements Watchable, Snappable {
        mLock = new PackageManagerTracedLock();
        mPackages.putAll(pkgSettings);
        mAppIds = new AppIdSettingMap();
        mOtherAppIds = new AppIdSettingMap();
        mSystemDir = null;
        mPermissions = null;
        mRuntimePermissionsPersistence = null;
@@ -629,7 +622,6 @@ public final class Settings implements Watchable, Snappable {

        mLock = lock;
        mAppIds = new AppIdSettingMap();
        mOtherAppIds = new AppIdSettingMap();
        mPermissions = new LegacyPermissionSettings(lock);
        mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
                runtimePermissionsPersistence, new Consumer<Integer>() {
@@ -710,7 +702,6 @@ public final class Settings implements Watchable, Snappable {
                mCrossProfileIntentResolvers, r.mCrossProfileIntentResolvers);
        mSharedUsers.snapshot(r.mSharedUsers);
        mAppIds = r.mAppIds.snapshot();
        mOtherAppIds = r.mOtherAppIds.snapshot();
        WatchedArrayList.snapshot(
                mPastSignatures, r.mPastSignatures);
        WatchedArrayMap.snapshot(
@@ -782,7 +773,7 @@ public final class Settings implements Watchable, Snappable {
        SharedUserSetting s = mSharedUsers.get(name);
        if (s == null && create) {
            s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
            s.mAppId = acquireAndRegisterNewAppIdLPw(s);
            s.mAppId = mAppIds.acquireAndRegisterNewAppId(s);
            if (s.mAppId < 0) {
                // < 0 means we couldn't assign a userid; throw exception
                throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
@@ -890,7 +881,7 @@ public final class Settings implements Watchable, Snappable {
                pkgPrivateFlags, 0 /*userId*/, usesSdkLibraries, usesSdkLibrariesVersions,
                usesStaticLibraries, usesStaticLibrariesVersions, mimeGroups, domainSetId);
        p.setAppId(uid);
        if (registerExistingAppIdLPw(uid, p, name)) {
        if (mAppIds.registerExistingAppId(uid, p, name)) {
            mPackages.put(name, p);
            return p;
        }
@@ -909,7 +900,7 @@ public final class Settings implements Watchable, Snappable {
        }
        s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
        s.mAppId = uid;
        if (registerExistingAppIdLPw(uid, s, name)) {
        if (mAppIds.registerExistingAppId(uid, s, name)) {
            mSharedUsers.put(name, s);
            return s;
        }
@@ -1210,11 +1201,11 @@ public final class Settings implements Watchable, Snappable {
        final boolean createdNew;
        if (p.getAppId() == 0 || forceNew) {
            // Assign new user ID
            p.setAppId(acquireAndRegisterNewAppIdLPw(p));
            p.setAppId(mAppIds.acquireAndRegisterNewAppId(p));
            createdNew = true;
        } else {
            // Add new setting to list of user IDs
            createdNew = registerExistingAppIdLPw(p.getAppId(), p, p.getPackageName());
            createdNew = mAppIds.registerExistingAppId(p.getAppId(), p, p.getPackageName());
        }
        if (p.getAppId() < 0) {
            PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -1304,11 +1295,11 @@ public final class Settings implements Watchable, Snappable {
        Object userIdPs = getSettingLPr(p.getAppId());
        if (sharedUser == null) {
            if (userIdPs != null && userIdPs != p) {
                replaceAppIdLPw(p.getAppId(), p);
                mAppIds.replaceSetting(p.getAppId(), p);
            }
        } else {
            if (userIdPs != null && userIdPs != sharedUser) {
                replaceAppIdLPw(p.getAppId(), sharedUser);
                mAppIds.replaceSetting(p.getAppId(), sharedUser);
            }
        }
    }
@@ -1357,73 +1348,22 @@ public final class Settings implements Watchable, Snappable {
        mInstallerPackages.remove(packageName);
    }

    /** Returns true if the requested AppID was valid and not already registered. */
    private boolean registerExistingAppIdLPw(int appId, SettingBase obj, Object name) {
        if (appId > Process.LAST_APPLICATION_UID) {
            return false;
        }

        if (appId >= Process.FIRST_APPLICATION_UID) {
            if (mAppIds.get(appId) != null) {
                PackageManagerService.reportSettingsProblem(Log.WARN,
                        "Adding duplicate app id: " + appId
                        + " name=" + name);
                return false;
            }
            mAppIds.put(appId, obj);
        } else {
            if (mOtherAppIds.get(appId) != null) {
                PackageManagerService.reportSettingsProblem(Log.WARN,
                        "Adding duplicate shared id: " + appId
                                + " name=" + name);
                return false;
            }
            mOtherAppIds.put(appId, obj);
        }
        return true;
    }

    /** Gets the setting associated with the provided App ID */
    public SettingBase getSettingLPr(int appId) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            return mAppIds.get(appId);
        } else {
            return mOtherAppIds.get(appId);
        }
        return mAppIds.getSetting(appId);
    }

    /** Unregisters the provided app ID. */
    void removeAppIdLPw(int appId) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            mAppIds.remove(appId);
        } else {
            mOtherAppIds.remove(appId);
        mAppIds.removeSetting(appId);
    }
        setFirstAvailableUid(appId + 1);
    }

    private void replaceAppIdLPw(int appId, SettingBase obj) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            if (appId <= mAppIds.getCurrentMaxAppId()) {
                mAppIds.put(appId, obj);
            } else {
                PackageManagerService.reportSettingsProblem(Log.WARN,
                        "Error in package manager settings: calling replaceAppIdLpw to"
                                + " replace SettingBase at appId=" + appId
                                + " but nothing is replaced.");
            }
        } else {
            mOtherAppIds.put(appId, obj);
        }
    }

    /**
     * Transparently convert a SharedUserSetting into PackageSettings without changing appId.
     * The sharedUser passed to this method has to be {@link SharedUserSetting#isSingleUser()}.
     */
    void convertSharedUserSettingsLPw(SharedUserSetting sharedUser) {
        final PackageSetting ps = sharedUser.getPackageSettings().valueAt(0);
        replaceAppIdLPw(sharedUser.getAppId(), ps);
        mAppIds.replaceSetting(sharedUser.getAppId(), ps);

        // Unlink the SharedUserSetting
        ps.setSharedUserAppId(INVALID_UID);
@@ -4287,32 +4227,6 @@ public final class Settings implements Watchable, Snappable {
        }
    }

    // This should be called (at least) whenever an application is removed
    private void setFirstAvailableUid(int uid) {
        if (uid > mFirstAvailableUid) {
            mFirstAvailableUid = uid;
        }
    }

    /** Returns a new AppID or -1 if we could not find an available AppID to assign */
    private int acquireAndRegisterNewAppIdLPw(SettingBase obj) {
        final int nextAvailableAppId = mAppIds.getNextAvailableAppId();
        for (int uid = mFirstAvailableUid; uid < nextAvailableAppId; uid++) {
            if (mAppIds.get(uid) == null) {
                mAppIds.put(uid, obj);
                return uid;
            }
        }

        // None left?
        if (nextAvailableAppId > Process.LAST_APPLICATION_UID) {
            return -1;
        }

        mAppIds.put(nextAvailableAppId, obj);
        return nextAvailableAppId;
    }

    public VerifierDeviceIdentity getVerifierDeviceIdentityLPw(@NonNull Computer computer) {
        if (mVerifierDeviceIdentity == null) {
            mVerifierDeviceIdentity = VerifierDeviceIdentity.generate();