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

Commit 211c1afd authored by Jonathan Klee's avatar Jonathan Klee
Browse files

feat: Introduce Hide From Microg feature

parent df7b659b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -6421,6 +6421,10 @@ public final class Settings {
         */
        public static final String PREFERRED_REGION = "preferred_region";
        /** @hide */
        public static final String HIDE_MICROG_PACKAGES_FOR_PACKAGE =
                "hide_microg_packages_for_package";
        /**
         * Setting to enable camera flash notification feature.
         * <ul>
@@ -6607,6 +6611,7 @@ public final class Settings {
            PRIVATE_SETTINGS.add(MOUSE_REVERSE_VERTICAL_SCROLLING);
            PRIVATE_SETTINGS.add(MOUSE_SWAP_PRIMARY_BUTTON);
            PRIVATE_SETTINGS.add(PREFERRED_REGION);
            PRIVATE_SETTINGS.add(HIDE_MICROG_PACKAGES_FOR_PACKAGE);
        }
        /**
+15 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.provider.settings.validators.SettingsValidators.FONT_SCALE
import static android.provider.settings.validators.SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_FLOAT_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.URI_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.VIBRATION_INTENSITY_VALIDATOR;
import static android.view.PointerIcon.DEFAULT_POINTER_SCALE;
@@ -268,5 +269,19 @@ public class SystemSettingsValidators {
        VALIDATORS.put(System.NOTIFICATION_COOLDOWN_ALL, BOOLEAN_VALIDATOR);
        VALIDATORS.put(System.NOTIFICATION_COOLDOWN_VIBRATE_UNLOCKED, BOOLEAN_VALIDATOR);
        VALIDATORS.put(System.PREFERRED_REGION, ANY_STRING_VALIDATOR);
        VALIDATORS.put(System.HIDE_MICROG_PACKAGES_FOR_PACKAGE, value -> {
            if (value == null) {
                return true;
            }

            for (String packageName : value.split(",")) {
                final String trimmedPackageName = packageName.trim();
                if (trimmedPackageName.isEmpty()
                        || !PACKAGE_NAME_VALIDATOR.validate(trimmedPackageName)) {
                    return false;
                }
            }
            return true;
        });
    }
}
+89 −0
Original line number Diff line number Diff line
@@ -63,6 +63,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
 */
public abstract class AppsFilterBase implements AppsFilterSnapshot {
    protected static final String TAG = "AppsFilter";
    private static final String GOOGLE_PLAY_SERVICES_PACKAGE = "com.google.android.gms";
    private static final String GOOGLE_PLAY_STORE_PACKAGE = "com.android.vending";
    private static final String GOOGLE_SERVICES_FRAMEWORK_PACKAGE = "com.google.android.gsf";

    // Logs all filtering instead of enforcing
    protected static final boolean DEBUG_ALLOW_ALL = false;
@@ -199,11 +202,81 @@ public abstract class AppsFilterBase implements AppsFilterSnapshot {
    protected volatile boolean mCacheReady = false;
    protected volatile boolean mCacheEnabled = true;
    protected volatile boolean mNeedToUpdateCacheForImplicitAccess = false;
    @NonNull
    protected volatile SparseArray<ArraySet<String>> mHideMicrogPackagesForCallerByUser =
            new SparseArray<>();

    protected static final boolean CACHE_VALID = true;
    protected static final boolean CACHE_INVALID = false;
    protected final AtomicBoolean mCacheValid = new AtomicBoolean(CACHE_INVALID);

    protected static SparseArray<ArraySet<String>> copyPackageNamesByUser(
            @NonNull SparseArray<ArraySet<String>> packageNamesByUser) {
        final SparseArray<ArraySet<String>> copy = new SparseArray<>(packageNamesByUser.size());
        for (int i = 0; i < packageNamesByUser.size(); i++) {
            final ArraySet<String> packageNames = packageNamesByUser.valueAt(i);
            copy.put(packageNamesByUser.keyAt(i),
                    packageNames == null ? null : new ArraySet<>(packageNames));
        }
        return copy;
    }

    private static boolean isMicrogPackageHiddenByConfig(@NonNull String packageName) {
        return GOOGLE_PLAY_SERVICES_PACKAGE.equals(packageName)
                || GOOGLE_PLAY_STORE_PACKAGE.equals(packageName)
                || GOOGLE_SERVICES_FRAMEWORK_PACKAGE.equals(packageName);
    }

    private boolean shouldHideMicrogPackagesForCaller(int callingUserId,
            @Nullable String[] callingPackageNames, @NonNull String targetPackageName) {
        if (!isMicrogPackageHiddenByConfig(targetPackageName)) {
            return false;
        }

        final ArraySet<String> configuredPackageNames =
                mHideMicrogPackagesForCallerByUser.get(callingUserId);

        if (configuredPackageNames == null || configuredPackageNames.isEmpty()
                || callingPackageNames == null) {
            return false;
        }

        for (String callingPackageName : callingPackageNames) {
            if (configuredPackageNames.contains(callingPackageName)) {
                return true;
            }
        }
        return false;
    }

    private boolean shouldHideMicrogPackagesForCaller(int callingUid,
            @Nullable PackageStateInternal callingPkgSetting,
            @NonNull ArraySet<PackageStateInternal> callingSharedPkgSettings,
            @NonNull PackageStateInternal targetPkgSetting) {
        if (!isMicrogPackageHiddenByConfig(targetPkgSetting.getPackageName())) {
            return false;
        }

        final ArraySet<String> configuredPackageNames =
                mHideMicrogPackagesForCallerByUser.get(UserHandle.getUserId(callingUid));

        if (configuredPackageNames == null || configuredPackageNames.isEmpty()) {
            return false;
        }

        if (callingPkgSetting != null) {
            return configuredPackageNames.contains(callingPkgSetting.getPackageName());
        }

        for (int i = 0; i < callingSharedPkgSettings.size(); i++) {
            if (configuredPackageNames.contains(
                    callingSharedPkgSettings.valueAt(i).getPackageName())) {
                return true;
            }
        }
        return false;
    }

    protected boolean isForceQueryable(int callingAppId) {
        return mForceQueryable.contains(callingAppId);
    }
@@ -342,6 +415,13 @@ public abstract class AppsFilterBase implements AppsFilterSnapshot {
                    || callingAppId == targetPkgSetting.getAppId()) {
                return false;
            } else if (Process.isSdkSandboxUid(callingAppId)) {
                final Computer computer = (Computer) snapshot;
                if (shouldHideMicrogPackagesForCaller(UserHandle.getUserId(callingUid),
                        computer.getPackagesForUid(Process.getAppUidForSdkSandboxUid(callingUid)),
                        targetPkgSetting.getPackageName())) {
                    return true;
                }

                final int targetAppId = targetPkgSetting.getAppId();
                final int targetUid = UserHandle.getUid(userId, targetAppId);
                // we only allow sdk sandbox processes access to forcequeryable packages or
@@ -453,6 +533,15 @@ public abstract class AppsFilterBase implements AppsFilterSnapshot {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }

            if (shouldHideMicrogPackagesForCaller(callingUid, callingPkgSetting,
                    callingSharedPkgSettings, targetPkgSetting)) {
                if (DEBUG_LOGGING) {
                    log(callingSetting, targetPkgSetting, "hidden package by microg config");
                }

                return true;
            }

            if (callingPkgSetting != null) {
                if (callingPkgSetting.getPkg() != null
                        && !mFeatureConfig.packageIsEnabled(callingPkgSetting.getPkg())) {
+83 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import android.provider.DeviceConfig;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseSetArray;

@@ -496,6 +497,62 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
                PACKAGE_MANAGER_APPS_FILTER_CACHE_BUILD_REPORTED__EVENT_TYPE__BOOT);
    }

    public void updateHiddenMicrogPackagesConfig(Computer snapshot,
            @NonNull SparseArray<ArraySet<String>> packageNamesByUser) {
        final SparseArray<ArraySet<String>> oldPackageNamesByUser =
                mHideMicrogPackagesForCallerByUser;
        final SparseArray<ArraySet<String>> newPackageNamesByUser =
                copyPackageNamesByUser(packageNamesByUser);

        if (samePackageNamesByUser(oldPackageNamesByUser, newPackageNamesByUser)) {
            return;
        }

        mHideMicrogPackagesForCallerByUser = newPackageNamesByUser;

        if (mCacheReady) {
            for (UserInfo userInfo : snapshot.getUserInfos()) {
                final int userId = userInfo.id;
                if (!Objects.equals(oldPackageNamesByUser.get(userId),
                        newPackageNamesByUser.get(userId))) {
                    updateEntireShouldFilterCache(snapshot, userId);
                }
            }
        }

        onChanged();
    }

    public void updateHiddenMicrogPackagesConfig(Computer snapshot, @UserIdInt int userId,
            @Nullable ArraySet<String> packageNames) {
        final SparseArray<ArraySet<String>> oldPackageNamesByUser =
                mHideMicrogPackagesForCallerByUser;
        final ArraySet<String> oldPackageNames = oldPackageNamesByUser.get(userId);
        final ArraySet<String> newPackageNames =
                packageNames == null ? null : new ArraySet<>(packageNames);

        if (Objects.equals(oldPackageNames, newPackageNames)) {
            return;
        }

        final SparseArray<ArraySet<String>> newPackageNamesByUser =
                copyPackageNamesByUser(oldPackageNamesByUser);

        if (newPackageNames == null || newPackageNames.isEmpty()) {
            newPackageNamesByUser.remove(userId);
        } else {
            newPackageNamesByUser.put(userId, newPackageNames);
        }

        mHideMicrogPackagesForCallerByUser = newPackageNamesByUser;

        if (mCacheReady && hasUser(snapshot.getUserInfos(), userId)) {
            updateEntireShouldFilterCache(snapshot, userId);
        }

        onChanged();
    }

    /**
     * Adds a package that should be considered when filtering visibility between apps.
     *
@@ -1295,4 +1352,30 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable,
        FrameworkStatsLog.write(PACKAGE_MANAGER_APPS_FILTER_CACHE_UPDATE_REPORTED,
                eventId, appId, latency, userCount, packageCount, mShouldFilterCache.size());
    }

    private static boolean samePackageNamesByUser(
            @NonNull SparseArray<ArraySet<String>> oldPackageNamesByUser,
            @NonNull SparseArray<ArraySet<String>> newPackageNamesByUser) {
        if (oldPackageNamesByUser.size() != newPackageNamesByUser.size()) {
            return false;
        }

        for (int i = 0; i < oldPackageNamesByUser.size(); i++) {
            final int userId = oldPackageNamesByUser.keyAt(i);
            if (!Objects.equals(oldPackageNamesByUser.valueAt(i),
                    newPackageNamesByUser.get(userId))) {
                return false;
            }
        }
        return true;
    }

    private static boolean hasUser(@NonNull UserInfo[] users, @UserIdInt int userId) {
        for (UserInfo user : users) {
            if (user.id == userId) {
                return true;
            }
        }
        return false;
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -57,9 +57,13 @@ public final class AppsFilterSnapshotImpl extends AppsFilterBase {
        }
        mProtectedBroadcastsSnapshot = new SnapshotCache.Sealed<>();
        mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute;
        mHideMicrogPackagesForCallerByUser =
                copyPackageNamesByUser(orig.mHideMicrogPackagesForCallerByUser);

        mForceQueryableByDevicePackageNames =
                Arrays.copyOf(orig.mForceQueryableByDevicePackageNames,
                        orig.mForceQueryableByDevicePackageNames.length);

        mSystemAppsQueryable = orig.mSystemAppsQueryable;
        mFeatureConfig = orig.mFeatureConfig.snapshot();
        mOverlayReferenceMapper = orig.mOverlayReferenceMapper;
Loading