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

Commit b9df101c authored by Eugene Susla's avatar Eugene Susla Committed by Android (Google) Code Review
Browse files

Merge "Call roles granting only when packages changed"

parents 5cf6abed abdefbae
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.pm.PackageManager.PackageInfoFlags;
import android.content.pm.PackageManager.ResolveInfoFlags;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.util.ArraySet;
import android.util.SparseArray;

import com.android.internal.util.function.TriFunction;
@@ -37,6 +38,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;

/**
 * Package manager local system service interface.
@@ -735,4 +737,22 @@ public abstract class PackageManagerInternal {

    /** Returns {@code true} if the given user requires extra badging for icons. */
    public abstract boolean userNeedsBadging(int userId);

    /**
     * Perform the given action for each package.
     * Note that packages lock will be held while performin the actions.
     *
     * @param actionLocked action to be performed
     */
    public abstract void forEachPackage(Consumer<PackageParser.Package> actionLocked);

    /** Returns the list of enabled components */
    public abstract ArraySet<String> getEnabledComponents(String packageName, int userId);

    /** Returns the list of disabled components */
    public abstract ArraySet<String> getDisabledComponents(String packageName, int userId);

    /** Returns whether the given package is enabled for the given user */
    public abstract @PackageManager.EnabledState int getApplicationEnabledState(
            String packageName, int userId);
}
+8 −1
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ import java.util.function.IntFunction;

/**
 * A utility class for handling unsigned integers and unsigned arithmetics, as well as syntactic
 * sugar methods for ByteBuffer. Useful for networking and packet manipulations.
 * sugar methods for {@link ByteBuffer}. Useful for networking and packet manipulations.
 * {@hide}
 */
public final class BitUtils {
@@ -151,4 +151,11 @@ public final class BitUtils {
        TextUtils.wrap(builder, "[", "]");
        return builder.toString();
    }

    /**
     * Converts long to byte array
     */
    public static byte[] toBytes(long l) {
        return ByteBuffer.allocate(8).putLong(l).array();
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -189,6 +190,13 @@ public class CollectionUtils {
        return cur != null ? cur.size() : 0;
    }

    /**
     * Returns the size of the given map, or 0 if null
     */
    public static int size(@Nullable Map<?, ?> cur) {
        return cur != null ? cur.size() : 0;
    }

    /**
     * Returns whether the given collection {@link Collection#isEmpty is empty} or {@code null}
     */
+51 −4
Original line number Diff line number Diff line
@@ -116,8 +116,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS;
import static com.android.server.pm.permission.PermissionsState
        .PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
import android.Manifest;
import android.annotation.IntDef;
@@ -314,8 +313,7 @@ import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.dex.PackageDexUsage;
import com.android.server.pm.permission.BasePermission;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy
        .DefaultPermissionGrantedCallback;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
import com.android.server.pm.permission.PermissionManagerInternal;
import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
import com.android.server.pm.permission.PermissionManagerService;
@@ -374,6 +372,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
@@ -23207,6 +23206,45 @@ public class PackageManagerService extends IPackageManager.Stub
                throws IOException {
            PackageManagerService.this.freeStorage(volumeUuid, bytes, storageFlags);
        }
        @Override
        public void forEachPackage(Consumer<PackageParser.Package> actionLocked) {
            PackageManagerService.this.forEachPackage(actionLocked);
        }
        @Override
        public ArraySet<String> getEnabledComponents(String packageName, int userId) {
            synchronized (mPackages) {
                PackageSetting setting = mSettings.getPackageLPr(packageName);
                if (setting == null) {
                    return new ArraySet<>();
                }
                return setting.getEnabledComponents(userId);
            }
        }
        @Override
        public ArraySet<String> getDisabledComponents(String packageName, int userId) {
            synchronized (mPackages) {
                PackageSetting setting = mSettings.getPackageLPr(packageName);
                if (setting == null) {
                    return new ArraySet<>();
                }
                return setting.getDisabledComponents(userId);
            }
        }
        @Override
        public @PackageManager.EnabledState int getApplicationEnabledState(
                String packageName, int userId) {
            synchronized (mPackages) {
                PackageSetting setting = mSettings.getPackageLPr(packageName);
                if (setting == null) {
                    return COMPONENT_ENABLED_STATE_DEFAULT;
                }
                return setting.getEnabled(userId);
            }
        }
    }
    @GuardedBy("mPackages")
@@ -23329,6 +23367,15 @@ public class PackageManagerService extends IPackageManager.Stub
        }
    }
    void forEachPackage(Consumer<PackageParser.Package> actionLocked) {
        synchronized (mPackages) {
            int numPackages = mPackages.size();
            for (int i = 0; i < numPackages; i++) {
                actionLocked.accept(mPackages.valueAt(i));
            }
        }
    }
    private static void enforceSystemOrPhoneCaller(String tag) {
        int callingUid = Binder.getCallingUid();
        if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) {
+52 −5
Original line number Diff line number Diff line
@@ -30,20 +30,27 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.PackageUtils;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.BitUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.FunctionalUtils;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;

import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Collections;
@@ -117,13 +124,18 @@ public class RoleManagerService extends SystemService {

    @Override
    public void onStartUser(@UserIdInt int userId) {
        RoleUserState userState;
        synchronized (mLock) {
            //TODO only call into PermissionController if it or system upgreaded (for boot time)
            getUserStateLocked(userId);
            userState = getUserStateLocked(userId);
        }
        //TODO consider calling grants only when certain conditions are met
        // such as OS or PermissionController upgrade
        if (RemoteRoleControllerService.DEBUG) {
        String packagesHash = computeComponentStateHash(userId);
        boolean needGrant;
        synchronized (mLock) {
            needGrant = !packagesHash.equals(userState.getLastGrantPackagesHashLocked());
        }
        if (needGrant) {
            // Some vital packages state has changed since last role grant
            // Run grants again
            Slog.i(LOG_TAG, "Granting default permissions...");
            CompletableFuture<Void> result = new CompletableFuture<>();
            getControllerService(userId).onGrantDefaultRoles(
@@ -140,12 +152,47 @@ public class RoleManagerService extends SystemService {
                    });
            try {
                result.get(5, TimeUnit.SECONDS);
                synchronized (mLock) {
                    userState.setLastGrantPackagesHashLocked(packagesHash);
                }
            } catch (InterruptedException | ExecutionException | TimeoutException e) {
                Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
            }
        } else if (RemoteRoleControllerService.DEBUG) {
            Slog.i(LOG_TAG, "Already ran grants for package state " + packagesHash);
        }
    }

    private String computeComponentStateHash(int userId) {
        PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        pm.forEachPackage(FunctionalUtils.uncheckExceptions(pkg -> {
            out.write(pkg.packageName.getBytes());
            out.write(BitUtils.toBytes(pkg.getLongVersionCode()));
            out.write(pm.getApplicationEnabledState(pkg.packageName, userId));

            ArraySet<String> enabledComponents =
                    pm.getEnabledComponents(pkg.packageName, userId);
            int numComponents = CollectionUtils.size(enabledComponents);
            for (int i = 0; i < numComponents; i++) {
                out.write(enabledComponents.valueAt(i).getBytes());
            }

            ArraySet<String> disabledComponents =
                    pm.getDisabledComponents(pkg.packageName, userId);
            numComponents = CollectionUtils.size(disabledComponents);
            for (int i = 0; i < numComponents; i++) {
                out.write(disabledComponents.valueAt(i).getBytes());
            }
            for (Signature signature : pkg.mSigningDetails.signatures) {
                out.write(signature.toByteArray());
            }
        }));

        return PackageUtils.computeSha256Digest(out.toByteArray());
    }

    @GuardedBy("mLock")
    @NonNull
    private RoleUserState getUserStateLocked(@UserIdInt int userId) {
Loading