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

Commit 6d332e6d authored by Lee Shombert's avatar Lee Shombert
Browse files

Add a WatchedLongSparseArray

Bug: 179648149

Add a WatchedLongSparseArray class and use it in
PackageManagerService.  This includes a unit test for the new class.

Test: atest
 * FrameworksServicesTests:AppsFilterTest
 * FrameworksServicesTests:PackageInstallerSessionTest
 * FrameworksServicesTests:PackageManagerServiceTest
 * FrameworksServicesTests:PackageManagerSettingsTests
 * FrameworksServicesTests:ScanTests
 * FrameworksServicesTests:UserSystemPackageInstallerTest
 * PackageManagerServiceBootTest
 * UserLifecycleTests#startUser
 * UserLifecycleTests#stopUser
 * UserLifecycleTests#switchUser
 * android.appsecurity.cts.EphemeralTest
 * android.appsecurity.cts.InstantAppUserTest
 * FrameworksServicesTests:WatcherTest

Change-Id: If0dfde203db7a85ded3cf409981d58518a13990b
parent 62e67203
Loading
Loading
Loading
Loading
+40 −37
Original line number Diff line number Diff line
@@ -316,7 +316,6 @@ import android.util.ExceptionUtils;
import android.util.IntArray;
import android.util.Log;
import android.util.LogPrinter;
import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.MathUtils;
import android.util.PackageUtils;
@@ -401,6 +400,7 @@ import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.utils.Watchable;
import com.android.server.utils.Watched;
import com.android.server.utils.WatchedArrayMap;
import com.android.server.utils.WatchedLongSparseArray;
import com.android.server.utils.WatchedSparseBooleanArray;
import com.android.server.utils.Watcher;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -1402,10 +1402,10 @@ public class PackageManagerService extends IPackageManager.Stub
    // Currently known shared libraries.
    @Watched
    final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>> mSharedLibraries =
            new WatchedArrayMap<>();
    final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
            mSharedLibraries = new WatchedArrayMap<>();
    @Watched
    final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>>
    final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
            mStaticLibsByDeclaringPackage = new WatchedArrayMap<>();
    // Mapping from instrumentation class names to info about them.
@@ -1786,8 +1786,8 @@ public class PackageManagerService extends IPackageManager.Stub
        public final Settings settings;
        public final SparseIntArray isolatedOwners;
        public final WatchedArrayMap<String, AndroidPackage> packages;
        public final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>> sharedLibs;
        public final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>> staticLibs;
        public final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibs;
        public final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> staticLibs;
        public final WatchedArrayMap<ComponentName, ParsedInstrumentation> instrumentation;
        public final WatchedSparseBooleanArray webInstantAppsDisabled;
        public final ComponentName resolveComponentName;
@@ -2005,9 +2005,9 @@ public class PackageManagerService extends IPackageManager.Stub
        private final WatchedArrayMap<String, AndroidPackage> mPackages;
        private final WatchedArrayMap<ComponentName, ParsedInstrumentation>
                mInstrumentation;
        private final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>>
        private final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
                mStaticLibsByDeclaringPackage;
        private final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>>
        private final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
                mSharedLibraries;
        private final ComponentName mLocalResolveComponentName;
        private final ActivityInfo mResolveActivity;
@@ -3546,7 +3546,7 @@ public class PackageManagerService extends IPackageManager.Stub
            packageName = normalizedPackageName != null ? normalizedPackageName : packageName;
            // Is this a static library?
            LongSparseArray<SharedLibraryInfo> versionedLib =
            WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
                    mStaticLibsByDeclaringPackage.get(packageName);
            if (versionedLib == null || versionedLib.size() <= 0) {
                return packageName;
@@ -8039,7 +8039,7 @@ public class PackageManagerService extends IPackageManager.Stub
            final int[] allUsers = mUserManager.getUserIds();
            final int libCount = mSharedLibraries.size();
            for (int i = 0; i < libCount; i++) {
                final LongSparseArray<SharedLibraryInfo> versionedLib
                final WatchedLongSparseArray<SharedLibraryInfo> versionedLib
                        = mSharedLibraries.valueAt(i);
                if (versionedLib == null) {
                    continue;
@@ -8304,7 +8304,8 @@ public class PackageManagerService extends IPackageManager.Stub
            final int libCount = mSharedLibraries.size();
            for (int i = 0; i < libCount; i++) {
                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
                WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
                        mSharedLibraries.valueAt(i);
                if (versionedLib == null) {
                    continue;
                }
@@ -8373,7 +8374,8 @@ public class PackageManagerService extends IPackageManager.Stub
            int libraryCount = mSharedLibraries.size();
            for (int i = 0; i < libraryCount; i++) {
                LongSparseArray<SharedLibraryInfo> versionedLibrary = mSharedLibraries.valueAt(i);
                WatchedLongSparseArray<SharedLibraryInfo> versionedLibrary =
                        mSharedLibraries.valueAt(i);
                if (versionedLibrary == null) {
                    continue;
                }
@@ -8534,7 +8536,8 @@ public class PackageManagerService extends IPackageManager.Stub
            Set<String> libs = null;
            final int libCount = mSharedLibraries.size();
            for (int i = 0; i < libCount; i++) {
                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
                WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
                        mSharedLibraries.valueAt(i);
                if (versionedLib == null) {
                    continue;
                }
@@ -12199,10 +12202,10 @@ public class PackageManagerService extends IPackageManager.Stub
    @Nullable
    private static SharedLibraryInfo getSharedLibraryInfo(String name, long version,
            Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
            @Nullable Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries) {
            Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
            @Nullable Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries) {
        if (newLibraries != null) {
            final LongSparseArray<SharedLibraryInfo> versionedLib = newLibraries.get(name);
            final WatchedLongSparseArray<SharedLibraryInfo> versionedLib = newLibraries.get(name);
            SharedLibraryInfo info = null;
            if (versionedLib != null) {
                info = versionedLib.get(version);
@@ -12211,7 +12214,7 @@ public class PackageManagerService extends IPackageManager.Stub
                return info;
            }
        }
        final LongSparseArray<SharedLibraryInfo> versionedLib = existingLibraries.get(name);
        final WatchedLongSparseArray<SharedLibraryInfo> versionedLib = existingLibraries.get(name);
        if (versionedLib == null) {
            return null;
        }
@@ -12219,7 +12222,7 @@ public class PackageManagerService extends IPackageManager.Stub
    }
    private SharedLibraryInfo getLatestSharedLibraVersionLPr(AndroidPackage pkg) {
        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
        WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
                pkg.getStaticSharedLibName());
        if (versionedLib == null) {
            return null;
@@ -12524,8 +12527,8 @@ public class PackageManagerService extends IPackageManager.Stub
    private static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(AndroidPackage pkg,
            Map<String, AndroidPackage> availablePackages,
            @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
            @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries)
            @NonNull final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
            @Nullable final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries)
            throws PackageManagerException {
        if (pkg == null) {
            return null;
@@ -12622,8 +12625,8 @@ public class PackageManagerService extends IPackageManager.Stub
            @NonNull String packageName, boolean required, int targetSdk,
            @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries,
            @NonNull final Map<String, AndroidPackage> availablePackages,
            @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
            @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries)
            @NonNull final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
            @Nullable final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries)
            throws PackageManagerException {
        final int libCount = requestedLibraries.size();
        for (int i = 0; i < libCount; i++) {
@@ -14044,7 +14047,7 @@ public class PackageManagerService extends IPackageManager.Stub
                long minVersionCode = Long.MIN_VALUE;
                long maxVersionCode = Long.MAX_VALUE;
                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
                WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
                        pkg.getStaticSharedLibName());
                if (versionedLib != null) {
                    final int versionCount = versionedLib.size();
@@ -14272,8 +14275,8 @@ public class PackageManagerService extends IPackageManager.Stub
    }
    private static boolean sharedLibExists(final String name, final long version,
            Map<String, LongSparseArray<SharedLibraryInfo>> librarySource) {
        LongSparseArray<SharedLibraryInfo> versionedLib = librarySource.get(name);
            Map<String, WatchedLongSparseArray<SharedLibraryInfo>> librarySource) {
        WatchedLongSparseArray<SharedLibraryInfo> versionedLib = librarySource.get(name);
        if (versionedLib != null && versionedLib.indexOfKey(version) >= 0) {
            return true;
        }
@@ -14283,9 +14286,9 @@ public class PackageManagerService extends IPackageManager.Stub
    @GuardedBy("mLock")
    private void commitSharedLibraryInfoLocked(SharedLibraryInfo libraryInfo) {
        final String name = libraryInfo.getName();
        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
        WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
        if (versionedLib == null) {
            versionedLib = new LongSparseArray<>();
            versionedLib = new WatchedLongSparseArray<>();
            mSharedLibraries.put(name, versionedLib);
        }
        final String declaringPackageName = libraryInfo.getDeclaringPackage().getPackageName();
@@ -14296,7 +14299,7 @@ public class PackageManagerService extends IPackageManager.Stub
    }
    private boolean removeSharedLibraryLPw(String name, long version) {
        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
        WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
        if (versionedLib == null) {
            return false;
        }
@@ -18291,7 +18294,7 @@ public class PackageManagerService extends IPackageManager.Stub
        public final Map<String, ScanResult> scannedPackages;
        public final Map<String, AndroidPackage> allPackages;
        public final Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource;
        public final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource;
        public final Map<String, InstallArgs> installArgs;
        public final Map<String, PackageInstalledInfo> installResults;
        public final Map<String, PrepareResult> preparedPackages;
@@ -18302,7 +18305,7 @@ public class PackageManagerService extends IPackageManager.Stub
                Map<String, InstallArgs> installArgs,
                Map<String, PackageInstalledInfo> installResults,
                Map<String, PrepareResult> preparedPackages,
                Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
                Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
                Map<String, AndroidPackage> allPackages,
                Map<String, VersionInfo> versionInfos,
                Map<String, PackageSetting> lastStaticSharedLibSettings) {
@@ -18317,7 +18320,7 @@ public class PackageManagerService extends IPackageManager.Stub
        }
        private ReconcileRequest(Map<String, ScanResult> scannedPackages,
                Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
                Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
                Map<String, AndroidPackage> allPackages,
                Map<String, VersionInfo> versionInfos,
                Map<String, PackageSetting> lastStaticSharedLibSettings) {
@@ -18414,7 +18417,7 @@ public class PackageManagerService extends IPackageManager.Stub
        combinedPackages.putAll(request.allPackages);
        final Map<String, LongSparseArray<SharedLibraryInfo>> incomingSharedLibraries =
        final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> incomingSharedLibraries =
                new ArrayMap<>();
        for (String installPackageName : scannedPackages.keySet()) {
@@ -18638,7 +18641,7 @@ public class PackageManagerService extends IPackageManager.Stub
     */
    private static List<SharedLibraryInfo> getAllowedSharedLibInfos(
            ScanResult scanResult,
            Map<String, LongSparseArray<SharedLibraryInfo>> existingSharedLibraries) {
            Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingSharedLibraries) {
        // Let's used the parsed package as scanResult.pkgSetting may be null
        final ParsedPackage parsedPackage = scanResult.request.parsedPackage;
        if (scanResult.staticSharedLibraryInfo == null
@@ -18708,7 +18711,7 @@ public class PackageManagerService extends IPackageManager.Stub
     * added.
     */
    private static boolean addSharedLibraryToPackageVersionMap(
            Map<String, LongSparseArray<SharedLibraryInfo>> target,
            Map<String, WatchedLongSparseArray<SharedLibraryInfo>> target,
            SharedLibraryInfo library) {
        final String name = library.getName();
        if (target.containsKey(name)) {
@@ -18720,7 +18723,7 @@ public class PackageManagerService extends IPackageManager.Stub
                return false;
            }
        } else {
            target.put(name, new LongSparseArray<>());
            target.put(name, new WatchedLongSparseArray<>());
        }
        target.get(name).put(library.getLongVersion(), library);
        return true;
@@ -23843,7 +23846,7 @@ public class PackageManagerService extends IPackageManager.Stub
                final int numSharedLibraries = mSharedLibraries.size();
                for (int index = 0; index < numSharedLibraries; index++) {
                    final String libName = mSharedLibraries.keyAt(index);
                    LongSparseArray<SharedLibraryInfo> versionedLib
                    WatchedLongSparseArray<SharedLibraryInfo> versionedLib
                            = mSharedLibraries.get(libName);
                    if (versionedLib == null) {
                        continue;
@@ -24192,7 +24195,7 @@ public class PackageManagerService extends IPackageManager.Stub
        final int count = mSharedLibraries.size();
        for (int i = 0; i < count; i++) {
            final String libName = mSharedLibraries.keyAt(i);
            LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
            WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
            if (versionedLib == null) {
                continue;
            }
+418 −0

File added.

Preview size limit exceeded, changes collapsed.

+163 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static org.junit.Assert.fail;

import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LongSparseArray;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
@@ -618,6 +619,129 @@ public class WatcherTest {
        }
    }

    @Test
    public void testWatchedLongSparseArray() {
        final String name = "WatchedLongSparseArray";
        WatchableTester tester;

        // Create a few leaves
        Leaf leafA = new Leaf();
        Leaf leafB = new Leaf();
        Leaf leafC = new Leaf();
        Leaf leafD = new Leaf();

        // Test WatchedLongSparseArray
        WatchedLongSparseArray<Leaf> array = new WatchedLongSparseArray<>();
        array.put(INDEX_A, leafA);
        array.put(INDEX_B, leafB);
        tester = new WatchableTester(array, name);
        tester.verify(0, "Initial array - no registration");
        leafA.tick();
        tester.verify(0, "Updates with no registration");
        tester.register();
        tester.verify(0, "Updates with no registration");
        leafA.tick();
        tester.verify(1, "Updates with registration");
        leafB.tick();
        tester.verify(2, "Updates with registration");
        array.remove(INDEX_B);
        tester.verify(3, "Removed b");
        leafB.tick();
        tester.verify(3, "Updates with b not watched");
        array.put(INDEX_B, leafB);
        array.put(INDEX_C, leafB);
        tester.verify(5, "Added b twice");
        leafB.tick();
        tester.verify(6, "Changed b - single notification");
        array.remove(INDEX_C);
        tester.verify(7, "Removed first b");
        leafB.tick();
        tester.verify(8, "Changed b - single notification");
        array.remove(INDEX_B);
        tester.verify(9, "Removed second b");
        leafB.tick();
        tester.verify(9, "Updated leafB - no change");
        array.clear();
        tester.verify(10, "Cleared array");
        leafB.tick();
        tester.verify(10, "Change to b not in array");

        // Special methods
        array.put(INDEX_A, leafA);
        array.put(INDEX_B, leafB);
        array.put(INDEX_C, leafC);
        tester.verify(13, "Added c");
        leafC.tick();
        tester.verify(14, "Ticked c");
        array.setValueAt(array.indexOfKey(INDEX_C), leafD);
        tester.verify(15, "Replaced c with d");
        leafC.tick();
        tester.verify(15, "Ticked c (c not registered)");
        leafD.tick();
        tester.verify(16, "Ticked d and c (c not registered)");
        array.append(INDEX_D, leafC);
        tester.verify(17, "Append c");
        leafC.tick();
        leafD.tick();
        tester.verify(19, "Ticked d and c");
        assertEquals("Verify four elements", 4, array.size());
        // Figure out which elements are at which indices.
        Leaf[] x = new Leaf[4];
        for (int i = 0; i < 4; i++) {
            x[i] = array.valueAt(i);
        }
        array.removeAt(1);
        tester.verify(20, "Removed one element");
        x[1].tick();
        tester.verify(20, "Ticked one removed element");
        x[2].tick();
        tester.verify(21, "Ticked one remaining element");

        // Snapshot
        {
            final WatchedLongSparseArray<Leaf> arraySnap = array.snapshot();
            tester.verify(21, "Generate snapshot (no changes)");
            // Verify that the snapshot is a proper copy of the source.
            assertEquals(name + " snap same size",
                         array.size(), arraySnap.size());
            for (int i = 0; i < array.size(); i++) {
                for (int j = 0; j < arraySnap.size(); j++) {
                    assertTrue(name + " elements differ",
                               array.valueAt(i) != arraySnap.valueAt(j));
                }
                assertTrue(name + " element copy",
                           array.valueAt(i).equals(arraySnap.valueAt(i)));
            }
            leafD.tick();
            tester.verify(22, "Tick after snapshot");
            // Verify that the array snapshot is sealed
            verifySealed(name, ()->arraySnap.put(INDEX_A, leafB));
            assertTrue(!array.isSealed());
            assertTrue(arraySnap.isSealed());
        }
        // Recreate the snapshot since the test corrupted it.
        {
            final WatchedLongSparseArray<Leaf> arraySnap = array.snapshot();
            // Verify that elements are also snapshots
            final Leaf arraySnapElement = arraySnap.valueAt(0);
            verifySealed("ArraySnapshotElement", ()->arraySnapElement.tick());
        }
        // Verify copy-in/out
        {
            final String msg = name + " copy-in/out";
            LongSparseArray<Leaf> base = new LongSparseArray<>();
            array.copyTo(base);
            WatchedLongSparseArray<Leaf> copy = new WatchedLongSparseArray<>();
            copy.copyFrom(base);
            final int end = array.size();
            assertTrue(msg + " size mismatch " + end + " " + copy.size(), end == copy.size());
            for (int i = 0; i < end; i++) {
                final long key = array.keyAt(i);
                assertTrue(msg, array.get(i) == copy.get(i));
            }
        }
    }

    @Test
    public void testWatchedSparseBooleanArray() {
        final String name = "WatchedSparseBooleanArray";
@@ -733,4 +857,43 @@ public class WatcherTest {
            }
        }
    }

    @Test
    public void testNestedArrays() {
        final String name = "NestedArrays";
        WatchableTester tester;

        // Create a few leaves
        Leaf leafA = new Leaf();
        Leaf leafB = new Leaf();
        Leaf leafC = new Leaf();
        Leaf leafD = new Leaf();

        // Test nested arrays.
        WatchedLongSparseArray<Leaf> lsaA = new WatchedLongSparseArray<>();
        lsaA.put(2, leafA);
        WatchedLongSparseArray<Leaf> lsaB = new WatchedLongSparseArray<>();
        lsaB.put(4, leafB);
        WatchedLongSparseArray<Leaf> lsaC = new WatchedLongSparseArray<>();
        lsaC.put(6, leafC);

        WatchedArrayMap<String, WatchedLongSparseArray<Leaf>> array =
                new WatchedArrayMap<>();
        array.put("A", lsaA);
        array.put("B", lsaB);

        // Test WatchedSparseIntArray
        tester = new WatchableTester(array, name);
        tester.verify(0, "Initial array - no registration");
        tester.register();
        tester.verify(0, "Initial array - post registration");
        leafA.tick();
        tester.verify(1, "tick grand-leaf");
        lsaA.put(2, leafD);
        tester.verify(2, "replace leafA");
        leafA.tick();
        tester.verify(2, "tick unregistered leafA");
        leafD.tick();
        tester.verify(3, "tick leafD");
    }
}