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

Commit 71615844 authored by YK Hung's avatar YK Hung Committed by Android (Google) Code Review
Browse files

Merge "Add the thread-safe protection for PowerAllowlistBackend if possible" into main

parents b117b4c1 2bf60697
Loading
Loading
Loading
Loading
+78 −51
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;

import androidx.annotation.GuardedBy;
import androidx.annotation.VisibleForTesting;

import com.android.internal.telephony.SmsApplication;
@@ -56,13 +57,22 @@ public class PowerAllowlistBackend {

    private static PowerAllowlistBackend sInstance;

    private final Object mAllowlistedAppsLock = new Object();
    private final Object mSysAllowlistedAppsLock = new Object();
    private final Object mDefaultActiveAppsLock = new Object();

    private final Context mAppContext;
    private final IDeviceIdleController mDeviceIdleService;

    @GuardedBy("mAllowlistedAppsLock")
    private final ArraySet<String> mAllowlistedApps = new ArraySet<>();
    @GuardedBy("mSysAllowlistedAppsLock")
    private final ArraySet<String> mSysAllowlistedApps = new ArraySet<>();
    @GuardedBy("mDefaultActiveAppsLock")
    private final ArraySet<String> mDefaultActiveApps = new ArraySet<>();

    public PowerAllowlistBackend(Context context) {
    @VisibleForTesting
    PowerAllowlistBackend(Context context) {
        this(context, IDeviceIdleController.Stub.asInterface(
                ServiceManager.getService(DEVICE_IDLE_SERVICE)));
    }
@@ -75,24 +85,25 @@ public class PowerAllowlistBackend {
    }

    public int getAllowlistSize() {
        synchronized (mAllowlistedAppsLock) {
            return mAllowlistedApps.size();
        }
    }

    /**
    * Check if target package is in System allow list
    */
    /** Check if target package is in System allow list */
    public boolean isSysAllowlisted(String pkg) {
        synchronized (mSysAllowlistedAppsLock) {
            return mSysAllowlistedApps.contains(pkg);
        }
    }

    /**
     * Check if target package is in allow list
     */
    /** Check if target package is in allow list */
    public boolean isAllowlisted(String pkg, int uid) {
        synchronized (mAllowlistedAppsLock) {
            if (mAllowlistedApps.contains(pkg)) {
                return true;
            }

        }
        if (isDefaultActiveApp(pkg, uid)) {
            return true;
        }
@@ -100,17 +111,17 @@ public class PowerAllowlistBackend {
        return false;
    }

    /**
     * Check if it is default active app in multiple area(i.e. SMS, Dialer, Device admin..)
     */
    /** Check if it is default active app in multiple area */
    public boolean isDefaultActiveApp(String pkg, int uid) {
        // Additionally, check if pkg is default dialer/sms. They are considered essential apps and
        // should be automatically allowlisted (otherwise user may be able to set restriction on
        // them, leading to bad device behavior.)

        synchronized (mDefaultActiveAppsLock) {
            if (mDefaultActiveApps.contains(pkg)) {
                return true;
            }
        }

        final DevicePolicyManager devicePolicyManager = mAppContext.getSystemService(
                DevicePolicyManager.class);
@@ -143,9 +154,7 @@ public class PowerAllowlistBackend {
                DEFAULT_SYSTEM_EXEMPT_POWER_RESTRICTIONS_ENABLED);
    }

    /**
     * Check if target package is in allow list except idle app
     */
    /** Check if target package is in allow list except idle app */
    public boolean isAllowlistedExceptIdle(String pkg) {
        try {
            return mDeviceIdleService.isPowerSaveWhitelistExceptIdleApp(pkg);
@@ -156,6 +165,7 @@ public class PowerAllowlistBackend {
    }

    /**
     * Check if target package is in allow list except idle app
     *
     * @param pkgs a list of packageName
     * @return true when one of package is in allow list
@@ -174,20 +184,21 @@ public class PowerAllowlistBackend {
    }

    /**
     * Add app into power save allow list.
     * Add app into power save allow list
     *
     * @param pkg packageName of the app
     */
    // TODO: Fix all callers to pass in UID
    public void addApp(String pkg) {
        addApp(pkg, Process.INVALID_UID);
    }

    /**
     * Add app into power save allow list.
     * Add app into power save allow list
     *
     * @param pkg packageName of the app
     * @param uid uid of the app
     */
    public void addApp(String pkg, int uid) {
    public synchronized void addApp(String pkg, int uid) {
        try {
            if (android.app.Flags.appRestrictionsApi()) {
                if (uid == Process.INVALID_UID) {
@@ -204,7 +215,9 @@ public class PowerAllowlistBackend {
            }

            mDeviceIdleService.addPowerSaveWhitelistApp(pkg);
            synchronized (mAllowlistedAppsLock) {
                mAllowlistedApps.add(pkg);
            }
        } catch (RemoteException e) {
            Log.w(TAG, "Unable to reach IDeviceIdleController", e);
        } catch (NameNotFoundException e) {
@@ -213,7 +226,8 @@ public class PowerAllowlistBackend {
    }

    /**
     * Remove package from power save allow list.
     * Remove package from power save allow list
     *
     * @param pkg packageName of the app
     */
    public void removeApp(String pkg) {
@@ -222,10 +236,11 @@ public class PowerAllowlistBackend {

    /**
     * Remove package from power save allow list.
     *
     * @param pkg packageName of the app
     * @param uid uid of the app
     */
    public void removeApp(String pkg, int uid) {
    public synchronized void removeApp(String pkg, int uid) {
        try {
            if (android.app.Flags.appRestrictionsApi()) {
                if (uid == Process.INVALID_UID) {
@@ -241,7 +256,9 @@ public class PowerAllowlistBackend {
            }

            mDeviceIdleService.removePowerSaveWhitelistApp(pkg);
            synchronized (mAllowlistedAppsLock) {
                mAllowlistedApps.remove(pkg);
            }
        } catch (RemoteException e) {
            Log.w(TAG, "Unable to reach IDeviceIdleController", e);
        } catch (NameNotFoundException e) {
@@ -249,26 +266,34 @@ public class PowerAllowlistBackend {
        }
    }

    /**
     * Refresh all of lists
     */
    /** Refresh all of lists */
    @VisibleForTesting
    public void refreshList() {
    public synchronized void refreshList() {
        synchronized (mSysAllowlistedAppsLock) {
            mSysAllowlistedApps.clear();
        }
        synchronized (mAllowlistedAppsLock) {
            mAllowlistedApps.clear();
        }
        synchronized (mDefaultActiveAppsLock) {
            mDefaultActiveApps.clear();
        }
        if (mDeviceIdleService == null) {
            return;
        }
        try {
            final String[] allowlistedApps = mDeviceIdleService.getFullPowerWhitelist();
            synchronized (mAllowlistedAppsLock) {
                for (String app : allowlistedApps) {
                    mAllowlistedApps.add(app);
                }
            }
            final String[] sysAllowlistedApps = mDeviceIdleService.getSystemPowerWhitelist();
            synchronized (mSysAllowlistedAppsLock) {
                for (String app : sysAllowlistedApps) {
                    mSysAllowlistedApps.add(app);
                }
            }
            final boolean hasTelephony = mAppContext.getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_TELEPHONY);
            final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(mAppContext,
@@ -278,26 +303,28 @@ public class PowerAllowlistBackend {

            if (hasTelephony) {
                if (defaultSms != null) {
                    synchronized (mDefaultActiveAppsLock) {
                        mDefaultActiveApps.add(defaultSms.getPackageName());
                    }
                }
                if (!TextUtils.isEmpty(defaultDialer)) {
                    synchronized (mDefaultActiveAppsLock) {
                        mDefaultActiveApps.add(defaultDialer);
                    }
                }
        } catch (RemoteException e) {
            Log.w(TAG, "Unable to reach IDeviceIdleController", e);
            }
        } catch (Exception e) {
            Log.e(TAG, "Failed to invoke refreshList()", e);
        }
    }

    /**
     * @param context
     * @return a PowerAllowlistBackend object
     */
    /** Get the {@link PowerAllowlistBackend} instance */
    public static PowerAllowlistBackend getInstance(Context context) {
        synchronized (PowerAllowlistBackend.class) {
            if (sInstance == null) {
                sInstance = new PowerAllowlistBackend(context);
            }
            return sInstance;
        }

    }
}