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

Commit 38d5d66c authored by Suprabh Shukla's avatar Suprabh Shukla
Browse files

More changes for the exact alarm permission

Adding a deny list option, which changes the default grant state of the
permission to denied. This means now alarm manager is the source of
truth of the permission state and exposes an API that clients like
Settings should call.
Also using the same API to cap the minimum standby-bucket
for apps with this permission to WORKING_SET.

Adding an app to the deny list may mean revocation of its permission, in
which case its exact alarms will be removed.
Meanwhile, performed some long needed refactoring on the remove methods,
so they re-use common code and are easier to maintain.

Also, changing strings for the Settings UI to be clearer.

Test: atest FrameworksMockingServicesTests:com.android.server.alarm
atest CtsAlarmManagerTestCases

Bug: 171306433
Bug: 130444055
Bug: 181894091
Bug: 181152252
Change-Id: I9410f988343800b7322963fecf3eafac9561b093
parent f5042bcc
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
@@ -1132,12 +1133,31 @@ public class AlarmManager {
    }

    /**
     * Called to check if the caller has permission to use alarms set via {@link }
     * @return
     * Called to check if the caller has the permission
     * {@link Manifest.permission#SCHEDULE_EXACT_ALARM}.
     *
     * Apps can start {@link android.provider.Settings#ACTION_REQUEST_SCHEDULE_EXACT_ALARM} to
     * request this from the user.
     *
     * @return {@code true} if the caller has the permission, {@code false} otherwise.
     * @see android.provider.Settings#ACTION_REQUEST_SCHEDULE_EXACT_ALARM
     */
    public boolean canScheduleExactAlarms() {
        return hasScheduleExactAlarm(mContext.getOpPackageName(), mContext.getUserId());
    }

    /**
     * Called to check if the given package in the given user has the permission
     * {@link Manifest.permission#SCHEDULE_EXACT_ALARM}.
     *
     * <p><em>Note: This is only for use by system components.</em>
     *
     * @hide
     */
    @TestApi
    public boolean hasScheduleExactAlarm(@NonNull String packageName, int userId) {
        try {
            return mService.canScheduleExactAlarms();
            return mService.hasScheduleExactAlarm(packageName, userId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
+1 −1
Original line number Diff line number Diff line
@@ -41,6 +41,6 @@ interface IAlarmManager {
    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
    AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
    long currentNetworkTimeMillis();
    boolean canScheduleExactAlarms();
    boolean hasScheduleExactAlarm(String packageName, int userId);
    int getConfigVersion();
}
+165 −207

File changed.

Preview size limit exceeded, changes collapsed.

+11 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ConcurrentUtils;
import com.android.server.AlarmManagerInternal;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -1191,6 +1192,10 @@ public class AppStandbyController
            if (mInjector.isWellbeingPackage(packageName)) {
                return STANDBY_BUCKET_WORKING_SET;
            }

            if (mInjector.hasScheduleExactAlarm(packageName, UserHandle.getUid(userId, appId))) {
                return STANDBY_BUCKET_WORKING_SET;
            }
        }

        // Check this last, as it can be the most expensive check
@@ -2007,6 +2012,7 @@ public class AppStandbyController
        private PowerManager mPowerManager;
        private IDeviceIdleController mDeviceIdleController;
        private CrossProfileAppsInternal mCrossProfileAppsInternal;
        private AlarmManagerInternal mAlarmManagerInternal;
        int mBootPhase;
        /**
         * The minimum amount of time required since the last user interaction before an app can be
@@ -2047,6 +2053,7 @@ public class AppStandbyController
                mBatteryManager = mContext.getSystemService(BatteryManager.class);
                mCrossProfileAppsInternal = LocalServices.getService(
                        CrossProfileAppsInternal.class);
                mAlarmManagerInternal = LocalServices.getService(AlarmManagerInternal.class);

                final ActivityManager activityManager =
                        (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
@@ -2110,6 +2117,10 @@ public class AppStandbyController
            return mWellbeingApp != null && mWellbeingApp.equals(packageName);
        }

        boolean hasScheduleExactAlarm(String packageName, int uid) {
            return mAlarmManagerInternal.hasScheduleExactAlarm(packageName, uid);
        }

        void updatePowerWhitelistCache() {
            try {
                // Don't call out to DeviceIdleController with the lock held.
+4 −0
Original line number Diff line number Diff line
@@ -204,6 +204,10 @@ package android.app {
    method public void onTaskRemovalStarted(int);
  }

  public class AlarmManager {
    method public boolean hasScheduleExactAlarm(@NonNull String, int);
  }

  public class AppDetailsActivity extends android.app.Activity {
    ctor public AppDetailsActivity();
  }
Loading