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

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

Merge "[AppsFilter] separate classes for read and write" into tm-dev am: 4c71401d am: 0539d49a

parents 3d14fd38 0539d49a
Loading
Loading
Loading
Loading
+773 −0

File added.

Preview size limit exceeded, changes collapsed.

+47 −945

File changed.

Preview size limit exceeded, changes collapsed.

+93 −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.annotation.Nullable;

import java.io.PrintWriter;

/**
 * Overrides the unlocked methods in {@link AppsFilterBase} and guards them with locks.
 * These are used by {@link AppsFilterImpl} which contains modifications to the class members
 */
abstract class AppsFilterLocked extends AppsFilterBase {
    /**
     * Guards the accesses for the list/set class members
     */
    protected final Object mLock = new Object();
    /**
     * Guards the access for {@link AppsFilterBase#mShouldFilterCache};
     */
    protected Object mCacheLock = new Object();

    @Override
    protected boolean isForceQueryable(int appId) {
        synchronized (mLock) {
            return super.isForceQueryable(appId);
        }
    }

    @Override
    protected boolean isQueryableViaPackage(int callingAppId, int targetAppId) {
        synchronized (mLock) {
            return super.isQueryableViaPackage(callingAppId, targetAppId);
        }
    }

    @Override
    protected boolean isQueryableViaComponent(int callingAppId, int targetAppId) {
        synchronized (mLock) {
            return super.isQueryableViaComponent(callingAppId, targetAppId);
        }
    }

    @Override
    protected boolean isImplicitlyQueryable(int callingAppId, int targetAppId) {
        synchronized (mLock) {
            return super.isImplicitlyQueryable(callingAppId, targetAppId);
        }
    }

    @Override
    protected boolean isRetainedImplicitlyQueryable(int callingAppId, int targetAppId) {
        synchronized (mLock) {
            return super.isRetainedImplicitlyQueryable(callingAppId, targetAppId);
        }
    }

    @Override
    protected boolean isQueryableViaUsesLibrary(int callingAppId, int targetAppId) {
        synchronized (mLock) {
            return super.isQueryableViaUsesLibrary(callingAppId, targetAppId);
        }
    }

    @Override
    protected boolean shouldFilterApplicationUsingCache(int callingUid, int appId, int userId) {
        synchronized (mCacheLock) {
            return super.shouldFilterApplicationUsingCache(callingUid, appId, userId);
        }
    }

    @Override
    protected void dumpQueryables(PrintWriter pw, @Nullable Integer filteringAppId, int[] users,
            ToString<Integer> expandPackages) {
        synchronized (mLock) {
            dumpQueryables(pw, filteringAppId, users, expandPackages);
        }
    }
}
+60 −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 com.android.server.utils.SnapshotCache;

import java.util.Arrays;

/**
 * Implements the copy-constructor that generates a snapshot of AppsFilter
 */
public final class AppsFilterSnapshotImpl extends AppsFilterBase {
    AppsFilterSnapshotImpl(AppsFilterImpl orig) {
        synchronized (orig.mLock) {
            mImplicitlyQueryable = orig.mImplicitQueryableSnapshot.snapshot();
            mImplicitQueryableSnapshot = new SnapshotCache.Sealed<>();
            mRetainedImplicitlyQueryable = orig.mRetainedImplicitlyQueryableSnapshot.snapshot();
            mRetainedImplicitlyQueryableSnapshot = new SnapshotCache.Sealed<>();
            mQueriesViaPackage = orig.mQueriesViaPackageSnapshot.snapshot();
            mQueriesViaPackageSnapshot = new SnapshotCache.Sealed<>();
            mQueriesViaComponent = orig.mQueriesViaComponentSnapshot.snapshot();
            mQueriesViaComponentSnapshot = new SnapshotCache.Sealed<>();
            mQueryableViaUsesLibrary = orig.mQueryableViaUsesLibrarySnapshot.snapshot();
            mQueryableViaUsesLibrarySnapshot = new SnapshotCache.Sealed<>();
            mForceQueryable = orig.mForceQueryableSnapshot.snapshot();
            mForceQueryableSnapshot = new SnapshotCache.Sealed<>();
            mProtectedBroadcasts = orig.mProtectedBroadcastsSnapshot.snapshot();
            mProtectedBroadcastsSnapshot = new SnapshotCache.Sealed<>();
        }
        mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute;
        mForceQueryableByDevicePackageNames =
                Arrays.copyOf(orig.mForceQueryableByDevicePackageNames,
                        orig.mForceQueryableByDevicePackageNames.length);
        mSystemAppsQueryable = orig.mSystemAppsQueryable;
        mFeatureConfig = orig.mFeatureConfig.snapshot();
        mOverlayReferenceMapper = orig.mOverlayReferenceMapper;
        mSystemSigningDetails = orig.mSystemSigningDetails;
        synchronized (orig.mCacheLock) {
            mShouldFilterCache = orig.mShouldFilterCacheSnapshot.snapshot();
            mShouldFilterCacheSnapshot = new SnapshotCache.Sealed<>();
        }

        mBackgroundExecutor = null;
        mSystemReady = orig.mSystemReady;
    }
}
+172 −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.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Intent;
import android.content.IntentFilter;

import com.android.internal.util.ArrayUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
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.ParsedProvider;
import com.android.server.utils.WatchedArrayList;

import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

final class AppsFilterUtils {
    public static boolean requestsQueryAllPackages(@NonNull AndroidPackage pkg) {
        // we're not guaranteed to have permissions yet analyzed at package add, so we inspect the
        // package directly
        return pkg.getRequestedPermissions().contains(
                Manifest.permission.QUERY_ALL_PACKAGES);
    }

    /** Returns true if the querying package may query for the potential target package */
    public static boolean canQueryViaComponents(AndroidPackage querying,
            AndroidPackage potentialTarget, WatchedArrayList<String> protectedBroadcasts) {
        if (!querying.getQueriesIntents().isEmpty()) {
            for (Intent intent : querying.getQueriesIntents()) {
                if (matchesPackage(intent, potentialTarget, protectedBroadcasts)) {
                    return true;
                }
            }
        }
        if (!querying.getQueriesProviders().isEmpty()
                && matchesProviders(querying.getQueriesProviders(), potentialTarget)) {
            return true;
        }
        return false;
    }

    public static boolean canQueryViaPackage(AndroidPackage querying,
            AndroidPackage potentialTarget) {
        return !querying.getQueriesPackages().isEmpty()
                && querying.getQueriesPackages().contains(potentialTarget.getPackageName());
    }

    public static boolean canQueryAsInstaller(PackageStateInternal querying,
            AndroidPackage potentialTarget) {
        final InstallSource installSource = querying.getInstallSource();
        if (potentialTarget.getPackageName().equals(installSource.installerPackageName)) {
            return true;
        }
        if (!installSource.isInitiatingPackageUninstalled
                && potentialTarget.getPackageName().equals(installSource.initiatingPackageName)) {
            return true;
        }
        return false;
    }

    public static boolean canQueryViaUsesLibrary(AndroidPackage querying,
            AndroidPackage potentialTarget) {
        if (potentialTarget.getLibraryNames().isEmpty()) {
            return false;
        }
        final List<String> libNames = potentialTarget.getLibraryNames();
        for (int i = 0, size = libNames.size(); i < size; i++) {
            final String libName = libNames.get(i);
            if (querying.getUsesLibraries().contains(libName)
                    || querying.getUsesOptionalLibraries().contains(libName)) {
                return true;
            }
        }
        return false;
    }

    private static boolean matchesProviders(
            Set<String> queriesAuthorities, AndroidPackage potentialTarget) {
        for (int p = ArrayUtils.size(potentialTarget.getProviders()) - 1; p >= 0; p--) {
            ParsedProvider provider = potentialTarget.getProviders().get(p);
            if (!provider.isExported()) {
                continue;
            }
            if (provider.getAuthority() == null) {
                continue;
            }
            StringTokenizer authorities = new StringTokenizer(provider.getAuthority(), ";",
                    false);
            while (authorities.hasMoreElements()) {
                if (queriesAuthorities.contains(authorities.nextToken())) {
                    return true;
                }
            }
        }
        return false;
    }

    private static boolean matchesPackage(Intent intent, AndroidPackage potentialTarget,
            WatchedArrayList<String> protectedBroadcasts) {
        if (matchesAnyComponents(
                intent, potentialTarget.getServices(), null /*protectedBroadcasts*/)) {
            return true;
        }
        if (matchesAnyComponents(
                intent, potentialTarget.getActivities(), null /*protectedBroadcasts*/)) {
            return true;
        }
        if (matchesAnyComponents(intent, potentialTarget.getReceivers(), protectedBroadcasts)) {
            return true;
        }
        if (matchesAnyComponents(
                intent, potentialTarget.getProviders(), null /*protectedBroadcasts*/)) {
            return true;
        }
        return false;
    }

    private static boolean matchesAnyComponents(Intent intent,
            List<? extends ParsedMainComponent> components,
            WatchedArrayList<String> protectedBroadcasts) {
        for (int i = ArrayUtils.size(components) - 1; i >= 0; i--) {
            ParsedMainComponent component = components.get(i);
            if (!component.isExported()) {
                continue;
            }
            if (matchesAnyFilter(intent, component, protectedBroadcasts)) {
                return true;
            }
        }
        return false;
    }

    private static boolean matchesAnyFilter(Intent intent, ParsedComponent component,
            WatchedArrayList<String> protectedBroadcasts) {
        List<ParsedIntentInfo> intents = component.getIntents();
        for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) {
            IntentFilter intentFilter = intents.get(i).getIntentFilter();
            if (matchesIntentFilter(intent, intentFilter, protectedBroadcasts)) {
                return true;
            }
        }
        return false;
    }

    private static boolean matchesIntentFilter(Intent intent, IntentFilter intentFilter,
            @Nullable WatchedArrayList<String> protectedBroadcasts) {
        return intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
                intent.getData(), intent.getCategories(), "AppsFilter", true,
                protectedBroadcasts != null ? protectedBroadcasts.untrackedStorage() : null) > 0;
    }
}
Loading