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

Commit 0001d508 authored by Songchun Fan's avatar Songchun Fan Committed by Automerger Merge Worker
Browse files

Merge "[pm] refactor mAppIds to be more readable" into tm-dev am: 4e45ade9

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

Change-Id: I42fa13966818ab1074fd70c7141fd348d4467d19
parents 4d308014 4e45ade9
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.pm;

import android.os.Process;

import com.android.server.utils.WatchedSparseArray;

/**
 * A wrapper over {@link WatchedSparseArray} that tracks the current maximum App ID.
 */
public class AppIdSettingMap extends WatchedSparseArray<SettingBase> {
    private int mCurrentMaxAppId;

    @Override
    public void put(int key, SettingBase value) {
        if (key > mCurrentMaxAppId) {
            mCurrentMaxAppId = key;
        }
        super.put(key, value);
    }

    @Override
    public AppIdSettingMap snapshot() {
        AppIdSettingMap l = new AppIdSettingMap();
        snapshot(l, this);
        return l;
    }

    /**
     * @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;
    }

    /**
     * @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;
        } else {
            return mCurrentMaxAppId + 1;
        }
    }
}
+29 −65
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
@@ -113,11 +112,9 @@ import com.android.server.pm.permission.LegacyPermissionState.PermissionState;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserState;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.PackageUserStateUtils;
import com.android.server.pm.pkg.SuspendParams;
import com.android.server.pm.pkg.component.ParsedComponent;
import com.android.server.pm.pkg.component.ParsedIntentInfo;
import com.android.server.pm.pkg.component.ParsedMainComponent;
import com.android.server.pm.pkg.component.ParsedPermission;
import com.android.server.pm.pkg.component.ParsedProcess;
import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils;
@@ -476,9 +473,9 @@ public final class Settings implements Watchable, Snappable {
    @Watched
    final WatchedArrayMap<String, SharedUserSetting> mSharedUsers = new WatchedArrayMap<>();
    @Watched
    private final WatchedArrayList<SettingBase> mAppIds;
    private final AppIdSettingMap mAppIds;
    @Watched
    private final WatchedSparseArray<SettingBase> mOtherAppIds;
    private final AppIdSettingMap mOtherAppIds;

    // For reading/writing settings file.
    @Watched
@@ -594,8 +591,8 @@ public final class Settings implements Watchable, Snappable {

        mLock = new PackageManagerTracedLock();
        mPackages.putAll(pkgSettings);
        mAppIds = new WatchedArrayList<>();
        mOtherAppIds = new WatchedSparseArray<>();
        mAppIds = new AppIdSettingMap();
        mOtherAppIds = new AppIdSettingMap();
        mSystemDir = null;
        mPermissions = null;
        mRuntimePermissionsPersistence = null;
@@ -631,8 +628,8 @@ public final class Settings implements Watchable, Snappable {
        mKeySetManagerService = new KeySetManagerService(mPackages);

        mLock = lock;
        mAppIds = new WatchedArrayList<>();
        mOtherAppIds = new WatchedSparseArray<>();
        mAppIds = new AppIdSettingMap();
        mOtherAppIds = new AppIdSettingMap();
        mPermissions = new LegacyPermissionSettings(lock);
        mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
                runtimePermissionsPersistence, new Consumer<Integer>() {
@@ -1278,7 +1275,8 @@ public final class Settings implements Watchable, Snappable {
    // Utility method that adds a PackageSetting to mPackages and
    // completes updating the shared user attributes and any restored
    // app link verification state
    private void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) {
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) {
        mPackages.put(p.getPackageName(), p);
        if (sharedUser != null) {
            SharedUserSetting existingSharedUserSetting = getSharedUserSettingLPr(p);
@@ -1301,7 +1299,7 @@ public final class Settings implements Watchable, Snappable {
            p.setAppId(sharedUser.mAppId);
        }

        // If the we know about this user id, we have to update it as it
        // If we know about this user id, we have to update it as it
        // has to point to the same PackageSetting instance as the package.
        Object userIdPs = getSettingLPr(p.getAppId());
        if (sharedUser == null) {
@@ -1366,20 +1364,13 @@ public final class Settings implements Watchable, Snappable {
        }

        if (appId >= Process.FIRST_APPLICATION_UID) {
            int size = mAppIds.size();
            final int index = appId - Process.FIRST_APPLICATION_UID;
            // fill the array until our index becomes valid
            while (index >= size) {
                mAppIds.add(null);
                size++;
            }
            if (mAppIds.get(index) != null) {
            if (mAppIds.get(appId) != null) {
                PackageManagerService.reportSettingsProblem(Log.WARN,
                        "Adding duplicate app id: " + appId
                        + " name=" + name);
                return false;
            }
            mAppIds.set(index, obj);
            mAppIds.put(appId, obj);
        } else {
            if (mOtherAppIds.get(appId) != null) {
                PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -1395,9 +1386,7 @@ public final class Settings implements Watchable, Snappable {
    /** Gets the setting associated with the provided App ID */
    public SettingBase getSettingLPr(int appId) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            final int size = mAppIds.size();
            final int index = appId - Process.FIRST_APPLICATION_UID;
            return index < size ? mAppIds.get(index) : null;
            return mAppIds.get(appId);
        } else {
            return mOtherAppIds.get(appId);
        }
@@ -1406,9 +1395,7 @@ public final class Settings implements Watchable, Snappable {
    /** Unregisters the provided app ID. */
    void removeAppIdLPw(int appId) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            final int size = mAppIds.size();
            final int index = appId - Process.FIRST_APPLICATION_UID;
            if (index < size) mAppIds.set(index, null);
            mAppIds.remove(appId);
        } else {
            mOtherAppIds.remove(appId);
        }
@@ -1417,9 +1404,14 @@ public final class Settings implements Watchable, Snappable {

    private void replaceAppIdLPw(int appId, SettingBase obj) {
        if (appId >= Process.FIRST_APPLICATION_UID) {
            final int size = mAppIds.size();
            final int index = appId - Process.FIRST_APPLICATION_UID;
            if (index < size) mAppIds.set(index, obj);
            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);
        }
@@ -4304,22 +4296,21 @@ public final class Settings implements Watchable, Snappable {

    /** Returns a new AppID or -1 if we could not find an available AppID to assign */
    private int acquireAndRegisterNewAppIdLPw(SettingBase obj) {
        // Let's be stupidly inefficient for now...
        final int size = mAppIds.size();
        for (int i = mFirstAvailableUid - Process.FIRST_APPLICATION_UID; i < size; i++) {
            if (mAppIds.get(i) == null) {
                mAppIds.set(i, obj);
                return Process.FIRST_APPLICATION_UID + i;
        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 (size > (Process.LAST_APPLICATION_UID - Process.FIRST_APPLICATION_UID)) {
        if (nextAvailableAppId > Process.LAST_APPLICATION_UID) {
            return -1;
        }

        mAppIds.add(obj);
        return Process.FIRST_APPLICATION_UID + size;
        mAppIds.put(nextAvailableAppId, obj);
        return nextAvailableAppId;
    }

    public VerifierDeviceIdentity getVerifierDeviceIdentityLPw(@NonNull Computer computer) {
@@ -4354,33 +4345,6 @@ public final class Settings implements Watchable, Snappable {
        return getDisabledSystemPkgLPr(enabledPackageSetting.getPackageName());
    }

    boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, long flags, int userId) {
        final PackageSetting ps = mPackages.get(componentInfo.packageName);
        if (ps == null) return false;

        final PackageUserStateInternal userState = ps.readUserState(userId);
        return PackageUserStateUtils.isMatch(userState, componentInfo, flags);
    }

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean isEnabledAndMatchLPr(AndroidPackage pkg, ParsedMainComponent component,
            long flags, int userId) {
        final PackageSetting ps = mPackages.get(component.getPackageName());
        if (ps == null) return false;

        final PackageUserStateInternal userState = ps.readUserState(userId);
        return PackageUserStateUtils.isMatch(userState, pkg.isSystem(), pkg.isEnabled(), component,
                flags);
    }

    boolean isOrphaned(String packageName) {
        final PackageSetting pkg = mPackages.get(packageName);
        if (pkg == null) {
            throw new IllegalArgumentException("Unknown package: " + packageName);
        }
        return pkg.getInstallSource().isOrphaned;
    }

    int getApplicationEnabledSettingLPr(String packageName, int userId)
            throws PackageManager.NameNotFoundException {
        final PackageSetting pkg = mPackages.get(packageName);
+54 −1
Original line number Diff line number Diff line
@@ -31,11 +31,11 @@ import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.annotation.NonNull;
@@ -1103,6 +1103,59 @@ public class PackageManagerSettingsTests {
        assertThat(countDownLatch.getCount(), is(0L));
    }

    @Test
    public void testRegisterAndRemoveAppId() throws PackageManagerException {
        // Test that the first new app UID should start from FIRST_APPLICATION_UID
        final Settings settings = makeSettings();
        final PackageSetting ps = createPackageSetting("com.foo");
        assertTrue(settings.registerAppIdLPw(ps, false));
        assertEquals(10000, ps.getAppId());
        // Set up existing app IDs: 10000, 10001, 10003
        final PackageSetting ps1 = createPackageSetting("com.foo1");
        ps1.setAppId(10001);
        final PackageSetting ps2 = createPackageSetting("com.foo2");
        ps2.setAppId(10003);
        final PackageSetting ps3 = createPackageSetting("com.foo3");
        assertEquals(0, ps3.getAppId());
        assertTrue(settings.registerAppIdLPw(ps1, false));
        assertTrue(settings.registerAppIdLPw(ps2, false));
        assertTrue(settings.registerAppIdLPw(ps3, false));
        assertEquals(10001, ps1.getAppId());
        assertEquals(10003, ps2.getAppId());
        // Expecting the new one to start with the next available uid
        assertEquals(10002, ps3.getAppId());
        // Remove and insert a new one and the new one should not reuse the same uid
        settings.removeAppIdLPw(10002);
        final PackageSetting ps4 = createPackageSetting("com.foo4");
        assertTrue(settings.registerAppIdLPw(ps4, false));
        assertEquals(10004, ps4.getAppId());
        // Keep adding more
        final PackageSetting ps5 = createPackageSetting("com.foo5");
        assertTrue(settings.registerAppIdLPw(ps5, false));
        assertEquals(10005, ps5.getAppId());
        // Remove the last one and the new one should use incremented uid
        settings.removeAppIdLPw(10005);
        final PackageSetting ps6 = createPackageSetting("com.foo6");
        assertTrue(settings.registerAppIdLPw(ps6, false));
        assertEquals(10006, ps6.getAppId());
    }

    /**
     * Test replacing a PackageSetting with a SharedUserSetting in mAppIds
     */
    @Test
    public void testAddPackageSetting() throws PackageManagerException {
        final Settings settings = makeSettings();
        final SharedUserSetting sus1 = new SharedUserSetting(
                "TestUser", 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
        sus1.mAppId = 10001;
        final PackageSetting ps1 = createPackageSetting("com.foo");
        ps1.setAppId(10001);
        assertTrue(settings.registerAppIdLPw(ps1, false));
        settings.addPackageSettingLPw(ps1, sus1);
        assertSame(sus1, settings.getSharedUserSettingLPr(ps1));
    }

    private void verifyUserState(PackageUserState userState,
            boolean notLaunched, boolean stopped, boolean installed) {
        assertThat(userState.getEnabledState(), is(0));