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

Commit 2979b5ec authored by Winson Chiu's avatar Winson Chiu Committed by Automerger Merge Worker
Browse files

Merge changes Ie90dc390,Ia9513817 into sc-dev am: 627cac02

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

Change-Id: I98c4605050a27fa3a3070fc75a62660e81bccfe6
parents 27890381 627cac02
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -247,6 +247,48 @@ public class FunctionalUtils {
        }
    }

    /**
     * A {@link Consumer} that allows the caller to specify a custom checked {@link Exception} that
     * can be thrown by the implementer. This is usually used when proxying/wrapping calls between
     * different classes.
     *
     * @param <Input> Method parameter type
     * @param <ExceptionType> Checked exception type
     */
    @FunctionalInterface
    public interface ThrowingCheckedConsumer<Input, ExceptionType extends Exception> {
        void accept(Input input) throws ExceptionType;
    }

    /**
     * A {@link Consumer} that allows the caller to specify 2 different custom checked
     * {@link Exception}s that can be thrown by the implementer. This is usually used when
     * proxying/wrapping calls between different classes.
     *
     * @param <Input> Method parameter type
     * @param <ExceptionOne> First checked exception type
     * @param <ExceptionTwo> Second checked exception type
     */
    @FunctionalInterface
    public interface ThrowingChecked2Consumer<Input, ExceptionOne extends Exception,
            ExceptionTwo extends Exception> {
        void accept(Input input) throws ExceptionOne, ExceptionTwo;
    }

    /**
     * A {@link Function} that allows the caller to specify a custom checked {@link Exception} that
     * can be thrown by the implementer. This is usually used when proxying/wrapping calls between
     * different classes.
     *
     * @param <Input> Method parameter type
     * @param <Output> Method return type
     * @param <ExceptionType> Checked exception type
     */
    @FunctionalInterface
    public interface ThrowingCheckedFunction<Input, Output, ExceptionType extends Exception> {
        Output apply(Input input) throws ExceptionType;
    }

    // TODO: add unit test
    /**
     * Gets a user-friendly name for a lambda function.
+7 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ import java.util.function.Consumer;
 *
 * @hide Only for use within the system server.
 */
public abstract class PackageManagerInternal {
public abstract class PackageManagerInternal implements PackageSettingsSnapshotProvider {
    @IntDef(prefix = "PACKAGE_", value = {
            PACKAGE_SYSTEM,
            PACKAGE_SETUP_WIZARD,
@@ -795,6 +795,9 @@ public abstract class PackageManagerInternal {
     * Perform the given action for each package.
     * Note that packages lock will be held while performing the actions.
     *
     * If the caller does not need all packages, prefer the potentially non-locking
     * {@link #withPackageSettingsSnapshot(Consumer)}.
     *
     * @param actionLocked action to be performed
     */
    public abstract void forEachPackage(Consumer<AndroidPackage> actionLocked);
@@ -803,6 +806,9 @@ public abstract class PackageManagerInternal {
     * Perform the given action for each {@link PackageSetting}.
     * Note that packages lock will be held while performing the actions.
     *
     * If the caller does not need all packages, prefer the potentially non-locking
     * {@link #withPackageSettingsSnapshot(Consumer)}.
     *
     * @param actionLocked action to be performed
     */
    public abstract void forEachPackageSetting(Consumer<PackageSetting> actionLocked);
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 android.content.pm;

import android.annotation.NonNull;

import com.android.internal.util.FunctionalUtils;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.PackageSetting;

import java.util.function.Consumer;
import java.util.function.Function;

/** @hide */
public interface PackageSettingsSnapshotProvider {

    /**
     * Run a function block that requires access to {@link PackageSetting} data. This will
     * ensure the {@link PackageManagerService} lock is taken before any caller's internal lock
     * to avoid deadlock. Note that this method may or may not lock. If a snapshot is available
     * and valid, it will iterate the snapshot set of data.
     */
    void withPackageSettingsSnapshot(
            @NonNull Consumer<Function<String, PackageSetting>> block);

    /**
     * Variant which returns a value to the caller.
     * @see #withPackageSettingsSnapshot(Consumer)
     */
    <Output> Output withPackageSettingsSnapshotReturning(
            @NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageSetting>, Output>
                    block);

    /**
     * Variant which throws.
     * @see #withPackageSettingsSnapshot(Consumer)
     */
    <ExceptionType extends Exception> void withPackageSettingsSnapshotThrowing(
            @NonNull FunctionalUtils.ThrowingCheckedConsumer<Function<String, PackageSetting>,
                    ExceptionType> block) throws ExceptionType;

    /**
     * Variant which throws 2 exceptions.
     * @see #withPackageSettingsSnapshot(Consumer)
     */
    <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
            withPackageSettingsSnapshotThrowing2(
                    @NonNull FunctionalUtils.ThrowingChecked2Consumer<
                            Function<String, PackageSetting>, ExceptionOne, ExceptionTwo> block)
            throws ExceptionOne, ExceptionTwo;

    /**
     * Variant which returns a value to the caller and throws.
     * @see #withPackageSettingsSnapshot(Consumer)
     */
    <Output, ExceptionType extends Exception> Output
            withPackageSettingsSnapshotReturningThrowing(
                    @NonNull FunctionalUtils.ThrowingCheckedFunction<
                            Function<String, PackageSetting>, Output, ExceptionType> block)
            throws ExceptionType;
}
+118 −77
Original line number Diff line number Diff line
@@ -1731,104 +1731,57 @@ public class PackageManagerService extends IPackageManager.Stub
            return PackageManagerService.this.getPackage(packageName);
        }
        @NonNull
        @Override
        public void withPackageSettings(@NonNull Consumer<Function<String, PackageSetting>> block) {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    block.accept(snapshot::getPackageSetting);
                }
            } else {
                block.accept(snapshot::getPackageSetting);
            }
        public boolean filterAppAccess(String packageName, int callingUid, int userId) {
            return mPmInternal.filterAppAccess(packageName, callingUid, userId);
        }
        @Override
        public <Output> Output withPackageSettingsReturning(
                @NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageSetting>, Output>
                        block) {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    return block.apply(snapshot::getPackageSetting);
                }
            } else {
                return block.apply(snapshot::getPackageSetting);
            }
        public int[] getAllUserIds() {
            return mUserManager.getUserIds();
        }
        @Override
        public <ExceptionType extends Exception> void withPackageSettingsThrowing(
                @NonNull ThrowingConsumer<Function<String, PackageSetting>, ExceptionType> block)
                throws ExceptionType {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    block.accept(snapshot::getPackageSetting);
                }
            } else {
                block.accept(snapshot::getPackageSetting);
            }
        public boolean doesUserExist(@UserIdInt int userId) {
            return mUserManager.exists(userId);
        }
        @Override
        public <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
                withPackageSettingsThrowing2(
                        @NonNull Throwing2Consumer<Function<String, PackageSetting>, ExceptionOne,
                                ExceptionTwo> block) throws ExceptionOne, ExceptionTwo {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    block.accept(snapshot::getPackageSetting);
                }
            } else {
                block.accept(snapshot::getPackageSetting);
            }
        public void withPackageSettingsSnapshot(
                @NonNull Consumer<Function<String, PackageSetting>> block) {
            mPmInternal.withPackageSettingsSnapshot(block);
        }
        @Override
        public <Output, ExceptionType extends Exception> Output
                withPackageSettingsReturningThrowing(@NonNull ThrowingFunction<Function<String,
                PackageSetting>, Output, ExceptionType> block) throws ExceptionType {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    return block.apply(snapshot::getPackageSetting);
                }
            } else {
                return block.apply(snapshot::getPackageSetting);
            }
        public <Output> Output withPackageSettingsSnapshotReturning(
                @NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageSetting>, Output>
                        block) {
            return mPmInternal.withPackageSettingsSnapshotReturning(block);
        }
        @Override
        public boolean filterAppAccess(String packageName, int callingUid, int userId) {
            return mPmInternal.filterAppAccess(packageName, callingUid, userId);
        public <ExceptionType extends Exception> void withPackageSettingsSnapshotThrowing(
                @NonNull FunctionalUtils.ThrowingCheckedConsumer<Function<String, PackageSetting>,
                        ExceptionType> block) throws ExceptionType {
            mPmInternal.withPackageSettingsSnapshotThrowing(block);
        }
        @Override
        public int[] getAllUserIds() {
            return mUserManager.getUserIds();
        public <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
                withPackageSettingsSnapshotThrowing2(
                        @NonNull FunctionalUtils.ThrowingChecked2Consumer<
                                Function<String, PackageSetting>, ExceptionOne, ExceptionTwo> block)
                throws ExceptionOne, ExceptionTwo {
            mPmInternal.withPackageSettingsSnapshotThrowing2(block);
        }
        @Override
        public boolean doesUserExist(@UserIdInt int userId) {
            return mUserManager.exists(userId);
        public <Output, ExceptionType extends Exception> Output
                withPackageSettingsSnapshotReturningThrowing(
                        @NonNull FunctionalUtils.ThrowingCheckedFunction<
                                Function<String, PackageSetting>, Output, ExceptionType> block)
                throws ExceptionType {
            return mPmInternal.withPackageSettingsSnapshotReturningThrowing(block);
        }
    }
@@ -27290,6 +27243,94 @@ public class PackageManagerService extends IPackageManager.Stub
        public void deleteOatArtifactsOfPackage(String packageName) {
            PackageManagerService.this.deleteOatArtifactsOfPackage(packageName);
        }
        @Override
        public void withPackageSettingsSnapshot(
                @NonNull Consumer<Function<String, PackageSetting>> block) {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    block.accept(snapshot::getPackageSetting);
                }
            } else {
                block.accept(snapshot::getPackageSetting);
            }
        }
        @Override
        public <Output> Output withPackageSettingsSnapshotReturning(
                @NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageSetting>, Output>
                        block) {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    return block.apply(snapshot::getPackageSetting);
                }
            } else {
                return block.apply(snapshot::getPackageSetting);
            }
        }
        @Override
        public <ExceptionType extends Exception> void withPackageSettingsSnapshotThrowing(
                @NonNull FunctionalUtils.ThrowingCheckedConsumer<Function<String, PackageSetting>,
                        ExceptionType> block) throws ExceptionType {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    block.accept(snapshot::getPackageSetting);
                }
            } else {
                block.accept(snapshot::getPackageSetting);
            }
        }
        @Override
        public <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
                withPackageSettingsSnapshotThrowing2(
                        @NonNull FunctionalUtils.ThrowingChecked2Consumer<
                                Function<String, PackageSetting>, ExceptionOne, ExceptionTwo> block)
                throws ExceptionOne, ExceptionTwo {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    block.accept(snapshot::getPackageSetting);
                }
            } else {
                block.accept(snapshot::getPackageSetting);
            }
        }
        @Override
        public <Output, ExceptionType extends Exception> Output
                withPackageSettingsSnapshotReturningThrowing(
                        @NonNull FunctionalUtils.ThrowingCheckedFunction<
                                Function<String, PackageSetting>, Output, ExceptionType> block)
                throws ExceptionType {
            final Computer snapshot = snapshotComputer();
            // This method needs to either lock or not lock consistently throughout the method,
            // so if the live computer is returned, force a wrapping sync block.
            if (snapshot == mLiveComputer) {
                synchronized (mLock) {
                    return block.apply(snapshot::getPackageSetting);
                }
            } else {
                return block.apply(snapshot::getPackageSetting);
            }
        }
    }
    @GuardedBy("mLock")
+3 −56
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.content.Intent;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageSettingsSnapshotProvider;
import android.content.pm.ResolveInfo;
import android.content.pm.verify.domain.DomainVerificationInfo;
import android.content.pm.verify.domain.DomainVerificationManager;
@@ -36,7 +37,6 @@ import android.util.Pair;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;

import com.android.internal.util.FunctionalUtils;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.Settings;
@@ -49,7 +49,6 @@ import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Function;

public interface DomainVerificationManagerInternal {
@@ -406,7 +405,8 @@ public interface DomainVerificationManagerInternal {
            @NonNull Set<String> domains, int state) throws NameNotFoundException;


    interface Connection extends DomainVerificationEnforcer.Callback {
    interface Connection extends DomainVerificationEnforcer.Callback,
            PackageSettingsSnapshotProvider {

        /**
         * Notify that a settings change has been made and that eventually
@@ -430,60 +430,7 @@ public interface DomainVerificationManagerInternal {
         */
        void schedule(int code, @Nullable Object object);

        /**
         * Run a function block that requires access to {@link PackageSetting} data. This will
         * ensure the {@link PackageManagerService} is taken before
         * {@link DomainVerificationManagerInternal}'s lock is taken to avoid deadlock.
         */
        void withPackageSettings(@NonNull Consumer<Function<String, PackageSetting>> block);

        /**
         * Variant which returns a value to the caller.
         * @see #withPackageSettings(Consumer)
         */
        <Output> Output withPackageSettingsReturning(
                @NonNull FunctionalUtils.ThrowingFunction<Function<String, PackageSetting>, Output>
                        block);

        /**
         * Variant which throws.
         * @see #withPackageSettings(Consumer)
         */
        <ExceptionType extends Exception> void withPackageSettingsThrowing(
                @NonNull ThrowingConsumer<Function<String, PackageSetting>, ExceptionType> block)
                throws ExceptionType;

        /**
         * Variant which throws 2 exceptions.
         * @see #withPackageSettings(Consumer)
         */
        <ExceptionOne extends Exception, ExceptionTwo extends Exception> void
                withPackageSettingsThrowing2(
                        @NonNull Throwing2Consumer<Function<String, PackageSetting>, ExceptionOne,
                                ExceptionTwo> block) throws ExceptionOne, ExceptionTwo;

        /**
         * Variant which returns a value to the caller and throws.
         * @see #withPackageSettings(Consumer)
         */
        <Output, ExceptionType extends Exception> Output withPackageSettingsReturningThrowing(
                @NonNull ThrowingFunction<Function<String, PackageSetting>, Output, ExceptionType>
                        block) throws ExceptionType;

        @UserIdInt
        int[] getAllUserIds();

        interface ThrowingConsumer<Input, ExceptionType extends Exception> {
            void accept(Input input) throws ExceptionType;
        }

        interface Throwing2Consumer<Input, ExceptionOne extends Exception,
                ExceptionTwo extends Exception> {
            void accept(Input input) throws ExceptionOne, ExceptionTwo;
        }

        interface ThrowingFunction<Input, Output, ExceptionType extends Exception> {
            Output apply(Input input) throws ExceptionType;
        }
    }
}
Loading