diff options
76 files changed, 1476 insertions, 711 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java b/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java index 91d254d16b09..a413f7b1f3ca 100644 --- a/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java +++ b/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java @@ -17,10 +17,13 @@ package com.android.server; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.Looper; import android.os.Trace; +import java.util.concurrent.Executor; + /** * Shared singleton background thread. * @@ -31,6 +34,7 @@ public final class JobSchedulerBackgroundThread extends HandlerThread { private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000; private static JobSchedulerBackgroundThread sInstance; private static Handler sHandler; + private static Executor sHandlerExecutor; private JobSchedulerBackgroundThread() { super("jobscheduler.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND); @@ -45,6 +49,7 @@ public final class JobSchedulerBackgroundThread extends HandlerThread { looper.setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); sHandler = new Handler(sInstance.getLooper()); + sHandlerExecutor = new HandlerExecutor(sHandler); } } @@ -63,4 +68,12 @@ public final class JobSchedulerBackgroundThread extends HandlerThread { return sHandler; } } + + /** Returns the singleton handler executor for JobSchedulerBackgroundThread */ + public static Executor getExecutor() { + synchronized (JobSchedulerBackgroundThread.class) { + ensureThreadLocked(); + return sHandlerExecutor; + } + } } diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java index a1a5004447a6..b35a7be1f689 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java @@ -166,7 +166,7 @@ class JobConcurrencyManager { // Note: we can't directly do postDelayed(this::rampUpForScreenOn), because // we need the exact same instance for removeCallbacks(). mHandler.postDelayed(mRampUpForScreenOff, - mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.getValue()); + mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS); } } } @@ -189,7 +189,7 @@ class JobConcurrencyManager { } final long now = JobSchedulerService.sElapsedRealtimeClock.millis(); if ((mLastScreenOffRealtime - + mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.getValue()) + + mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS) > now) { return; } diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index 3234b274eaa7..cf4caea9c487 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -39,7 +39,6 @@ import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -50,7 +49,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; import android.content.pm.ServiceInfo; -import android.database.ContentObserver; import android.net.Uri; import android.os.BatteryStats; import android.os.BatteryStatsInternal; @@ -67,11 +65,10 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManagerInternal; import android.os.WorkSource; -import android.provider.Settings; +import android.provider.DeviceConfig; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.IndentingPrintWriter; -import android.util.KeyValueListParser; import android.util.Log; import android.util.Slog; import android.util.SparseArray; @@ -88,6 +85,7 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.server.AppStateTracker; import com.android.server.AppStateTrackerImpl; import com.android.server.DeviceIdleInternal; +import com.android.server.JobSchedulerBackgroundThread; import com.android.server.LocalServices; import com.android.server.SystemService.TargetUser; import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob; @@ -329,39 +327,70 @@ public class JobSchedulerService extends com.android.server.SystemService // -- Pre-allocated temporaries only for use in assignJobsToContextsLocked -- - private class ConstantsObserver extends ContentObserver { - private ContentResolver mResolver; - - public ConstantsObserver(Handler handler) { - super(handler); - } - - public void start(ContentResolver resolver) { - mResolver = resolver; - mResolver.registerContentObserver(Settings.Global.getUriFor( - Settings.Global.JOB_SCHEDULER_CONSTANTS), false, this); - updateConstants(); + private class ConstantsObserver implements DeviceConfig.OnPropertiesChangedListener { + public void start() { + DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + JobSchedulerBackgroundThread.getExecutor(), this); + // Load all the constants. + onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_JOB_SCHEDULER)); } @Override - public void onChange(boolean selfChange, Uri uri) { - updateConstants(); - } - - private void updateConstants() { + public void onPropertiesChanged(DeviceConfig.Properties properties) { + boolean apiQuotaScheduleUpdated = false; + boolean concurrencyUpdated = false; synchronized (mLock) { - try { - mConstants.updateConstantsLocked(Settings.Global.getString(mResolver, - Settings.Global.JOB_SCHEDULER_CONSTANTS)); - for (int controller = 0; controller < mControllers.size(); controller++) { - final StateController sc = mControllers.get(controller); - sc.onConstantsUpdatedLocked(); + for (String name : properties.getKeyset()) { + if (name == null) { + continue; } - updateQuotaTracker(); - } catch (IllegalArgumentException e) { - // Failed to parse the settings string, log this and move on - // with defaults. - Slog.e(TAG, "Bad jobscheduler settings", e); + switch (name) { + case Constants.KEY_ENABLE_API_QUOTAS: + case Constants.KEY_API_QUOTA_SCHEDULE_COUNT: + case Constants.KEY_API_QUOTA_SCHEDULE_WINDOW_MS: + case Constants.KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT: + case Constants.KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION: + if (!apiQuotaScheduleUpdated) { + mConstants.updateApiQuotaConstantsLocked(); + updateQuotaTracker(); + apiQuotaScheduleUpdated = true; + } + break; + case Constants.KEY_MIN_READY_NON_ACTIVE_JOBS_COUNT: + case Constants.KEY_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS: + mConstants.updateBatchingConstantsLocked(); + break; + case Constants.KEY_HEAVY_USE_FACTOR: + case Constants.KEY_MODERATE_USE_FACTOR: + mConstants.updateUseFactorConstantsLocked(); + break; + case Constants.KEY_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS: + if (!concurrencyUpdated) { + mConstants.updateConcurrencyConstantsLocked(); + concurrencyUpdated = true; + } + break; + case Constants.KEY_MIN_LINEAR_BACKOFF_TIME_MS: + case Constants.KEY_MIN_EXP_BACKOFF_TIME_MS: + mConstants.updateBackoffConstantsLocked(); + break; + case Constants.KEY_CONN_CONGESTION_DELAY_FRAC: + case Constants.KEY_CONN_PREFETCH_RELAX_FRAC: + mConstants.updateConnectivityConstantsLocked(); + break; + default: + // Too many max_job_* strings to list. + if (name.startsWith(Constants.KEY_PREFIX_MAX_JOB) + && !concurrencyUpdated) { + mConstants.updateConcurrencyConstantsLocked(); + concurrencyUpdated = true; + } + break; + } + } + for (int controller = 0; controller < mControllers.size(); controller++) { + final StateController sc = mControllers.get(controller); + sc.onConstantsUpdatedLocked(); } } } @@ -376,53 +405,52 @@ public class JobSchedulerService extends com.android.server.SystemService } static class MaxJobCounts { - private final KeyValueListParser.IntValue mTotal; - private final KeyValueListParser.IntValue mMaxBg; - private final KeyValueListParser.IntValue mMinBg; + private final int mTotalDefault; + private final String mTotalKey; + private final int mMaxBgDefault; + private final String mMaxBgKey; + private final int mMinBgDefault; + private final String mMinBgKey; + private int mTotal; + private int mMaxBg; + private int mMinBg; MaxJobCounts(int totalDefault, String totalKey, int maxBgDefault, String maxBgKey, int minBgDefault, String minBgKey) { - mTotal = new KeyValueListParser.IntValue(totalKey, totalDefault); - mMaxBg = new KeyValueListParser.IntValue(maxBgKey, maxBgDefault); - mMinBg = new KeyValueListParser.IntValue(minBgKey, minBgDefault); + mTotalKey = totalKey; + mTotal = mTotalDefault = totalDefault; + mMaxBgKey = maxBgKey; + mMaxBg = mMaxBgDefault = maxBgDefault; + mMinBgKey = minBgKey; + mMinBg = mMinBgDefault = minBgDefault; } - public void parse(KeyValueListParser parser) { - mTotal.parse(parser); - mMaxBg.parse(parser); - mMinBg.parse(parser); + public void update() { + mTotal = DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + mTotalKey, mTotalDefault); + mMaxBg = DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + mMaxBgKey, mMaxBgDefault); + mMinBg = DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + mMinBgKey, mMinBgDefault); - if (mTotal.getValue() < 1) { - mTotal.setValue(1); - } else if (mTotal.getValue() > MAX_JOB_CONTEXTS_COUNT) { - mTotal.setValue(MAX_JOB_CONTEXTS_COUNT); - } + // Ensure total in the range [1, MAX_JOB_CONTEXTS_COUNT]. + mTotal = Math.min(Math.max(1, mTotal), MAX_JOB_CONTEXTS_COUNT); - if (mMaxBg.getValue() < 1) { - mMaxBg.setValue(1); - } else if (mMaxBg.getValue() > mTotal.getValue()) { - mMaxBg.setValue(mTotal.getValue()); - } - if (mMinBg.getValue() < 0) { - mMinBg.setValue(0); - } else { - if (mMinBg.getValue() > mMaxBg.getValue()) { - mMinBg.setValue(mMaxBg.getValue()); - } - if (mMinBg.getValue() >= mTotal.getValue()) { - mMinBg.setValue(mTotal.getValue() - 1); - } - } + // Ensure maxBg in the range [1, total]. + mMaxBg = Math.min(Math.max(1, mMaxBg), mTotal); + + // Ensure minBg in the range [0, min(maxBg, total - 1)] + mMinBg = Math.min(Math.max(0, mMinBg), Math.min(mMaxBg, mTotal - 1)); } /** Total number of jobs to run simultaneously. */ public int getMaxTotal() { - return mTotal.getValue(); + return mTotal; } /** Max number of BG (== owned by non-TOP apps) jobs to run simultaneously. */ public int getMaxBg() { - return mMaxBg.getValue(); + return mMaxBg; } /** @@ -430,20 +458,34 @@ public class JobSchedulerService extends com.android.server.SystemService * pending, rather than always running the TOTAL number of FG jobs. */ public int getMinBg() { - return mMinBg.getValue(); + return mMinBg; } public void dump(PrintWriter pw, String prefix) { - mTotal.dump(pw, prefix); - mMaxBg.dump(pw, prefix); - mMinBg.dump(pw, prefix); + pw.print(prefix); + pw.print(mTotalKey); + pw.print("="); + pw.print(mTotal); + pw.println(); + + pw.print(prefix); + pw.print(mMaxBgKey); + pw.print("="); + pw.print(mMaxBg); + pw.println(); + + pw.print(prefix); + pw.print(mMinBgKey); + pw.print("="); + pw.print(mMinBg); + pw.println(); } public void dumpProto(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); - mTotal.dumpProto(proto, MaxJobCountsProto.TOTAL_JOBS); - mMaxBg.dumpProto(proto, MaxJobCountsProto.MAX_BG); - mMinBg.dumpProto(proto, MaxJobCountsProto.MIN_BG); + proto.write(MaxJobCountsProto.TOTAL_JOBS, mTotal); + proto.write(MaxJobCountsProto.MAX_BG, mMaxBg); + proto.write(MaxJobCountsProto.MIN_BG, mMinBg); proto.end(token); } } @@ -476,23 +518,11 @@ public class JobSchedulerService extends com.android.server.SystemService } /** - * All times are in milliseconds. These constants are kept synchronized with the system - * global Settings. Any access to this class or its fields should be done while + * All times are in milliseconds. Any access to this class or its fields should be done while * holding the JobSchedulerService.mLock lock. */ public static class Constants { // Key names stored in the settings value. - // TODO(124466289): remove deprecated flags when we migrate to DeviceConfig - private static final String DEPRECATED_KEY_MIN_IDLE_COUNT = "min_idle_count"; - private static final String DEPRECATED_KEY_MIN_CHARGING_COUNT = "min_charging_count"; - private static final String DEPRECATED_KEY_MIN_BATTERY_NOT_LOW_COUNT = - "min_battery_not_low_count"; - private static final String DEPRECATED_KEY_MIN_STORAGE_NOT_LOW_COUNT = - "min_storage_not_low_count"; - private static final String DEPRECATED_KEY_MIN_CONNECTIVITY_COUNT = - "min_connectivity_count"; - private static final String DEPRECATED_KEY_MIN_CONTENT_COUNT = "min_content_count"; - private static final String DEPRECATED_KEY_MIN_READY_JOBS_COUNT = "min_ready_jobs_count"; private static final String KEY_MIN_READY_NON_ACTIVE_JOBS_COUNT = "min_ready_non_active_jobs_count"; private static final String KEY_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = @@ -500,28 +530,10 @@ public class JobSchedulerService extends com.android.server.SystemService private static final String KEY_HEAVY_USE_FACTOR = "heavy_use_factor"; private static final String KEY_MODERATE_USE_FACTOR = "moderate_use_factor"; - // The following values used to be used on P and below. Do not reuse them. - private static final String DEPRECATED_KEY_FG_JOB_COUNT = "fg_job_count"; - private static final String DEPRECATED_KEY_BG_NORMAL_JOB_COUNT = "bg_normal_job_count"; - private static final String DEPRECATED_KEY_BG_MODERATE_JOB_COUNT = "bg_moderate_job_count"; - private static final String DEPRECATED_KEY_BG_LOW_JOB_COUNT = "bg_low_job_count"; - private static final String DEPRECATED_KEY_BG_CRITICAL_JOB_COUNT = "bg_critical_job_count"; - - private static final String DEPRECATED_KEY_MAX_STANDARD_RESCHEDULE_COUNT - = "max_standard_reschedule_count"; - private static final String DEPRECATED_KEY_MAX_WORK_RESCHEDULE_COUNT = - "max_work_reschedule_count"; - private static final String KEY_MIN_LINEAR_BACKOFF_TIME = "min_linear_backoff_time"; - private static final String KEY_MIN_EXP_BACKOFF_TIME = "min_exp_backoff_time"; - private static final String DEPRECATED_KEY_STANDBY_HEARTBEAT_TIME = - "standby_heartbeat_time"; - private static final String DEPRECATED_KEY_STANDBY_WORKING_BEATS = "standby_working_beats"; - private static final String DEPRECATED_KEY_STANDBY_FREQUENT_BEATS = - "standby_frequent_beats"; - private static final String DEPRECATED_KEY_STANDBY_RARE_BEATS = "standby_rare_beats"; + private static final String KEY_MIN_LINEAR_BACKOFF_TIME_MS = "min_linear_backoff_time_ms"; + private static final String KEY_MIN_EXP_BACKOFF_TIME_MS = "min_exp_backoff_time_ms"; private static final String KEY_CONN_CONGESTION_DELAY_FRAC = "conn_congestion_delay_frac"; private static final String KEY_CONN_PREFETCH_RELAX_FRAC = "conn_prefetch_relax_frac"; - private static final String DEPRECATED_KEY_USE_HEARTBEATS = "use_heartbeats"; private static final String KEY_ENABLE_API_QUOTAS = "enable_api_quotas"; private static final String KEY_API_QUOTA_SCHEDULE_COUNT = "aq_schedule_count"; private static final String KEY_API_QUOTA_SCHEDULE_WINDOW_MS = "aq_schedule_window_ms"; @@ -530,12 +542,15 @@ public class JobSchedulerService extends com.android.server.SystemService private static final String KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = "aq_schedule_return_failure"; + private static final String KEY_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS = + "screen_off_job_concurrency_increase_delay_ms"; + private static final int DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT = 5; private static final long DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = 31 * MINUTE_IN_MILLIS; private static final float DEFAULT_HEAVY_USE_FACTOR = .9f; private static final float DEFAULT_MODERATE_USE_FACTOR = .5f; - private static final long DEFAULT_MIN_LINEAR_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS; - private static final long DEFAULT_MIN_EXP_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS; + private static final long DEFAULT_MIN_LINEAR_BACKOFF_TIME_MS = JobInfo.MIN_BACKOFF_MILLIS; + private static final long DEFAULT_MIN_EXP_BACKOFF_TIME_MS = JobInfo.MIN_BACKOFF_MILLIS; private static final float DEFAULT_CONN_CONGESTION_DELAY_FRAC = 0.5f; private static final float DEFAULT_CONN_PREFETCH_RELAX_FRAC = 0.5f; private static final boolean DEFAULT_ENABLE_API_QUOTAS = true; @@ -543,6 +558,7 @@ public class JobSchedulerService extends com.android.server.SystemService private static final long DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS = MINUTE_IN_MILLIS; private static final boolean DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION = true; private static final boolean DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false; + private static final long DEFAULT_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS = 30_000; /** * Minimum # of non-ACTIVE jobs for which the JMS will be happy running some work early. @@ -564,59 +580,61 @@ public class JobSchedulerService extends com.android.server.SystemService */ float MODERATE_USE_FACTOR = DEFAULT_MODERATE_USE_FACTOR; + /** Prefix for all of the max_job constants. */ + private static final String KEY_PREFIX_MAX_JOB = "max_job_"; + // Max job counts for screen on / off, for each memory trim level. final MaxJobCountsPerMemoryTrimLevel MAX_JOB_COUNTS_SCREEN_ON = new MaxJobCountsPerMemoryTrimLevel( new MaxJobCounts( - 8, "max_job_total_on_normal", - 6, "max_job_max_bg_on_normal", - 2, "max_job_min_bg_on_normal"), + 8, KEY_PREFIX_MAX_JOB + "total_on_normal", + 6, KEY_PREFIX_MAX_JOB + "max_bg_on_normal", + 2, KEY_PREFIX_MAX_JOB + "min_bg_on_normal"), new MaxJobCounts( - 8, "max_job_total_on_moderate", - 4, "max_job_max_bg_on_moderate", - 2, "max_job_min_bg_on_moderate"), + 8, KEY_PREFIX_MAX_JOB + "total_on_moderate", + 4, KEY_PREFIX_MAX_JOB + "max_bg_on_moderate", + 2, KEY_PREFIX_MAX_JOB + "min_bg_on_moderate"), new MaxJobCounts( - 5, "max_job_total_on_low", - 1, "max_job_max_bg_on_low", - 1, "max_job_min_bg_on_low"), + 5, KEY_PREFIX_MAX_JOB + "total_on_low", + 1, KEY_PREFIX_MAX_JOB + "max_bg_on_low", + 1, KEY_PREFIX_MAX_JOB + "min_bg_on_low"), new MaxJobCounts( - 5, "max_job_total_on_critical", - 1, "max_job_max_bg_on_critical", - 1, "max_job_min_bg_on_critical")); + 5, KEY_PREFIX_MAX_JOB + "total_on_critical", + 1, KEY_PREFIX_MAX_JOB + "max_bg_on_critical", + 1, KEY_PREFIX_MAX_JOB + "min_bg_on_critical")); final MaxJobCountsPerMemoryTrimLevel MAX_JOB_COUNTS_SCREEN_OFF = new MaxJobCountsPerMemoryTrimLevel( new MaxJobCounts( - 10, "max_job_total_off_normal", - 6, "max_job_max_bg_off_normal", - 2, "max_job_min_bg_off_normal"), + 10, KEY_PREFIX_MAX_JOB + "total_off_normal", + 6, KEY_PREFIX_MAX_JOB + "max_bg_off_normal", + 2, KEY_PREFIX_MAX_JOB + "min_bg_off_normal"), new MaxJobCounts( - 10, "max_job_total_off_moderate", - 4, "max_job_max_bg_off_moderate", - 2, "max_job_min_bg_off_moderate"), + 10, KEY_PREFIX_MAX_JOB + "total_off_moderate", + 4, KEY_PREFIX_MAX_JOB + "max_bg_off_moderate", + 2, KEY_PREFIX_MAX_JOB + "min_bg_off_moderate"), new MaxJobCounts( - 5, "max_job_total_off_low", - 1, "max_job_max_bg_off_low", - 1, "max_job_min_bg_off_low"), + 5, KEY_PREFIX_MAX_JOB + "total_off_low", + 1, KEY_PREFIX_MAX_JOB + "max_bg_off_low", + 1, KEY_PREFIX_MAX_JOB + "min_bg_off_low"), new MaxJobCounts( - 5, "max_job_total_off_critical", - 1, "max_job_max_bg_off_critical", - 1, "max_job_min_bg_off_critical")); + 5, KEY_PREFIX_MAX_JOB + "total_off_critical", + 1, KEY_PREFIX_MAX_JOB + "max_bg_off_critical", + 1, KEY_PREFIX_MAX_JOB + "min_bg_off_critical")); /** Wait for this long after screen off before increasing the job concurrency. */ - final KeyValueListParser.IntValue SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS = - new KeyValueListParser.IntValue( - "screen_off_job_concurrency_increase_delay_ms", 30_000); + long SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS = + DEFAULT_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS; /** * The minimum backoff time to allow for linear backoff. */ - long MIN_LINEAR_BACKOFF_TIME = DEFAULT_MIN_LINEAR_BACKOFF_TIME; + long MIN_LINEAR_BACKOFF_TIME_MS = DEFAULT_MIN_LINEAR_BACKOFF_TIME_MS; /** * The minimum backoff time to allow for exponential backoff. */ - long MIN_EXP_BACKOFF_TIME = DEFAULT_MIN_EXP_BACKOFF_TIME; + long MIN_EXP_BACKOFF_TIME_MS = DEFAULT_MIN_EXP_BACKOFF_TIME_MS; /** * The fraction of a job's running window that must pass before we @@ -652,61 +670,78 @@ public class JobSchedulerService extends com.android.server.SystemService public boolean API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT; - private final KeyValueListParser mParser = new KeyValueListParser(','); - - void updateConstantsLocked(String value) { - try { - mParser.setString(value); - } catch (Exception e) { - // Failed to parse the settings string, log this and move on - // with defaults. - Slog.e(TAG, "Bad jobscheduler settings", e); - } - - MIN_READY_NON_ACTIVE_JOBS_COUNT = mParser.getInt( + private void updateBatchingConstantsLocked() { + MIN_READY_NON_ACTIVE_JOBS_COUNT = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_READY_NON_ACTIVE_JOBS_COUNT, DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT); - MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = mParser.getLong( + MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = DeviceConfig.getLong( + DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS, DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS); - HEAVY_USE_FACTOR = mParser.getFloat(KEY_HEAVY_USE_FACTOR, + } + + private void updateUseFactorConstantsLocked() { + HEAVY_USE_FACTOR = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + KEY_HEAVY_USE_FACTOR, DEFAULT_HEAVY_USE_FACTOR); - MODERATE_USE_FACTOR = mParser.getFloat(KEY_MODERATE_USE_FACTOR, + MODERATE_USE_FACTOR = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + KEY_MODERATE_USE_FACTOR, DEFAULT_MODERATE_USE_FACTOR); + } - MAX_JOB_COUNTS_SCREEN_ON.normal.parse(mParser); - MAX_JOB_COUNTS_SCREEN_ON.moderate.parse(mParser); - MAX_JOB_COUNTS_SCREEN_ON.low.parse(mParser); - MAX_JOB_COUNTS_SCREEN_ON.critical.parse(mParser); + void updateConcurrencyConstantsLocked() { + MAX_JOB_COUNTS_SCREEN_ON.normal.update(); + MAX_JOB_COUNTS_SCREEN_ON.moderate.update(); + MAX_JOB_COUNTS_SCREEN_ON.low.update(); + MAX_JOB_COUNTS_SCREEN_ON.critical.update(); - MAX_JOB_COUNTS_SCREEN_OFF.normal.parse(mParser); - MAX_JOB_COUNTS_SCREEN_OFF.moderate.parse(mParser); - MAX_JOB_COUNTS_SCREEN_OFF.low.parse(mParser); - MAX_JOB_COUNTS_SCREEN_OFF.critical.parse(mParser); + MAX_JOB_COUNTS_SCREEN_OFF.normal.update(); + MAX_JOB_COUNTS_SCREEN_OFF.moderate.update(); + MAX_JOB_COUNTS_SCREEN_OFF.low.update(); + MAX_JOB_COUNTS_SCREEN_OFF.critical.update(); - SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.parse(mParser); + SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS = DeviceConfig.getLong( + DeviceConfig.NAMESPACE_JOB_SCHEDULER, + KEY_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS, + DEFAULT_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS); + } - MIN_LINEAR_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_LINEAR_BACKOFF_TIME, - DEFAULT_MIN_LINEAR_BACKOFF_TIME); - MIN_EXP_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_EXP_BACKOFF_TIME, - DEFAULT_MIN_EXP_BACKOFF_TIME); - CONN_CONGESTION_DELAY_FRAC = mParser.getFloat(KEY_CONN_CONGESTION_DELAY_FRAC, + private void updateBackoffConstantsLocked() { + MIN_LINEAR_BACKOFF_TIME_MS = DeviceConfig.getLong(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + KEY_MIN_LINEAR_BACKOFF_TIME_MS, + DEFAULT_MIN_LINEAR_BACKOFF_TIME_MS); + MIN_EXP_BACKOFF_TIME_MS = DeviceConfig.getLong(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + KEY_MIN_EXP_BACKOFF_TIME_MS, + DEFAULT_MIN_EXP_BACKOFF_TIME_MS); + } + + private void updateConnectivityConstantsLocked() { + CONN_CONGESTION_DELAY_FRAC = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + KEY_CONN_CONGESTION_DELAY_FRAC, DEFAULT_CONN_CONGESTION_DELAY_FRAC); - CONN_PREFETCH_RELAX_FRAC = mParser.getFloat(KEY_CONN_PREFETCH_RELAX_FRAC, + CONN_PREFETCH_RELAX_FRAC = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + KEY_CONN_PREFETCH_RELAX_FRAC, DEFAULT_CONN_PREFETCH_RELAX_FRAC); + } - ENABLE_API_QUOTAS = mParser.getBoolean(KEY_ENABLE_API_QUOTAS, - DEFAULT_ENABLE_API_QUOTAS); + private void updateApiQuotaConstantsLocked() { + ENABLE_API_QUOTAS = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + KEY_ENABLE_API_QUOTAS, DEFAULT_ENABLE_API_QUOTAS); // Set a minimum value on the quota limit so it's not so low that it interferes with // legitimate use cases. API_QUOTA_SCHEDULE_COUNT = Math.max(250, - mParser.getInt(KEY_API_QUOTA_SCHEDULE_COUNT, DEFAULT_API_QUOTA_SCHEDULE_COUNT)); - API_QUOTA_SCHEDULE_WINDOW_MS = mParser.getDurationMillis( + DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + KEY_API_QUOTA_SCHEDULE_COUNT, DEFAULT_API_QUOTA_SCHEDULE_COUNT)); + API_QUOTA_SCHEDULE_WINDOW_MS = DeviceConfig.getLong( + DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_API_QUOTA_SCHEDULE_WINDOW_MS, DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS); - API_QUOTA_SCHEDULE_THROW_EXCEPTION = mParser.getBoolean( + API_QUOTA_SCHEDULE_THROW_EXCEPTION = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION, DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION); - API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = mParser.getBoolean( + API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT, DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT); } @@ -731,10 +766,11 @@ public class JobSchedulerService extends com.android.server.SystemService MAX_JOB_COUNTS_SCREEN_OFF.low.dump(pw, ""); MAX_JOB_COUNTS_SCREEN_OFF.critical.dump(pw, ""); - SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.dump(pw, ""); + pw.print(KEY_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS, + SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS).println(); - pw.print(KEY_MIN_LINEAR_BACKOFF_TIME, MIN_LINEAR_BACKOFF_TIME).println(); - pw.print(KEY_MIN_EXP_BACKOFF_TIME, MIN_EXP_BACKOFF_TIME).println(); + pw.print(KEY_MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME_MS).println(); + pw.print(KEY_MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME_MS).println(); pw.print(KEY_CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC).println(); pw.print(KEY_CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC).println(); @@ -760,11 +796,11 @@ public class JobSchedulerService extends com.android.server.SystemService MAX_JOB_COUNTS_SCREEN_ON.dumpProto(proto, ConstantsProto.MAX_JOB_COUNTS_SCREEN_ON); MAX_JOB_COUNTS_SCREEN_OFF.dumpProto(proto, ConstantsProto.MAX_JOB_COUNTS_SCREEN_OFF); - SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.dumpProto(proto, - ConstantsProto.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS); + proto.write(ConstantsProto.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS, + SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS); - proto.write(ConstantsProto.MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME); - proto.write(ConstantsProto.MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME); + proto.write(ConstantsProto.MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME_MS); + proto.write(ConstantsProto.MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME_MS); proto.write(ConstantsProto.CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC); proto.write(ConstantsProto.CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC); @@ -1407,7 +1443,7 @@ public class JobSchedulerService extends com.android.server.SystemService mHandler = new JobHandler(context.getMainLooper()); mConstants = new Constants(); - mConstantsObserver = new ConstantsObserver(mHandler); + mConstantsObserver = new ConstantsObserver(); mJobSchedulerStub = new JobSchedulerStub(); mConcurrencyManager = new JobConcurrencyManager(this); @@ -1521,7 +1557,7 @@ public class JobSchedulerService extends com.android.server.SystemService @Override public void onBootPhase(int phase) { if (PHASE_SYSTEM_SERVICES_READY == phase) { - mConstantsObserver.start(getContext().getContentResolver()); + mConstantsObserver.start(); for (StateController controller : mControllers) { controller.onSystemServicesReady(); } @@ -1693,8 +1729,8 @@ public class JobSchedulerService extends com.android.server.SystemService switch (job.getBackoffPolicy()) { case JobInfo.BACKOFF_POLICY_LINEAR: { long backoff = initialBackoffMillis; - if (backoff < mConstants.MIN_LINEAR_BACKOFF_TIME) { - backoff = mConstants.MIN_LINEAR_BACKOFF_TIME; + if (backoff < mConstants.MIN_LINEAR_BACKOFF_TIME_MS) { + backoff = mConstants.MIN_LINEAR_BACKOFF_TIME_MS; } delayMillis = backoff * backoffAttempts; } break; @@ -1704,8 +1740,8 @@ public class JobSchedulerService extends com.android.server.SystemService } case JobInfo.BACKOFF_POLICY_EXPONENTIAL: { long backoff = initialBackoffMillis; - if (backoff < mConstants.MIN_EXP_BACKOFF_TIME) { - backoff = mConstants.MIN_EXP_BACKOFF_TIME; + if (backoff < mConstants.MIN_EXP_BACKOFF_TIME_MS) { + backoff = mConstants.MIN_EXP_BACKOFF_TIME_MS; } delayMillis = (long) Math.scalb(backoff, backoffAttempts - 1); } break; diff --git a/api/current.txt b/api/current.txt index 9e0d88ecdfd1..bf0b0cb67a99 100644 --- a/api/current.txt +++ b/api/current.txt @@ -36733,9 +36733,11 @@ package android.os { public final class PowerManager { method public void addThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener); method public void addThermalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.PowerManager.OnThermalStatusChangedListener); + method @Nullable public java.time.Duration getBatteryDischargePrediction(); method public int getCurrentThermalStatus(); method public int getLocationPowerSaveMode(); method public float getThermalHeadroom(@IntRange(from=0, to=60) int); + method public boolean isBatteryDischargePredictionPersonalized(); method public boolean isDeviceIdleMode(); method public boolean isIgnoringBatteryOptimizations(String); method public boolean isInteractive(); diff --git a/api/system-current.txt b/api/system-current.txt index 3ab164554da6..b4869e3bf0ce 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8394,6 +8394,7 @@ package android.os { method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressedForToken(@NonNull String); method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean); method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig); + method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void setBatteryDischargePrediction(@NonNull java.time.Duration, boolean); method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setDynamicPowerSaveHint(boolean, int); method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveModeEnabled(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void suppressAmbientDisplay(@NonNull String, boolean); @@ -12744,8 +12745,8 @@ package android.webkit { public interface PacProcessor { method @Nullable public String findProxyForUrl(@NonNull String); method @NonNull public static android.webkit.PacProcessor getInstance(); - method @NonNull public static android.webkit.PacProcessor getInstanceForNetwork(long); - method public default long getNetworkHandle(); + method @NonNull public static android.webkit.PacProcessor getInstanceForNetwork(@Nullable android.net.Network); + method @Nullable public default android.net.Network getNetwork(); method public default void releasePacProcessor(); method public boolean setProxyScript(@NonNull String); } @@ -12886,7 +12887,7 @@ package android.webkit { method public android.webkit.CookieManager getCookieManager(); method public android.webkit.GeolocationPermissions getGeolocationPermissions(); method @NonNull public default android.webkit.PacProcessor getPacProcessor(); - method @NonNull public default android.webkit.PacProcessor getPacProcessorForNetwork(long); + method @NonNull public default android.webkit.PacProcessor getPacProcessorForNetwork(@Nullable android.net.Network); method public android.webkit.ServiceWorkerController getServiceWorkerController(); method public android.webkit.WebViewFactoryProvider.Statics getStatics(); method @Deprecated public android.webkit.TokenBindingService getTokenBindingService(); diff --git a/api/test-current.txt b/api/test-current.txt index c37c6f79218f..a97a9e88a368 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -2799,8 +2799,10 @@ package android.os { public final class PowerManager { method @RequiresPermission("android.permission.POWER_SAVER") public int getPowerSaveModeTrigger(); + method @RequiresPermission("android.permission.DEVICE_POWER") public void setBatteryDischargePrediction(@NonNull java.time.Duration, boolean); method @RequiresPermission("android.permission.POWER_SAVER") public boolean setDynamicPowerSaveHint(boolean, int); method @RequiresPermission(anyOf={"android.permission.DEVICE_POWER", "android.permission.POWER_SAVER"}) public boolean setPowerSaveModeEnabled(boolean); + field public static final String ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED = "android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED"; field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1 field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0 } @@ -3238,6 +3240,7 @@ package android.provider { field public static final String NAMESPACE_AUTOFILL = "autofill"; field public static final String NAMESPACE_BIOMETRICS = "biometrics"; field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture"; + field public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler"; field public static final String NAMESPACE_PERMISSIONS = "permissions"; field public static final String NAMESPACE_PRIVACY = "privacy"; field public static final String NAMESPACE_ROLLBACK = "rollback"; diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp index 7a1ece94fd3e..3b65f8225ee9 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp +++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp @@ -38,9 +38,23 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf const vector<sp<ConditionTracker>>& allConditionTrackers, const unordered_map<int64_t, int>& conditionIdIndexMap, vector<bool>& stack, - vector<ConditionState>& initialConditionCache) { + vector<ConditionState>& conditionCache) { VLOG("Combination predicate init() %lld", (long long)mConditionId); if (mInitialized) { + // All the children are guaranteed to be initialized, but the recursion is needed to + // fill the conditionCache properly, since another combination condition or metric + // might rely on this. The recursion is needed to compute the current condition. + + // Init is called instead of isConditionMet so that the ConditionKey can be filled with the + // default key for sliced conditions, since we do not know all indirect descendants here. + for (const int childIndex : mChildren) { + if (conditionCache[childIndex] == ConditionState::kNotEvaluated) { + allConditionTrackers[childIndex]->init(allConditionConfig, allConditionTrackers, + conditionIdIndexMap, stack, conditionCache); + } + } + conditionCache[mIndex] = + evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache); return true; } @@ -74,9 +88,8 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf return false; } - bool initChildSucceeded = - childTracker->init(allConditionConfig, allConditionTrackers, conditionIdIndexMap, - stack, initialConditionCache); + bool initChildSucceeded = childTracker->init(allConditionConfig, allConditionTrackers, + conditionIdIndexMap, stack, conditionCache); if (!initChildSucceeded) { ALOGW("Child initialization failed %lld ", (long long)child); @@ -96,10 +109,10 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf childTracker->getAtomMatchingTrackerIndex().end()); } - mUnSlicedPartCondition = evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation, - initialConditionCache); - initialConditionCache[mIndex] = - evaluateCombinationCondition(mChildren, mLogicalOperation, initialConditionCache); + mUnSlicedPartCondition = + evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation, conditionCache); + conditionCache[mIndex] = + evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache); // unmark this node in the recursion stack. stack[mIndex] = false; diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h index 39ff0ab03266..a7fac3deaabe 100644 --- a/cmds/statsd/src/condition/CombinationConditionTracker.h +++ b/cmds/statsd/src/condition/CombinationConditionTracker.h @@ -33,7 +33,7 @@ public: bool init(const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack, - std::vector<ConditionState>& initialConditionCache) override; + std::vector<ConditionState>& conditionCache) override; void evaluateCondition(const LogEvent& event, const std::vector<MatchingState>& eventMatcherValues, diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h index 9da1af427e5f..4e1253506be7 100644 --- a/cmds/statsd/src/condition/ConditionTracker.h +++ b/cmds/statsd/src/condition/ConditionTracker.h @@ -46,17 +46,19 @@ public: // Initialize this ConditionTracker. This initialization is done recursively (DFS). It can also // be done in the constructor, but we do it separately because (1) easy to return a bool to // indicate whether the initialization is successful. (2) makes unit test easier. + // This function can also be called on config updates, in which case it does nothing other than + // fill the condition cache with the current condition. // allConditionConfig: the list of all Predicate config from statsd_config. // allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also // need to call init() on children conditions) // conditionIdIndexMap: the mapping from condition id to its index. // stack: a bit map to keep track which nodes have been visited on the stack in the recursion. - // initialConditionCache: tracks initial conditions of all ConditionTrackers. + // conditionCache: tracks initial conditions of all ConditionTrackers. returns the + // current condition if called on a config update. virtual bool init(const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, const std::unordered_map<int64_t, int>& conditionIdIndexMap, - std::vector<bool>& stack, - std::vector<ConditionState>& initialConditionCache) = 0; + std::vector<bool>& stack, std::vector<ConditionState>& conditionCache) = 0; // evaluate current condition given the new event. // event: the new log event diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp index efb4d4989425..f45759b6a77e 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp +++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp @@ -95,11 +95,14 @@ SimpleConditionTracker::~SimpleConditionTracker() { bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig, const vector<sp<ConditionTracker>>& allConditionTrackers, const unordered_map<int64_t, int>& conditionIdIndexMap, - vector<bool>& stack, - vector<ConditionState>& initialConditionCache) { + vector<bool>& stack, vector<ConditionState>& conditionCache) { // SimpleConditionTracker does not have dependency on other conditions, thus we just return // if the initialization was successful. - initialConditionCache[mIndex] = mInitialValue; + ConditionKey conditionKey; + if (mSliced) { + conditionKey[mConditionId] = DEFAULT_DIMENSION_KEY; + } + isConditionMet(conditionKey, allConditionTrackers, mSliced, conditionCache); return mInitialized; } diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h index ea7f87bde2b8..1a9e35e38207 100644 --- a/cmds/statsd/src/condition/SimpleConditionTracker.h +++ b/cmds/statsd/src/condition/SimpleConditionTracker.h @@ -38,7 +38,7 @@ public: bool init(const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack, - std::vector<ConditionState>& initialConditionCache) override; + std::vector<ConditionState>& conditionCache) override; void evaluateCondition(const LogEvent& event, const std::vector<MatchingState>& eventMatcherValues, diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp index daf67e93557c..e40fbdb250f1 100644 --- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp @@ -303,8 +303,7 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config, const int conditionTrackerCount = config.predicate_size(); conditionConfigs.reserve(conditionTrackerCount); allConditionTrackers.reserve(conditionTrackerCount); - initialConditionCache.reserve(conditionTrackerCount); - std::fill(initialConditionCache.begin(), initialConditionCache.end(), ConditionState::kUnknown); + initialConditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated); for (int i = 0; i < conditionTrackerCount; i++) { const Predicate& condition = config.predicate(i); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index f6b533434ac2..1b3e865945d1 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -187,6 +187,16 @@ class ContextImpl extends Context { private static final String XATTR_INODE_CODE_CACHE = "user.inode_code_cache"; /** + * Special intent extra that critical system apps can use to hide the notification for a + * foreground service. This extra should be placed in the intent passed into {@link + * #startForegroundService(Intent)}. + * + * @hide + */ + private static final String EXTRA_HIDDEN_FOREGROUND_SERVICE = + "android.intent.extra.HIDDEN_FOREGROUND_SERVICE"; + + /** * Map from package name, to preference name, to cached preferences. */ @GuardedBy("ContextImpl.class") @@ -1698,9 +1708,12 @@ class ContextImpl extends Context { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); + final boolean hideForegroundNotification = requireForeground + && service.getBooleanExtra(EXTRA_HIDDEN_FOREGROUND_SERVICE, false); ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground, + hideForegroundNotification, getOpPackageName(), getAttributionTag(), user.getIdentifier()); if (cn != null) { if (cn.getPackageName().equals("!")) { diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index f37ca61ba69f..0a47248e3b70 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -156,7 +156,8 @@ interface IActivityManager { boolean refContentProvider(in IBinder connection, int stableDelta, int unstableDelta); PendingIntent getRunningServiceControlPanel(in ComponentName service); ComponentName startService(in IApplicationThread caller, in Intent service, - in String resolvedType, boolean requireForeground, in String callingPackage, + in String resolvedType, boolean requireForeground, + boolean hideForegroundNotification, in String callingPackage, in String callingFeatureId, int userId); @UnsupportedAppUsage int stopService(in IApplicationThread caller, in Intent service, diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index fb2120e5a35b..1aafe2cc6350 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -825,8 +825,8 @@ public class ResourcesManager { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#createApkAssetsSupplierNotLocked"); try { - if (Thread.holdsLock(this)) { - Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + if (DEBUG && Thread.holdsLock(this)) { + Slog.w(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding mLock", new Throwable()); } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index b0d449769be4..fecfd3c2dc7a 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -2954,7 +2954,7 @@ public abstract class BatteryStats implements Parcelable { * enough current data to make a decision, or the battery is currently * charging. * - * @param curTime The current elepsed realtime in microseconds. + * @param curTime The current elapsed realtime in microseconds. */ @UnsupportedAppUsage public abstract long computeBatteryTimeRemaining(long curTime); diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index ce6c0ffbc10b..a92d91bdefc5 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -18,6 +18,7 @@ package android.os; import android.os.BatterySaverPolicyConfig; +import android.os.ParcelDuration; import android.os.PowerSaveState; import android.os.WorkSource; @@ -58,6 +59,9 @@ interface IPowerManager boolean setAdaptivePowerSavePolicy(in BatterySaverPolicyConfig config); boolean setAdaptivePowerSaveEnabled(boolean enabled); int getPowerSaveModeTrigger(); + void setBatteryDischargePrediction(in ParcelDuration timeRemaining, boolean isCustomized); + ParcelDuration getBatteryDischargePrediction(); + boolean isBatteryDischargePredictionPersonalized(); boolean isDeviceIdleMode(); boolean isLightDeviceIdleMode(); diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/dagger/OneHandedModule.java b/core/java/android/os/ParcelDuration.aidl index fe5fa2b5fccd..e1aa109f14ae 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/dagger/OneHandedModule.java +++ b/core/java/android/os/ParcelDuration.aidl @@ -14,23 +14,6 @@ * limitations under the License. */ -package com.android.systemui.onehanded.dagger; +package android.os; -import com.android.systemui.onehanded.OneHandedManager; -import com.android.systemui.onehanded.OneHandedManagerImpl; - -import dagger.Binds; -import dagger.Module; - -/** - * Dagger Module for One handed. - */ -@Module -public abstract class OneHandedModule { - - /** Binds OneHandedManager as the default. */ - @Binds - public abstract OneHandedManager provideOneHandedManager( - OneHandedManagerImpl oneHandedManagerImpl); - -} +parcelable ParcelDuration cpp_header "android/ParcelDuration.h";
\ No newline at end of file diff --git a/core/java/android/os/ParcelDuration.java b/core/java/android/os/ParcelDuration.java new file mode 100644 index 000000000000..37cde3125cb5 --- /dev/null +++ b/core/java/android/os/ParcelDuration.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2020 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.os; + +import android.annotation.NonNull; + +import java.time.Duration; + +/** + * Parcelable version of {@link Duration} that can be used in binder calls. + * + * @hide + */ +public final class ParcelDuration implements Parcelable { + + private final long mSeconds; + private final int mNanos; + + /** + * Construct a Duration object using the given millisecond value. + * + * @hide + */ + public ParcelDuration(long ms) { + this(Duration.ofMillis(ms)); + } + + /** + * Wrap a {@link Duration} instance. + * + * @param duration The {@link Duration} instance to wrap. + */ + public ParcelDuration(@NonNull Duration duration) { + mSeconds = duration.getSeconds(); + mNanos = duration.getNano(); + } + + private ParcelDuration(@NonNull Parcel parcel) { + mSeconds = parcel.readLong(); + mNanos = parcel.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int parcelableFlags) { + parcel.writeLong(mSeconds); + parcel.writeInt(mNanos); + } + + /** + * Returns a {@link Duration} instance that's equivalent to this Duration's length. + * + * @return a {@link Duration} instance of identical length. + */ + @NonNull + public Duration getDuration() { + return Duration.ofSeconds(mSeconds, mNanos); + } + + @Override + @NonNull + public String toString() { + return getDuration().toString(); + } + + /** + * Creator for Duration. + */ + @NonNull + public static final Parcelable.Creator<ParcelDuration> CREATOR = + new Parcelable.Creator<ParcelDuration>() { + + @Override + @NonNull + public ParcelDuration createFromParcel(@NonNull Parcel source) { + return new ParcelDuration(source); + } + + @Override + @NonNull + public ParcelDuration[] newArray(int size) { + return new ParcelDuration[size]; + } + }; +} diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 309805f14eeb..ed38b3ff78e5 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -41,6 +41,7 @@ import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.time.Duration; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicLong; @@ -1719,6 +1720,70 @@ public final class PowerManager { } /** + * Allows an app to tell the system how long it believes the battery will last and whether + * this estimate is customized based on historical device usage or on a generic configuration. + * These estimates will be displayed on system UI surfaces in place of the system computed + * value. + * + * Calling this requires the {@link android.Manifest.permission#DEVICE_POWER} permission. + * + * @param timeRemaining The time remaining as a {@link Duration}. + * @param isPersonalized true if personalized based on device usage history, false otherwise. + * @throws IllegalStateException if the device is powered or currently charging + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.DEVICE_POWER) + public void setBatteryDischargePrediction(@NonNull Duration timeRemaining, + boolean isPersonalized) { + if (timeRemaining == null) { + throw new IllegalArgumentException("time remaining must not be null"); + } + try { + mService.setBatteryDischargePrediction(new ParcelDuration(timeRemaining), + isPersonalized); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the current battery life remaining estimate. + * + * @return The estimated battery life remaining as a {@link Duration}. Will be {@code null} if + * the device is powered, charging, or an error was encountered. + */ + @Nullable + public Duration getBatteryDischargePrediction() { + try { + final ParcelDuration parcelDuration = mService.getBatteryDischargePrediction(); + if (parcelDuration == null) { + return null; + } + return parcelDuration.getDuration(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns whether the current battery life remaining estimate is personalized based on device + * usage history or not. This value does not take a device's powered or charging state into + * account. + * + * @return A boolean indicating if the current discharge estimate is personalized based on + * historical device usage or not. + */ + public boolean isBatteryDischargePredictionPersonalized() { + try { + return mService.isBatteryDischargePredictionPersonalized(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Get data about the battery saver mode for a specific service * @param serviceType unique key for the service, one of {@link ServiceType} * @return Battery saver state data. @@ -2185,6 +2250,18 @@ public final class PowerManager { } /** + * Intent that is broadcast when the enhanced battery discharge prediction changes. The new + * value can be retrieved via {@link #getBatteryDischargePrediction()}. + * This broadcast is only sent to registered receivers. + * + * @hide + */ + @TestApi + @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED = + "android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED"; + + /** * Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes. * This broadcast is only sent to registered receivers. */ diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index b45a1eba1e2f..859b70382328 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -197,6 +197,13 @@ public final class DeviceConfig { "intelligence_content_suggestions"; /** + * Namespace for JobScheduler configurations. + * @hide + */ + @TestApi + public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler"; + + /** * Namespace for all media native related features. * * @hide diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 6903a995bf7b..c302def19298 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -65,6 +65,7 @@ import android.os.Bundle; import android.os.DropBoxManager; import android.os.IBinder; import android.os.LocaleList; +import android.os.PowerManager; import android.os.PowerManager.AutoPowerSaveModeTriggers; import android.os.Process; import android.os.RemoteCallback; @@ -11844,36 +11845,6 @@ public final class Settings { public static final String ALARM_MANAGER_CONSTANTS = "alarm_manager_constants"; /** - * Job scheduler specific settings. - * This is encoded as a key=value list, separated by commas. Ex: - * - * "min_ready_jobs_count=2,moderate_use_factor=.5" - * - * The following keys are supported: - * - * <pre> - * min_idle_count (int) - * min_charging_count (int) - * min_connectivity_count (int) - * min_content_count (int) - * min_ready_jobs_count (int) - * heavy_use_factor (float) - * moderate_use_factor (float) - * fg_job_count (int) - * bg_normal_job_count (int) - * bg_moderate_job_count (int) - * bg_low_job_count (int) - * bg_critical_job_count (int) - * </pre> - * - * <p> - * Type: string - * @hide - * @see com.android.server.job.JobSchedulerService.Constants - */ - public static final String JOB_SCHEDULER_CONSTANTS = "job_scheduler_constants"; - - /** * Job scheduler QuotaController specific settings. * This is encoded as a key=value list, separated by commas. Ex: * @@ -12545,18 +12516,23 @@ public final class Settings { * millis. See {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} for the last time this value * was updated. * + * @deprecated Use {@link PowerManager#getBatteryDischargePrediction()} instead. * @hide */ + @Deprecated public static final String TIME_REMAINING_ESTIMATE_MILLIS = "time_remaining_estimate_millis"; /** - * A boolean indicating whether {@link #TIME_REMAINING_ESTIMATE_MILLIS} is based customized - * to the devices usage or using global models. See + * A boolean indicating whether {@link #TIME_REMAINING_ESTIMATE_MILLIS} is customized + * to the device's usage or using global models. See * {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} for the last time this value was updated. * + * @deprecated Use {@link PowerManager#isBatteryDischargePredictionPersonalized()} instead. + * * @hide */ + @Deprecated public static final String TIME_REMAINING_ESTIMATE_BASED_ON_USAGE = "time_remaining_estimate_based_on_usage"; @@ -12565,8 +12541,10 @@ public final class Settings { * average based on historical drain rates. See {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} * for the last time this value was updated. * + * @deprecated Use {@link PowerManager#getHistoricalDischargeTime()} instead. * @hide */ + @Deprecated public static final String AVERAGE_TIME_TO_DISCHARGE = "average_time_to_discharge"; /** @@ -12575,7 +12553,9 @@ public final class Settings { * and {@link #AVERAGE_TIME_TO_DISCHARGE} were last updated. * * @hide + * @deprecated No longer needed due to {@link PowerManager#getBatteryDischargePrediction}. */ + @Deprecated public static final String BATTERY_ESTIMATES_LAST_UPDATE_TIME = "battery_estimates_last_update_time"; diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java index e341845277d4..1ef701f732ff 100644 --- a/core/java/android/view/InputWindowHandle.java +++ b/core/java/android/view/InputWindowHandle.java @@ -70,11 +70,8 @@ public final class InputWindowHandle { // Window is visible. public boolean visible; - // Window can receive keys. - public boolean canReceiveKeys; - - // Window has focus. - public boolean hasFocus; + // Window can be focused. + public boolean focusable; // Window has wallpaper. (window is the current wallpaper target) public boolean hasWallpaper; diff --git a/core/java/android/webkit/PacProcessor.java b/core/java/android/webkit/PacProcessor.java index 7e7b987f72f3..b04105ab1e75 100644 --- a/core/java/android/webkit/PacProcessor.java +++ b/core/java/android/webkit/PacProcessor.java @@ -32,6 +32,10 @@ public interface PacProcessor { /** * Returns the default PacProcessor instance. * + * <p> There can only be one default {@link PacProcessor} instance. + * This method will create a new instance if one did not already exist, or + * if the previous instance was released with {@link #releasePacProcessor}. + * * @return the default PacProcessor instance. */ @NonNull @@ -43,14 +47,21 @@ public interface PacProcessor { * Returns PacProcessor instance associated with the {@link Network}. * The host resolution is done on this {@link Network}. * - * @param networkHandle a handle representing {@link Network} handle. - * @return PacProcessor instance for the specified network. - * @see Network#getNetworkHandle - * @see Network#fromNetworkHandle + * <p> There can only be one {@link PacProcessor} instance at a time for each {@link Network}. + * This method will create a new instance if one did not already exist, or + * if the previous instance was released with {@link #releasePacProcessor}. + * + * <p> The {@link PacProcessor} instance needs to be released manually with + * {@link #releasePacProcessor} when the associated {@link Network} goes away. + * + * @param network a {@link Network} which this {@link PacProcessor} + * will use for host/address resolution. + * If {@code null} this method is equivalent to {@link #getInstance}. + * @return {@link PacProcessor} instance for the specified network. */ @NonNull - static PacProcessor getInstanceForNetwork(long networkHandle) { - return WebViewFactory.getProvider().getPacProcessorForNetwork(networkHandle); + static PacProcessor getInstanceForNetwork(@Nullable Network network) { + return WebViewFactory.getProvider().getPacProcessorForNetwork(network); } /** @@ -73,19 +84,22 @@ public interface PacProcessor { /** * Stops support for this {@link PacProcessor} and release its resources. * No methods of this class must be called after calling this method. + * + * <p> Released instances will not be reused; a subsequent call to + * {@link #getInstance} and {@link #getInstanceForNetwork} + * for the same network will create a new instance. */ default void releasePacProcessor() { throw new UnsupportedOperationException("Not implemented"); } /** - * Returns a network handle associated with this {@link PacProcessor}. + * Returns a {@link Network} associated with this {@link PacProcessor}. * - * @return a network handle or 0 if a network is unspecified. - * @see Network#getNetworkHandle - * @see Network#fromNetworkHandle + * @return an associated {@link Network} or {@code null} if a network is unspecified. */ - default long getNetworkHandle() { + @Nullable + default Network getNetwork() { throw new UnsupportedOperationException("Not implemented"); } } diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java index f1863e319689..ce999cd5e235 100644 --- a/core/java/android/webkit/WebViewFactoryProvider.java +++ b/core/java/android/webkit/WebViewFactoryProvider.java @@ -17,6 +17,7 @@ package android.webkit; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; @@ -188,13 +189,13 @@ public interface WebViewFactoryProvider { * Returns PacProcessor instance associated with the {@link Network}. * The host resolution is done on this {@link Network}. * - * @param networkHandle a network handle representing the {@link Network}. + * @param network a {@link Network} which needs to be associated + * with the returned {@link PacProcessor}. + * If {@code null} the method returns default {@link PacProcessor}. * @return the {@link PacProcessor} instance associated with {@link Network}. - * @see Network#getNetworkHandle - * @see Network#fromNetworkHandle */ @NonNull - default PacProcessor getPacProcessorForNetwork(long networkHandle) { + default PacProcessor getPacProcessorForNetwork(@Nullable Network network) { throw new UnsupportedOperationException("Not implemented"); } diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java index c82a6564c1d7..937b9426476a 100644 --- a/core/java/com/android/internal/util/Preconditions.java +++ b/core/java/com/android/internal/util/Preconditions.java @@ -200,6 +200,20 @@ public class Preconditions { } /** + * Ensures the truth of an expression involving whether the calling identity is authorized to + * call the calling method. + * + * @param expression a boolean expression + * @param message the message of the security exception to be thrown + * @throws SecurityException if {@code expression} is false + */ + public static void checkSecurity(final boolean expression, final String message) { + if (!expression) { + throw new SecurityException(message); + } + } + + /** * Ensures the truth of an expression involving whether the calling user is authorized to * call the calling method. * diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp index ecdba3fcb023..a0638207a841 100644 --- a/core/jni/android_hardware_input_InputWindowHandle.cpp +++ b/core/jni/android_hardware_input_InputWindowHandle.cpp @@ -56,8 +56,7 @@ static struct { jfieldID scaleFactor; jfieldID touchableRegion; jfieldID visible; - jfieldID canReceiveKeys; - jfieldID hasFocus; + jfieldID focusable; jfieldID hasWallpaper; jfieldID paused; jfieldID trustedOverlay; @@ -145,10 +144,7 @@ bool NativeInputWindowHandle::updateInfo() { mInfo.visible = env->GetBooleanField(obj, gInputWindowHandleClassInfo.visible); - mInfo.canReceiveKeys = env->GetBooleanField(obj, - gInputWindowHandleClassInfo.canReceiveKeys); - mInfo.hasFocus = env->GetBooleanField(obj, - gInputWindowHandleClassInfo.hasFocus); + mInfo.focusable = env->GetBooleanField(obj, gInputWindowHandleClassInfo.focusable); mInfo.hasWallpaper = env->GetBooleanField(obj, gInputWindowHandleClassInfo.hasWallpaper); mInfo.paused = env->GetBooleanField(obj, @@ -320,11 +316,7 @@ int register_android_view_InputWindowHandle(JNIEnv* env) { GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz, "visible", "Z"); - GET_FIELD_ID(gInputWindowHandleClassInfo.canReceiveKeys, clazz, - "canReceiveKeys", "Z"); - - GET_FIELD_ID(gInputWindowHandleClassInfo.hasFocus, clazz, - "hasFocus", "Z"); + GET_FIELD_ID(gInputWindowHandleClassInfo.focusable, clazz, "focusable", "Z"); GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz, "hasWallpaper", "Z"); diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index d5619ca96fbd..9fccdaf9684f 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -507,7 +507,7 @@ message GlobalSettingsProto { } optional IntentFirewall intent_firewall = 65; - optional SettingProto job_scheduler_constants = 66 [ (android.privacy).dest = DEST_AUTOMATIC ]; + reserved 66; // job_scheduler_constants optional SettingProto job_scheduler_quota_controller_constants = 149 [ (android.privacy).dest = DEST_AUTOMATIC ]; reserved 150; // job_scheduler_time_controller_constants diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto index 0455d58f498b..a2f2c46cba6a 100644 --- a/core/proto/android/server/powermanagerservice.proto +++ b/core/proto/android/server/powermanagerservice.proto @@ -174,6 +174,16 @@ message PowerManagerServiceDumpProto { optional BatterySaverStateMachineProto battery_saver_state_machine = 50; // Attentive timeout in ms. The timeout is disabled if it is set to -1. optional sint32 attentive_timeout_ms = 51; + // The time (in the elapsed realtime timebase) at which the battery level will reach 0%. This + // is provided as an enhanced estimate and only valid if + // last_enhanced_discharge_time_updated_elapsed is greater than 0. + optional int64 enhanced_discharge_time_elapsed = 52; + // Timestamp (in the elapsed realtime timebase) of last update to enhanced battery estimate + // data. + optional int64 last_enhanced_discharge_time_updated_elapsed = 53; + // Whether or not the current enhanced discharge prediction is personalized based on device + // usage or not. + optional bool is_enhanced_discharge_prediction_personalized = 54; } // A com.android.server.power.PowerManagerService.SuspendBlockerImpl object. diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 32c1e4a1411c..57c1fcf7bfb4 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -102,6 +102,7 @@ <protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" /> <protected-broadcast android:name="android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED" /> <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL" /> + <protected-broadcast android:name="android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED" /> <!-- @deprecated This is rarely used and will be phased out soon. --> <protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" /> @@ -5040,6 +5041,10 @@ <permission android:name="android.permission.RESET_APP_ERRORS" android:protectionLevel="signature" /> + <!-- @hide Allows an application to create/destroy input consumer. --> + <permission android:name="android.permission.INPUT_CONSUMER" + android:protectionLevel="signature" /> + <!-- Attribution for Geofencing service. --> <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/> <!-- Attribution for Country Detector. --> diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index e90fbd4dead8..2ce11f1d2c39 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -35282,9 +35282,11 @@ package android.os { public final class PowerManager { method public void addThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener); method public void addThermalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.PowerManager.OnThermalStatusChangedListener); + method @Nullable public java.time.Duration getBatteryDischargePrediction(); method public int getCurrentThermalStatus(); method public int getLocationPowerSaveMode(); method public float getThermalHeadroom(@IntRange(from=0, to=60) int); + method public boolean isBatteryDischargePredictionPersonalized(); method public boolean isDeviceIdleMode(); method public boolean isIgnoringBatteryOptimizations(String); method public boolean isInteractive(); diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt index 3fd0ee1c8011..bc8517d6180a 100644 --- a/non-updatable-api/system-current.txt +++ b/non-updatable-api/system-current.txt @@ -7298,6 +7298,7 @@ package android.os { method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressedForToken(@NonNull String); method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean); method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig); + method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void setBatteryDischargePrediction(@NonNull java.time.Duration, boolean); method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setDynamicPowerSaveHint(boolean, int); method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveModeEnabled(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void suppressAmbientDisplay(@NonNull String, boolean); @@ -11585,8 +11586,8 @@ package android.webkit { public interface PacProcessor { method @Nullable public String findProxyForUrl(@NonNull String); method @NonNull public static android.webkit.PacProcessor getInstance(); - method @NonNull public static android.webkit.PacProcessor getInstanceForNetwork(long); - method public default long getNetworkHandle(); + method @NonNull public static android.webkit.PacProcessor getInstanceForNetwork(@Nullable android.net.Network); + method @Nullable public default android.net.Network getNetwork(); method public default void releasePacProcessor(); method public boolean setProxyScript(@NonNull String); } @@ -11727,7 +11728,7 @@ package android.webkit { method public android.webkit.CookieManager getCookieManager(); method public android.webkit.GeolocationPermissions getGeolocationPermissions(); method @NonNull public default android.webkit.PacProcessor getPacProcessor(); - method @NonNull public default android.webkit.PacProcessor getPacProcessorForNetwork(long); + method @NonNull public default android.webkit.PacProcessor getPacProcessorForNetwork(@Nullable android.net.Network); method public android.webkit.ServiceWorkerController getServiceWorkerController(); method public android.webkit.WebViewFactoryProvider.Statics getStatics(); method @Deprecated public android.webkit.TokenBindingService getTokenBindingService(); diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java index b2f98ecde513..24d9d09d2ca9 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java @@ -22,7 +22,6 @@ import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.SystemServicesModule; import com.android.systemui.dagger.SystemUIModule; -import com.android.systemui.onehanded.dagger.OneHandedModule; import com.android.systemui.pip.phone.dagger.PipModule; import dagger.Subcomponent; @@ -36,7 +35,6 @@ import dagger.Subcomponent; DependencyProvider.class, DependencyBinder.class, PipModule.class, - OneHandedModule.class, SystemServicesModule.class, SystemUIModule.class, CarSystemUIModule.class, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 66be8dd68283..a29314817a8f 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -860,9 +860,6 @@ class SettingsProtoDumpUtil { p.end(intentFirewallToken); dumpSetting(s, p, - Settings.Global.JOB_SCHEDULER_CONSTANTS, - GlobalSettingsProto.JOB_SCHEDULER_CONSTANTS); - dumpSetting(s, p, Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS, GlobalSettingsProto.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS); dumpSetting(s, p, diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 0ac3355c4952..f219aecfc9d9 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -309,7 +309,6 @@ public class SettingsBackupTest { Settings.Global.INSTANT_APP_DEXOPT_ENABLED, Settings.Global.INTENT_FIREWALL_UPDATE_CONTENT_URL, Settings.Global.INTENT_FIREWALL_UPDATE_METADATA_URL, - Settings.Global.JOB_SCHEDULER_CONSTANTS, Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS, Settings.Global.KEEP_PROFILE_IN_BACKGROUND, Settings.Global.KERNEL_CPU_THREAD_READER, diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 4ce9f5a9edc6..af008b996172 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -113,6 +113,7 @@ <uses-permission android:name="android.permission.SET_ORIENTATION" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <uses-permission android:name="android.permission.MONITOR_INPUT" /> + <uses-permission android:name="android.permission.INPUT_CONSUMER" /> <!-- DreamManager --> <uses-permission android:name="android.permission.READ_DREAM_STATE" /> diff --git a/packages/SystemUI/res/layout/notification_conversation_info.xml b/packages/SystemUI/res/layout/notification_conversation_info.xml index 2c4b937ce95b..fd89c0bf39dd 100644 --- a/packages/SystemUI/res/layout/notification_conversation_info.xml +++ b/packages/SystemUI/res/layout/notification_conversation_info.xml @@ -210,7 +210,7 @@ android:clickable="false" android:focusable="false" android:ellipsize="end" - android:maxLines="3" + android:maxLines="4" android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/> </com.android.systemui.statusbar.notification.row.ButtonLinearLayout> diff --git a/packages/SystemUI/res/layout/partial_conversation_info.xml b/packages/SystemUI/res/layout/partial_conversation_info.xml index 07951705664a..c353d089895c 100644 --- a/packages/SystemUI/res/layout/partial_conversation_info.xml +++ b/packages/SystemUI/res/layout/partial_conversation_info.xml @@ -128,6 +128,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" + android:textDirection="locale" style="@style/TextAppearance.NotificationImportanceChannelGroup" /> </LinearLayout> </com.android.systemui.statusbar.notification.row.ButtonLinearLayout> diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index 7281faf1a2c4..b606201cc803 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -22,7 +22,6 @@ import com.android.systemui.InitController; import com.android.systemui.SystemUIAppComponentFactory; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardSliceProvider; -import com.android.systemui.onehanded.dagger.OneHandedModule; import com.android.systemui.pip.phone.dagger.PipModule; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.InjectionInflationController; @@ -37,7 +36,6 @@ import dagger.Subcomponent; DefaultComponentBinder.class, DependencyProvider.class, DependencyBinder.class, - OneHandedModule.class, PipModule.class, SystemServicesModule.class, SystemUIBinder.class, diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java index 90e7e12b2b47..bb59449d114d 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java @@ -49,7 +49,7 @@ import javax.inject.Inject; * Manages and manipulates the one handed states, transitions, and gesture for phones. */ @SysUISingleton -public class OneHandedManagerImpl implements OneHandedManager, Dumpable { +public class OneHandedController implements Dumpable { private static final String TAG = "OneHandedManager"; private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE = "persist.debug.one_handed_offset_percentage"; @@ -106,7 +106,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { * Constructor of OneHandedManager */ @Inject - public OneHandedManagerImpl(Context context, + public OneHandedController(Context context, CommandQueue commandQueue, DisplayController displayController, NavigationModeController navigationModeController, @@ -137,7 +137,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { */ // TODO(b/161980408): Should remove extra constructor. @VisibleForTesting - OneHandedManagerImpl(Context context, + OneHandedController(Context context, CommandQueue commandQueue, DisplayController displayController, OneHandedDisplayAreaOrganizer displayAreaOrganizer, @@ -194,7 +194,6 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { /** * Enters one handed mode. */ - @Override public void startOneHanded() { if (!mDisplayAreaOrganizer.isInOneHanded()) { final int yOffSet = Math.round(getDisplaySize().y * mOffSetFraction); @@ -206,7 +205,6 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { /** * Exits one handed mode. */ - @Override public void stopOneHanded() { if (mDisplayAreaOrganizer.isInOneHanded()) { mDisplayAreaOrganizer.scheduleOffset(0, 0); diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java index 1420811b9b30..f3be699ab821 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java @@ -103,7 +103,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, } /** - * Notified by {@link OneHandedManager}, when user update settings of Enabled or Disabled + * Notified by {@link OneHandedController}, when user update settings of Enabled or Disabled * * @param isEnabled is one handed settings enabled or not */ @@ -264,7 +264,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, } /** - * The touch(gesture) events to notify {@link OneHandedManager} start or stop one handed + * The touch(gesture) events to notify {@link OneHandedController} start or stop one handed */ public interface OneHandedGestureEventCallback { /** diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManager.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManager.java deleted file mode 100644 index 90187a298cf2..000000000000 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManager.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2020 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 com.android.systemui.onehanded; - -/** - * The base class of OneHandedManager - */ -public interface OneHandedManager { - - /** - * Set one handed enabled or disabled - */ - default void setOneHandedEnabled(boolean enabled) {} - - /** - * Set task stack changed to exit - */ - default void setTaskChangeToExit(boolean enabled) {} - - /** - * Exit one handed mode - */ - default void stopOneHanded() {} - - /** - * Trigger one handed mode - */ - default void startOneHanded() {} - -} diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java index 0a7eb1bdada0..8265da6a5f14 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java @@ -63,7 +63,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa } /** - * Notified by {@link OneHandedManagerImpl}, when user update settings of Enabled or Disabled + * Notified by {@link OneHandedController}, when user update settings of Enabled or Disabled * * @param isEnabled is one handed settings enabled or not */ @@ -166,7 +166,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa } /** - * The touch(gesture) events to notify {@link OneHandedManager} start or stop one handed + * The touch(gesture) events to notify {@link OneHandedController} start or stop one handed */ public interface OneHandedTouchEventCallback { /** diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java index cebcd4ceabe9..3348a06d5cac 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java @@ -59,7 +59,7 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum "com.android.internal.systemui.onehanded.gestural"; private static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode"; - private final OneHandedManagerImpl mOneHandedManager; + private final OneHandedController mOneHandedController; private final CommandQueue mCommandQueue; private final Handler mMainHandler = new Handler(Looper.getMainLooper()); private final IOverlayManager mOverlayManager; @@ -74,8 +74,8 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum OneHandedEvents.writeEvent(enabled ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_ON : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF); - if (mOneHandedManager != null) { - mOneHandedManager.setOneHandedEnabled(enabled); + if (mOneHandedController != null) { + mOneHandedController.setOneHandedEnabled(enabled); } // Also checks swipe to notification settings since they all need gesture overlay. @@ -125,8 +125,8 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_ON : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_OFF); - if (mOneHandedManager != null) { - mOneHandedManager.setTaskChangeToExit(enabled); + if (mOneHandedController != null) { + mOneHandedController.setTaskChangeToExit(enabled); } } }; @@ -138,8 +138,8 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum final boolean enabled = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( mContext.getContentResolver()); - if (mOneHandedManager != null) { - mOneHandedManager.setSwipeToNotificationEnabled(enabled); + if (mOneHandedController != null) { + mOneHandedController.setSwipeToNotificationEnabled(enabled); } // Also checks one handed mode settings since they all need gesture overlay. @@ -152,14 +152,14 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum @Inject public OneHandedUI(Context context, CommandQueue commandQueue, - OneHandedManagerImpl oneHandedManager, + OneHandedController oneHandedController, ScreenLifecycle screenLifecycle) { super(context); if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) { Log.i(TAG, "Device config SUPPORT_ONE_HANDED_MODE off"); mCommandQueue = null; - mOneHandedManager = null; + mOneHandedController = null; mOverlayManager = null; mTimeoutHandler = null; mScreenLifecycle = null; @@ -167,7 +167,7 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum } mCommandQueue = commandQueue; - mOneHandedManager = oneHandedManager; + mOneHandedController = oneHandedController; mTimeoutHandler = OneHandedTimeoutHandler.get(); mScreenLifecycle = screenLifecycle; mOverlayManager = IOverlayManager.Stub.asInterface( @@ -260,13 +260,13 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum } private void updateSettings() { - mOneHandedManager.setOneHandedEnabled(OneHandedSettingsUtil + mOneHandedController.setOneHandedEnabled(OneHandedSettingsUtil .getSettingsOneHandedModeEnabled(mContext.getContentResolver())); mTimeoutHandler.setTimeout(OneHandedSettingsUtil .getSettingsOneHandedModeTimeout(mContext.getContentResolver())); - mOneHandedManager.setTaskChangeToExit(OneHandedSettingsUtil + mOneHandedController.setTaskChangeToExit(OneHandedSettingsUtil .getSettingsTapsAppToExit(mContext.getContentResolver())); - mOneHandedManager.setSwipeToNotificationEnabled(OneHandedSettingsUtil + mOneHandedController.setSwipeToNotificationEnabled(OneHandedSettingsUtil .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver())); } @@ -295,7 +295,7 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum * Trigger one handed more */ public void startOneHanded() { - mOneHandedManager.startOneHanded(); + mOneHandedController.startOneHanded(); OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_IN); } @@ -303,7 +303,7 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum * Dismiss one handed more */ public void stopOneHanded() { - mOneHandedManager.stopOneHanded(); + mOneHandedController.stopOneHanded(); OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT); } @@ -314,8 +314,8 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum final String innerPrefix = " "; pw.println(TAG + "one handed states: "); - if (mOneHandedManager != null) { - ((OneHandedManagerImpl) mOneHandedManager).dump(fd, pw, args); + if (mOneHandedController != null) { + mOneHandedController.dump(fd, pw, args); } if (mTimeoutHandler != null) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java index 20fa991dcc1f..6b42f2e07bc3 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW; +import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_VENDOR_GESTURE; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; @@ -37,6 +38,8 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum { SCREENSHOT_REQUESTED_OVERVIEW(304), @UiEvent(doc = "screenshot requested from accessibility actions") SCREENSHOT_REQUESTED_ACCESSIBILITY_ACTIONS(382), + @UiEvent(doc = "screenshot requested from vendor gesture") + SCREENSHOT_REQUESTED_VENDOR_GESTURE(638), @UiEvent(doc = "screenshot requested (other)") SCREENSHOT_REQUESTED_OTHER(305), @UiEvent(doc = "screenshot was saved") @@ -81,6 +84,8 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum { return ScreenshotEvent.SCREENSHOT_REQUESTED_OVERVIEW; case SCREENSHOT_ACCESSIBILITY_ACTIONS: return ScreenshotEvent.SCREENSHOT_REQUESTED_ACCESSIBILITY_ACTIONS; + case SCREENSHOT_VENDOR_GESTURE: + return ScreenshotEvent.SCREENSHOT_REQUESTED_VENDOR_GESTURE; case SCREENSHOT_OTHER: default: return ScreenshotEvent.SCREENSHOT_REQUESTED_OTHER; diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java index b7bc8c8fb7c4..302301d79c3a 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java @@ -24,7 +24,6 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.SystemServicesModule; import com.android.systemui.dagger.SystemUIBinder; import com.android.systemui.dagger.SystemUIModule; -import com.android.systemui.onehanded.dagger.OneHandedModule; import dagger.Subcomponent; @@ -36,7 +35,6 @@ import dagger.Subcomponent; DefaultComponentBinder.class, DependencyProvider.class, DependencyBinder.class, - OneHandedModule.class, SystemServicesModule.class, SystemUIBinder.class, SystemUIModule.class, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt index ca8f79d08ef0..da1ec9869d87 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt @@ -21,6 +21,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Before +import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.mock @@ -59,6 +60,7 @@ public class MediaPlayerDataTest : SysuiTestCase() { } @Test + @Ignore("Flaky") fun switchPlayersPlaying() { val playerIsPlaying1 = mock(MediaControlPanel::class.java) whenever(playerIsPlaying1.isPlaying).thenReturn(true) diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java index d7dba5fdf8c8..02d587d90655 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java @@ -46,9 +46,9 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper -public class OneHandedManagerImplTest extends OneHandedTestCase { +public class OneHandedControllerTest extends OneHandedTestCase { Display mDisplay; - OneHandedManagerImpl mOneHandedManagerImpl; + OneHandedController mOneHandedController; OneHandedTimeoutHandler mTimeoutHandler; @Mock @@ -70,7 +70,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mDisplay = mContext.getDisplay(); - mOneHandedManagerImpl = new OneHandedManagerImpl( + mOneHandedController = new OneHandedController( getContext(), mCommandQueue, mMockDisplayController, @@ -102,7 +102,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { @Test public void testStartOneHanded() { - mOneHandedManagerImpl.startOneHanded(); + mOneHandedController.startOneHanded(); verify(mMockDisplayAreaOrganizer).scheduleOffset(anyInt(), anyInt()); } @@ -110,7 +110,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { @Test public void testStopOneHanded() { when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false); - mOneHandedManagerImpl.stopOneHanded(); + mOneHandedController.stopOneHanded(); verify(mMockDisplayAreaOrganizer, never()).scheduleOffset(anyInt(), anyInt()); } @@ -122,7 +122,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { @Test public void testStopOneHanded_shouldRemoveTimer() { - mOneHandedManagerImpl.stopOneHanded(); + mOneHandedController.stopOneHanded(); verify(mTimeoutHandler).removeTimer(); } @@ -130,7 +130,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { @Test public void testUpdateIsEnabled() { final boolean enabled = true; - mOneHandedManagerImpl.setOneHandedEnabled(enabled); + mOneHandedController.setOneHandedEnabled(enabled); verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled); } @@ -138,7 +138,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { @Test public void testUpdateSwipeToNotificationIsEnabled() { final boolean enabled = true; - mOneHandedManagerImpl.setSwipeToNotificationEnabled(enabled); + mOneHandedController.setSwipeToNotificationEnabled(enabled); verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java index 95a230f6511c..756382a6c630 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java @@ -30,8 +30,8 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.systemui.model.SysUiState; -import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.statusbar.CommandQueue; import com.android.wm.shell.common.DisplayController; import org.junit.Before; @@ -48,7 +48,7 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase { OneHandedTouchHandler mTouchHandler; OneHandedTutorialHandler mTutorialHandler; OneHandedGestureHandler mGestureHandler; - OneHandedManagerImpl mOneHandedManagerImpl; + OneHandedController mOneHandedController; @Mock CommandQueue mCommandQueue; @Mock @@ -66,7 +66,7 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase { mTutorialHandler = new OneHandedTutorialHandler(mContext); mGestureHandler = Mockito.spy(new OneHandedGestureHandler( mContext, mMockDisplayController, mMockNavigationModeController)); - mOneHandedManagerImpl = new OneHandedManagerImpl( + mOneHandedController = new OneHandedController( getContext(), mCommandQueue, mMockDisplayController, @@ -93,15 +93,15 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase { public void testReceiveNewConfig_whenSetOneHandedEnabled() { // 1st called at init verify(mGestureHandler).onOneHandedEnabled(true); - mOneHandedManagerImpl.setOneHandedEnabled(true); + mOneHandedController.setOneHandedEnabled(true); // 2nd called by setOneHandedEnabled() verify(mGestureHandler, times(2)).onOneHandedEnabled(true); } @Test public void testOneHandedDisabled_shouldDisposeInputChannel() { - mOneHandedManagerImpl.setOneHandedEnabled(false); - mOneHandedManagerImpl.setSwipeToNotificationEnabled(false); + mOneHandedController.setOneHandedEnabled(false); + mOneHandedController.setSwipeToNotificationEnabled(false); assertThat(mGestureHandler.mInputMonitor).isNull(); assertThat(mGestureHandler.mInputEventReceiver).isNull(); @@ -111,7 +111,7 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase { public void testChangeNavBarTo2Button_shouldDisposeInputChannel() { // 1st called at init verify(mGestureHandler).onOneHandedEnabled(true); - mOneHandedManagerImpl.setOneHandedEnabled(true); + mOneHandedController.setOneHandedEnabled(true); // 2nd called by setOneHandedEnabled() verify(mGestureHandler, times(2)).onOneHandedEnabled(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java index 8ae632dd5a47..3c3ace052e47 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java @@ -28,8 +28,8 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.systemui.model.SysUiState; -import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.statusbar.CommandQueue; import com.android.wm.shell.common.DisplayController; import org.junit.Before; @@ -46,7 +46,7 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase { OneHandedTouchHandler mTouchHandler; OneHandedTutorialHandler mTutorialHandler; OneHandedGestureHandler mGestureHandler; - OneHandedManagerImpl mOneHandedManagerImpl; + OneHandedController mOneHandedController; @Mock CommandQueue mCommandQueue; @Mock @@ -64,7 +64,7 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase { mTouchHandler = Mockito.spy(new OneHandedTouchHandler()); mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController, mMockNavigationModeController); - mOneHandedManagerImpl = new OneHandedManagerImpl( + mOneHandedController = new OneHandedController( getContext(), mCommandQueue, mMockDisplayController, @@ -88,14 +88,14 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase { @Test public void testOneHandedDisabled_shouldDisposeInputChannel() { - mOneHandedManagerImpl.setOneHandedEnabled(false); + mOneHandedController.setOneHandedEnabled(false); assertThat(mTouchHandler.mInputMonitor).isNull(); assertThat(mTouchHandler.mInputEventReceiver).isNull(); } @Test public void testOneHandedEnabled_monitorInputChannel() { - mOneHandedManagerImpl.setOneHandedEnabled(true); + mOneHandedController.setOneHandedEnabled(true); assertThat(mTouchHandler.mInputMonitor).isNotNull(); assertThat(mTouchHandler.mInputEventReceiver).isNotNull(); } @@ -104,7 +104,7 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase { public void testReceiveNewConfig_whenSetOneHandedEnabled() { // 1st called at init verify(mTouchHandler).onOneHandedEnabled(true); - mOneHandedManagerImpl.setOneHandedEnabled(true); + mOneHandedController.setOneHandedEnabled(true); // 2nd called by setOneHandedEnabled() verify(mTouchHandler, times(2)).onOneHandedEnabled(true); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java index c75a8d2f5454..1bffbf7eb8dd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java @@ -24,8 +24,8 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.systemui.model.SysUiState; -import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.statusbar.CommandQueue; import com.android.wm.shell.common.DisplayController; import org.junit.Before; @@ -42,7 +42,7 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase { OneHandedTouchHandler mTouchHandler; OneHandedTutorialHandler mTutorialHandler; OneHandedGestureHandler mGestureHandler; - OneHandedManagerImpl mOneHandedManagerImpl; + OneHandedController mOneHandedController; @Mock CommandQueue mCommandQueue; @Mock @@ -61,7 +61,7 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase { mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext)); mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController, mMockNavigationModeController); - mOneHandedManagerImpl = new OneHandedManagerImpl( + mOneHandedController = new OneHandedController( getContext(), mCommandQueue, mMockDisplayController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java index f0e713e42046..ae3df5db30bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java @@ -48,7 +48,7 @@ public class OneHandedUITest extends OneHandedTestCase { OneHandedUI mOneHandedUI; ScreenLifecycle mScreenLifecycle; @Mock - OneHandedManagerImpl mMockOneHandedManagerImpl; + OneHandedController mOneHandedController; @Mock OneHandedTimeoutHandler mMockTimeoutHandler; @@ -59,7 +59,7 @@ public class OneHandedUITest extends OneHandedTestCase { mScreenLifecycle = new ScreenLifecycle(); mOneHandedUI = new OneHandedUI(mContext, mCommandQueue, - mMockOneHandedManagerImpl, + mOneHandedController, mScreenLifecycle); mOneHandedUI.start(); mKeyguardUpdateMonitor = mDependency.injectMockDependency(KeyguardUpdateMonitor.class); @@ -74,14 +74,14 @@ public class OneHandedUITest extends OneHandedTestCase { public void testStartOneHanded() { mOneHandedUI.startOneHanded(); - verify(mMockOneHandedManagerImpl).startOneHanded(); + verify(mOneHandedController).startOneHanded(); } @Test public void testStopOneHanded() { mOneHandedUI.stopOneHanded(); - verify(mMockOneHandedManagerImpl).stopOneHanded(); + verify(mOneHandedController).stopOneHanded(); } @Test @@ -89,7 +89,7 @@ public class OneHandedUITest extends OneHandedTestCase { Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.TAPS_APP_TO_EXIT, 1); - verify(mMockOneHandedManagerImpl).setTaskChangeToExit(true); + verify(mOneHandedController).setTaskChangeToExit(true); } @Test @@ -97,7 +97,7 @@ public class OneHandedUITest extends OneHandedTestCase { Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.ONE_HANDED_MODE_ENABLED, 1); - verify(mMockOneHandedManagerImpl).setOneHandedEnabled(true); + verify(mOneHandedController).setOneHandedEnabled(true); } @Test @@ -115,7 +115,7 @@ public class OneHandedUITest extends OneHandedTestCase { Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1); - verify(mMockOneHandedManagerImpl).setSwipeToNotificationEnabled(true); + verify(mOneHandedController).setSwipeToNotificationEnabled(true); } @Ignore("Clarifying do not receive callback") @@ -123,14 +123,14 @@ public class OneHandedUITest extends OneHandedTestCase { public void testKeyguardBouncerShowing_shouldStopOneHanded() { mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true); - verify(mMockOneHandedManagerImpl).stopOneHanded(); + verify(mOneHandedController).stopOneHanded(); } @Test public void testScreenTurningOff_shouldStopOneHanded() { mScreenLifecycle.dispatchScreenTurningOff(); - verify(mMockOneHandedManagerImpl).stopOneHanded(); + verify(mOneHandedController).stopOneHanded(); } } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 6328cb60cf73..c31d73246ff6 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -453,16 +453,16 @@ public final class ActiveServices { } ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, - int callingPid, int callingUid, boolean fgRequired, String callingPackage, - @Nullable String callingFeatureId, final int userId) + int callingPid, int callingUid, boolean fgRequired, boolean hideFgNotification, + String callingPackage, @Nullable String callingFeatureId, final int userId) throws TransactionTooLargeException { return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired, - callingPackage, callingFeatureId, userId, false); + hideFgNotification, callingPackage, callingFeatureId, userId, false); } ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, - int callingPid, int callingUid, boolean fgRequired, String callingPackage, - @Nullable String callingFeatureId, final int userId, + int callingPid, int callingUid, boolean fgRequired, boolean hideFgNotification, + String callingPackage, @Nullable String callingFeatureId, final int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service + " type=" + resolvedType + " args=" + service.getExtras()); @@ -626,6 +626,7 @@ public final class ActiveServices { r.startRequested = true; r.delayedStop = false; r.fgRequired = fgRequired; + r.hideFgNotification = hideFgNotification; r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), service, neededGrants, callingUid)); diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index e9539be8b0d5..fede1d2832b8 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -89,6 +89,7 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time"; static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration"; static final String KEY_PENDINGINTENT_WARNING_THRESHOLD = "pendingintent_warning_threshold"; + static final String KEY_MIN_CRASH_INTERVAL = "min_crash_interval"; private static final int DEFAULT_MAX_CACHED_PROCESSES = 32; private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000; @@ -122,6 +123,8 @@ final class ActivityManagerConstants extends ContentObserver { private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000; private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000; private static final int DEFAULT_PENDINGINTENT_WARNING_THRESHOLD = 2000; + private static final int DEFAULT_MIN_CRASH_INTERVAL = 2 * 60 * 1000; + // Flag stored in the DeviceConfig API. /** @@ -281,6 +284,12 @@ final class ActivityManagerConstants extends ContentObserver { // this long. public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION; + /** + * The minimum time we allow between crashes, for us to consider this + * application to be bad and stop its services and reject broadcasts. + */ + public static int MIN_CRASH_INTERVAL = DEFAULT_MIN_CRASH_INTERVAL; + // Indicates whether the activity starts logging is enabled. // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED volatile boolean mFlagActivityStartsLoggingEnabled; @@ -650,6 +659,8 @@ final class ActivityManagerConstants extends ContentObserver { DEFAULT_MEMORY_INFO_THROTTLE_TIME); TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION, DEFAULT_TOP_TO_FGS_GRACE_DURATION); + MIN_CRASH_INTERVAL = mParser.getInt(KEY_MIN_CRASH_INTERVAL, + DEFAULT_MIN_CRASH_INTERVAL); PENDINGINTENT_WARNING_THRESHOLD = mParser.getInt(KEY_PENDINGINTENT_WARNING_THRESHOLD, DEFAULT_PENDINGINTENT_WARNING_THRESHOLD); @@ -866,6 +877,8 @@ final class ActivityManagerConstants extends ContentObserver { pw.println(MEMORY_INFO_THROTTLE_TIME); pw.print(" "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("="); pw.println(TOP_TO_FGS_GRACE_DURATION); + pw.print(" "); pw.print(KEY_MIN_CRASH_INTERVAL); pw.print("="); + pw.println(MIN_CRASH_INTERVAL); pw.print(" "); pw.print(KEY_IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES); pw.print("="); pw.println(Arrays.toString(IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.toArray())); pw.print(" "); pw.print(KEY_IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES); pw.print("="); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 3e600b793385..6e1e3d0a9a9a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1370,6 +1370,10 @@ public class ActivityManagerService extends IActivityManager.Stub final Injector mInjector; + /** The package verifier app. */ + private String mPackageVerifier; + private int mPackageVerifierUid = UserHandle.USER_NULL; + static final class ProcessChangeItem { static final int CHANGE_ACTIVITIES = 1<<0; static final int CHANGE_FOREGROUND_SERVICES = 1<<1; @@ -2246,6 +2250,18 @@ public class ActivityManagerService extends IActivityManager.Stub if (phase == PHASE_SYSTEM_SERVICES_READY) { mService.mBatteryStatsService.systemServicesReady(); mService.mServices.systemServicesReady(); + mService.mPackageVerifier = ArrayUtils.firstOrNull( + LocalServices.getService(PackageManagerInternal.class).getKnownPackageNames( + PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM)); + if (mService.mPackageVerifier != null) { + try { + mService.mPackageVerifierUid = + getContext().getPackageManager().getPackageUid( + mService.mPackageVerifier, UserHandle.USER_SYSTEM); + } catch (NameNotFoundException e) { + Slog.wtf(TAG, "Package manager couldn't get package verifier uid", e); + } + } } else if (phase == PHASE_ACTIVITY_MANAGER_READY) { mService.startBroadcastObservers(); } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { @@ -13263,8 +13279,8 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public ComponentName startService(IApplicationThread caller, Intent service, - String resolvedType, boolean requireForeground, String callingPackage, - String callingFeatureId, int userId) + String resolvedType, boolean requireForeground, boolean hideForegroundNotification, + String callingPackage, String callingFeatureId, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("startService"); // Refuse possible leaked file descriptors @@ -13276,17 +13292,27 @@ public class ActivityManagerService extends IActivityManager.Stub throw new IllegalArgumentException("callingPackage cannot be null"); } + final int callingUid = Binder.getCallingUid(); + if (requireForeground && hideForegroundNotification) { + if (!UserHandle.isSameApp(callingUid, mPackageVerifierUid) + || !callingPackage.equals(mPackageVerifier)) { + throw new IllegalArgumentException( + "Only the package verifier can hide its foreground service notification"); + } + Slog.i(TAG, "Foreground service notification hiding requested by " + callingPackage); + } + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground); synchronized(this) { final int callingPid = Binder.getCallingPid(); - final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, - requireForeground, callingPackage, callingFeatureId, userId); + requireForeground, hideForegroundNotification, + callingPackage, callingFeatureId, userId); } finally { Binder.restoreCallingIdentity(origId); } @@ -17670,7 +17696,7 @@ public class ActivityManagerService extends IActivityManager.Stub ComponentName res; try { res = mServices.startServiceLocked(null, service, - resolvedType, -1, uid, fgRequired, callingPackage, + resolvedType, -1, uid, fgRequired, false, callingPackage, callingFeatureId, userId, allowBackgroundActivityStarts); } finally { Binder.restoreCallingIdentity(origId); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 149e3baa90e7..a512cca7bac4 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -654,7 +654,7 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println("Starting service: " + intent); pw.flush(); ComponentName cn = mInterface.startService(null, intent, intent.getType(), - asForeground, SHELL_PACKAGE_NAME, null, mUserId); + asForeground, false, SHELL_PACKAGE_NAME, null, mUserId); if (cn == null) { err.println("Error: Not found; no service started."); return -1; diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 2e92ac0fb3d6..5268359df327 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -716,7 +716,7 @@ class AppErrors { // back in the pending list. ServiceRecord sr = app.getRunningServiceAt(i); // If the service was restarted a while ago, then reset crash count, else increment it. - if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) { + if (now > sr.restartTime + ActivityManagerConstants.MIN_CRASH_INTERVAL) { sr.crashCount = 1; } else { sr.crashCount++; @@ -729,7 +729,7 @@ class AppErrors { } } - if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) { + if (crashTime != null && now < crashTime + ActivityManagerConstants.MIN_CRASH_INTERVAL) { // The process crashed again very quickly. If it was a bound foreground service, let's // try to restart again in a while, otherwise the process loses! Slog.w(TAG, "Process " + app.processName @@ -771,7 +771,7 @@ class AppErrors { data.taskId = affectedTaskId; } if (data != null && crashTimePersistent != null - && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) { + && now < crashTimePersistent + ActivityManagerConstants.MIN_CRASH_INTERVAL) { data.repeating = true; } } @@ -853,7 +853,7 @@ class AppErrors { mAppsNotReportingCrashes.contains(proc.info.packageName); final long now = SystemClock.uptimeMillis(); final boolean shouldThottle = crashShowErrorTime != null - && now < crashShowErrorTime + ProcessList.MIN_CRASH_INTERVAL; + && now < crashShowErrorTime + ActivityManagerConstants.MIN_CRASH_INTERVAL; if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground) && !crashSilenced && !shouldThottle && (showFirstCrash || showFirstCrashDevOption || data.repeating)) { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 4673ecde7a68..76089f8fba01 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -154,10 +154,6 @@ public final class ProcessList { static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY = "persist.sys.vold_app_data_isolation_enabled"; - // The minimum time we allow between crashes, for us to consider this - // application to be bad and stop and its services and reject broadcasts. - static final int MIN_CRASH_INTERVAL = 60 * 1000; - // OOM adjustments for processes in various states: // Uninitialized value for any major or minor adj fields @@ -4070,7 +4066,8 @@ public final class ProcessList { boolean enqueueLocked(ProcessRecord app, String reason, int requester) { // Throttle the killing request for potential bad app to avoid cpu thrashing Long last = app.isolated ? null : mLastProcessKillTimes.get(app.processName, app.uid); - if (last != null && SystemClock.uptimeMillis() < last + MIN_CRASH_INTERVAL) { + if ((last != null) && (SystemClock.uptimeMillis() + < (last + ActivityManagerConstants.MIN_CRASH_INTERVAL))) { return false; } diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 66677b67b6aa..5b12c8ce6582 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -104,6 +104,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN boolean whitelistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT? boolean delayed; // are we waiting to start this service in the background? boolean fgRequired; // is the service required to go foreground after starting? + boolean hideFgNotification; // Hide the fg service notification boolean fgWaiting; // is a timeout for going foreground already scheduled? boolean isForeground; // is service currently in foreground mode? int foregroundId; // Notification ID of last foreground req. @@ -836,6 +837,9 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } public void postNotification() { + if (hideFgNotification) { + return; + } final int appUid = appInfo.uid; final int appPid = app.pid; if (foregroundId != 0 && foregroundNoti != null) { @@ -928,7 +932,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } if (localForegroundNoti.getSmallIcon() == null) { // Notifications whose icon is 0 are defined to not show - // a notification, silently ignoring it. We don't want to + // a notification. We don't want to // just ignore it, we want to prevent the service from // being foreground. throw new RuntimeException("invalid service notification: " diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 9f9235dc852f..04658555f22b 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -6103,7 +6103,8 @@ public class NotificationManagerService extends SystemService { protected boolean isBlocked(NotificationRecord r, NotificationUsageStats usageStats) { if (isBlocked(r)) { if (DBG) { - Slog.e(TAG, "Suppressing notification from package by user request."); + Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName() + + " by user request."); } usageStats.registerBlocked(r); return true; diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 8f0fd607f928..d4375eb2935b 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -94,6 +94,7 @@ public class Notifier { private static final int MSG_USER_ACTIVITY = 1; private static final int MSG_BROADCAST = 2; private static final int MSG_WIRELESS_CHARGING_STARTED = 3; + private static final int MSG_BROADCAST_ENHANCED_PREDICTION = 4; private static final int MSG_PROFILE_TIMED_OUT = 5; private static final int MSG_WIRED_CHARGING_STARTED = 6; @@ -701,6 +702,16 @@ public class Notifier { mPolicy.userActivity(); } + void postEnhancedDischargePredictionBroadcast(long delayMs) { + mHandler.sendEmptyMessageDelayed(MSG_BROADCAST_ENHANCED_PREDICTION, delayMs); + } + + private void sendEnhancedDischargePredictionBroadcast() { + Intent intent = new Intent(PowerManager.ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + } + private void sendNextBroadcast() { final int powerState; synchronized (mLock) { @@ -872,6 +883,10 @@ public class Notifier { case MSG_WIRELESS_CHARGING_STARTED: showWirelessChargingStarted(msg.arg1, msg.arg2); break; + case MSG_BROADCAST_ENHANCED_PREDICTION: + removeMessages(MSG_BROADCAST_ENHANCED_PREDICTION); + sendEnhancedDischargePredictionBroadcast(); + break; case MSG_PROFILE_TIMED_OUT: lockProfile(msg.arg1); break; diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 882ed1b7960b..9ff164ac4a7b 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -56,6 +56,7 @@ import android.os.IBinder; import android.os.IPowerManager; import android.os.Looper; import android.os.Message; +import android.os.ParcelDuration; import android.os.PowerManager; import android.os.PowerManager.ServiceType; import android.os.PowerManager.WakeData; @@ -89,11 +90,13 @@ import android.view.Display; import android.view.KeyEvent; import com.android.internal.BrightnessSynchronizer; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; import com.android.internal.util.DumpUtils; +import com.android.internal.util.Preconditions; import com.android.server.EventLogTags; import com.android.server.LockGuard; import com.android.server.RescueParty; @@ -238,6 +241,18 @@ public final class PowerManagerService extends SystemService private static final int HALT_MODE_REBOOT = 1; private static final int HALT_MODE_REBOOT_SAFE_MODE = 2; + /** + * How stale we'll allow the enhanced discharge prediction values to get before considering them + * invalid. + */ + private static final long ENHANCED_DISCHARGE_PREDICTION_TIMEOUT_MS = 30 * 60 * 1000L; + + /** + * The minimum amount of time between sending consequent + * {@link PowerManager#ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED} broadcasts. + */ + private static final long ENHANCED_DISCHARGE_PREDICTION_BROADCAST_MIN_DELAY_MS = 60 * 1000L; + private final Context mContext; private final ServiceThread mHandlerThread; private final Handler mHandler; @@ -380,6 +395,34 @@ public final class PowerManagerService extends SystemService // The current battery level percentage. private int mBatteryLevel; + /** + * The lock that should be held when interacting with {@link #mEnhancedDischargeTimeElapsed}, + * {@link #mLastEnhancedDischargeTimeUpdatedElapsed}, and + * {@link #mEnhancedDischargePredictionIsPersonalized}. + */ + private final Object mEnhancedDischargeTimeLock = new Object(); + + /** + * The time (in the elapsed realtime timebase) at which the battery level will reach 0%. This + * is provided as an enhanced estimate and only valid if + * {@link #mLastEnhancedDischargeTimeUpdatedElapsed} is greater than 0. + */ + @GuardedBy("mEnhancedDischargeTimeLock") + private long mEnhancedDischargeTimeElapsed; + + /** + * Timestamp (in the elapsed realtime timebase) of last update to enhanced battery estimate + * data. + */ + @GuardedBy("mEnhancedDischargeTimeLock") + private long mLastEnhancedDischargeTimeUpdatedElapsed; + + /** + * Whether or not the current enhanced discharge prediction is personalized to the user. + */ + @GuardedBy("mEnhancedDischargeTimeLock") + private boolean mEnhancedDischargePredictionIsPersonalized; + // The battery level percentage at the time the dream started. // This is used to terminate a dream and go to sleep if the battery is // draining faster than it is charging and the user activity timeout has expired. @@ -3737,6 +3780,13 @@ public final class PowerManagerService extends SystemService pw.println(" mProximityPositive=" + mProximityPositive); pw.println(" mBootCompleted=" + mBootCompleted); pw.println(" mSystemReady=" + mSystemReady); + synchronized (mEnhancedDischargeTimeLock) { + pw.println(" mEnhancedDischargeTimeElapsed=" + mEnhancedDischargeTimeElapsed); + pw.println(" mLastEnhancedDischargeTimeUpdatedElapsed=" + + mLastEnhancedDischargeTimeUpdatedElapsed); + pw.println(" mEnhancedDischargePredictionIsPersonalized=" + + mEnhancedDischargePredictionIsPersonalized); + } pw.println(" mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled); pw.println(" mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled); pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)); @@ -3952,6 +4002,16 @@ public final class PowerManagerService extends SystemService proto.write(PowerManagerServiceDumpProto.IS_PROXIMITY_POSITIVE, mProximityPositive); proto.write(PowerManagerServiceDumpProto.IS_BOOT_COMPLETED, mBootCompleted); proto.write(PowerManagerServiceDumpProto.IS_SYSTEM_READY, mSystemReady); + synchronized (mEnhancedDischargeTimeLock) { + proto.write(PowerManagerServiceDumpProto.ENHANCED_DISCHARGE_TIME_ELAPSED, + mEnhancedDischargeTimeElapsed); + proto.write( + PowerManagerServiceDumpProto.LAST_ENHANCED_DISCHARGE_TIME_UPDATED_ELAPSED, + mLastEnhancedDischargeTimeUpdatedElapsed); + proto.write( + PowerManagerServiceDumpProto.IS_ENHANCED_DISCHARGE_PREDICTION_PERSONALIZED, + mEnhancedDischargePredictionIsPersonalized); + } proto.write( PowerManagerServiceDumpProto.IS_HAL_AUTO_SUSPEND_MODE_ENABLED, mHalAutoSuspendModeEnabled); @@ -3959,7 +4019,8 @@ public final class PowerManagerService extends SystemService PowerManagerServiceDumpProto.IS_HAL_AUTO_INTERACTIVE_MODE_ENABLED, mHalInteractiveModeEnabled); - final long activeWakeLocksToken = proto.start(PowerManagerServiceDumpProto.ACTIVE_WAKE_LOCKS); + final long activeWakeLocksToken = proto.start( + PowerManagerServiceDumpProto.ACTIVE_WAKE_LOCKS); proto.write( PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_CPU, (mWakeLockSummary & WAKE_LOCK_CPU) != 0); @@ -4262,6 +4323,7 @@ public final class PowerManagerService extends SystemService if (wcd != null) { wcd.dumpDebug(proto, PowerManagerServiceDumpProto.WIRELESS_CHARGER_DETECTOR); } + proto.flush(); } @@ -5022,6 +5084,96 @@ public final class PowerManagerService extends SystemService } @Override // Binder call + public void setBatteryDischargePrediction(@NonNull ParcelDuration timeRemaining, + boolean isPersonalized) { + // Get current time before acquiring the lock so that the calculated end time is as + // accurate as possible. + final long nowElapsed = SystemClock.elapsedRealtime(); + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); + + final long timeRemainingMs = timeRemaining.getDuration().toMillis(); + // A non-positive number means the battery should be dead right now... + Preconditions.checkArgumentPositive(timeRemainingMs, + "Given time remaining is not positive: " + timeRemainingMs); + + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + if (mIsPowered) { + throw new IllegalStateException( + "Discharge prediction can't be set while the device is charging"); + } + } + + final long broadcastDelayMs; + synchronized (mEnhancedDischargeTimeLock) { + if (mLastEnhancedDischargeTimeUpdatedElapsed > nowElapsed) { + // Another later call made it into the block first. Keep the latest info. + return; + } + broadcastDelayMs = Math.max(0, + ENHANCED_DISCHARGE_PREDICTION_BROADCAST_MIN_DELAY_MS + - (nowElapsed - mLastEnhancedDischargeTimeUpdatedElapsed)); + + // No need to persist the discharge prediction values since they'll most likely + // be wrong immediately after a reboot anyway. + mEnhancedDischargeTimeElapsed = nowElapsed + timeRemainingMs; + mEnhancedDischargePredictionIsPersonalized = isPersonalized; + mLastEnhancedDischargeTimeUpdatedElapsed = nowElapsed; + } + mNotifier.postEnhancedDischargePredictionBroadcast(broadcastDelayMs); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private boolean isEnhancedDischargePredictionValidLocked(long nowElapsed) { + return mLastEnhancedDischargeTimeUpdatedElapsed > 0 + && nowElapsed < mEnhancedDischargeTimeElapsed + && nowElapsed - mLastEnhancedDischargeTimeUpdatedElapsed + < ENHANCED_DISCHARGE_PREDICTION_TIMEOUT_MS; + } + + @Override // Binder call + public ParcelDuration getBatteryDischargePrediction() { + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + if (mIsPowered) { + return null; + } + } + synchronized (mEnhancedDischargeTimeLock) { + // Get current time after acquiring the lock so that the calculated duration + // is as accurate as possible. + final long nowElapsed = SystemClock.elapsedRealtime(); + if (isEnhancedDischargePredictionValidLocked(nowElapsed)) { + return new ParcelDuration(mEnhancedDischargeTimeElapsed - nowElapsed); + } + } + return new ParcelDuration(mBatteryStats.computeBatteryTimeRemaining()); + } catch (RemoteException e) { + // Shouldn't happen in-process. + } finally { + Binder.restoreCallingIdentity(ident); + } + return null; + } + + @Override // Binder call + public boolean isBatteryDischargePredictionPersonalized() { + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mEnhancedDischargeTimeLock) { + return isEnhancedDischargePredictionValidLocked(SystemClock.elapsedRealtime()) + && mEnhancedDischargePredictionIsPersonalized; + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override // Binder call public boolean isDeviceIdleMode() { final long ident = Binder.clearCallingIdentity(); try { diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java index 6dc1d6921dbb..0abeac890df1 100644 --- a/services/core/java/com/android/server/storage/StorageSessionController.java +++ b/services/core/java/com/android/server/storage/StorageSessionController.java @@ -336,11 +336,12 @@ public final class StorageSessionController { } /** - * Returns {@code true} if {@code vol} is an emulated or public volume, + * Returns {@code true} if {@code vol} is an emulated or visible public volume, * {@code false} otherwise **/ public static boolean isEmulatedOrPublic(VolumeInfo vol) { - return vol.type == VolumeInfo.TYPE_EMULATED || vol.type == VolumeInfo.TYPE_PUBLIC; + return vol.type == VolumeInfo.TYPE_EMULATED + || (vol.type == VolumeInfo.TYPE_PUBLIC && vol.isVisible()); } /** Exception thrown when communication with the {@link ExternalStorageService} fails. */ diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 133b11116460..c9f463b8fbeb 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -283,8 +283,9 @@ class DragState { mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; mDragWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; mDragWindowHandle.visible = true; - mDragWindowHandle.canReceiveKeys = false; - mDragWindowHandle.hasFocus = true; + // Allows the system to consume keys when dragging is active. This can also be used to + // modify the drag state on key press. Example, cancel drag on escape key. + mDragWindowHandle.focusable = true; mDragWindowHandle.hasWallpaper = false; mDragWindowHandle.paused = false; mDragWindowHandle.ownerPid = Process.myPid(); diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java index 3b24584b0357..a79d3bb00907 100644 --- a/services/core/java/com/android/server/wm/InputConsumerImpl.java +++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java @@ -80,8 +80,7 @@ class InputConsumerImpl implements IBinder.DeathRecipient { mWindowHandle.layoutParamsFlags = 0; mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; mWindowHandle.visible = true; - mWindowHandle.canReceiveKeys = false; - mWindowHandle.hasFocus = false; + mWindowHandle.focusable = false; mWindowHandle.hasWallpaper = false; mWindowHandle.paused = false; mWindowHandle.ownerPid = Process.myPid(); diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 0fe9735c9e46..16c4942ee972 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -227,6 +227,11 @@ final class InputMonitor { WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name, InputEventReceiver.Factory inputEventReceiverFactory) { + if (!name.contentEquals(INPUT_CONSUMER_NAVIGATION)) { + throw new IllegalArgumentException("Illegal input consumer : " + name + + ", display: " + mDisplayId); + } + if (mInputConsumers.containsKey(name)) { throw new IllegalStateException("Existing input consumer found with name: " + name + ", display: " + mDisplayId); @@ -256,6 +261,11 @@ final class InputMonitor { // stack, and we need FLAG_NOT_TOUCH_MODAL to ensure other events fall through consumer.mWindowHandle.layoutParamsFlags |= FLAG_NOT_TOUCH_MODAL; break; + case INPUT_CONSUMER_RECENTS_ANIMATION: + break; + default: + throw new IllegalArgumentException("Illegal input consumer : " + name + + ", display: " + mDisplayId); } addInputConsumer(name, consumer); } @@ -271,8 +281,7 @@ final class InputMonitor { inputWindowHandle.layoutParamsType = type; inputWindowHandle.dispatchingTimeoutMillis = child.getInputDispatchingTimeoutMillis(); inputWindowHandle.visible = isVisible; - inputWindowHandle.canReceiveKeys = child.canReceiveKeys(); - inputWindowHandle.hasFocus = hasFocus; + inputWindowHandle.focusable = hasFocus; inputWindowHandle.hasWallpaper = hasWallpaper; inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false; inputWindowHandle.ownerPid = child.mSession.mPid; @@ -463,9 +472,6 @@ final class InputMonitor { mDisplayContent.forAllWindows(this, true /* traverseTopToBottom */); - if (mAddWallpaperInputConsumerHandle) { - mWallpaperInputConsumer.show(mInputTransaction, 0); - } if (!mUpdateInputWindowsImmediately) { mDisplayContent.getPendingTransaction().merge(mInputTransaction); mDisplayContent.scheduleAnimation(); @@ -572,8 +578,7 @@ final class InputMonitor { inputWindowHandle.layoutParamsType = type; inputWindowHandle.dispatchingTimeoutMillis = 0; // it should never receive input inputWindowHandle.visible = isVisible; - inputWindowHandle.canReceiveKeys = false; - inputWindowHandle.hasFocus = false; + inputWindowHandle.focusable = false; inputWindowHandle.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL; inputWindowHandle.scaleFactor = 1; inputWindowHandle.layoutParamsFlags = diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 143fbb0fe48b..6882dc4ca151 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -821,7 +821,7 @@ public class RecentsAnimationController implements DeathRecipient { : null; if (targetAppMainWindow != null) { targetAppMainWindow.getBounds(mTmpRect); - inputWindowHandle.hasFocus = hasFocus; + inputWindowHandle.focusable = hasFocus; inputWindowHandle.touchableRegion.set(mTmpRect); return true; } diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index a66cd846e8be..f32781a8fcb8 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -242,8 +242,8 @@ class TaskPositioner implements IBinder.DeathRecipient { mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG; mDragWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; mDragWindowHandle.visible = true; - mDragWindowHandle.canReceiveKeys = false; - mDragWindowHandle.hasFocus = true; + // When dragging the window around, we do not want to steal focus for the window. + mDragWindowHandle.focusable = false; mDragWindowHandle.hasWallpaper = false; mDragWindowHandle.paused = false; mDragWindowHandle.ownerPid = Process.myPid(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 32251976eba1..2ce16b2fdd79 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; +import static android.Manifest.permission.INPUT_CONSUMER; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; import static android.Manifest.permission.MANAGE_APP_TOKENS; @@ -5861,6 +5862,11 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void createInputConsumer(IBinder token, String name, int displayId, InputChannel inputChannel) { + if (!mAtmInternal.isCallerRecents(Binder.getCallingUid()) + && mContext.checkCallingOrSelfPermission(INPUT_CONSUMER) != PERMISSION_GRANTED) { + throw new SecurityException("createInputConsumer requires INPUT_CONSUMER permission"); + } + synchronized (mGlobalLock) { DisplayContent display = mRoot.getDisplayContent(displayId); if (display != null) { @@ -5872,6 +5878,11 @@ public class WindowManagerService extends IWindowManager.Stub @Override public boolean destroyInputConsumer(String name, int displayId) { + if (!mAtmInternal.isCallerRecents(Binder.getCallingUid()) + && mContext.checkCallingOrSelfPermission(INPUT_CONSUMER) != PERMISSION_GRANTED) { + throw new SecurityException("destroyInputConsumer requires INPUT_CONSUMER permission"); + } + synchronized (mGlobalLock) { DisplayContent display = mRoot.getDisplayContent(displayId); if (display != null) { @@ -8065,8 +8076,7 @@ public class WindowManagerService extends IWindowManager.Stub h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags; h.layoutParamsType = type; h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; - h.canReceiveKeys = false; - h.hasFocus = false; + h.focusable = false; h.hasWallpaper = false; h.paused = false; diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 92177abbbf85..4ff985f6bd43 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -38,6 +38,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; +import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; @@ -1327,7 +1328,7 @@ class WindowStateAnimator { mWin.getDisplayContent().adjustForImeIfNeeded(); } - return mWin.isAnimating(PARENTS); + return mWin.isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION); } void dumpDebug(ProtoOutputStream proto, long fieldId) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 6154bef2bda3..e49c5abf59f3 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -1566,7 +1566,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { /** * Creates a new {@link CallerIdentity} object to represent the caller's identity. */ - private CallerIdentity getCallerIdentity(String callerPackage) { + private CallerIdentity getCallerIdentity() { + final int callerUid = mInjector.binderGetCallingUid(); + return new CallerIdentity(callerUid, null, null); + } + + /** + * Creates a new {@link CallerIdentity} object to represent the caller's identity. + */ + private CallerIdentity getCallerIdentity(@NonNull String callerPackage) { final int callerUid = mInjector.binderGetCallingUid(); if (!isCallingFromPackage(callerPackage, callerUid)) { @@ -2127,6 +2135,81 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { reqPolicy, /* permission= */ null); } + @NonNull ActiveAdmin getDeviceOwnerOfCallerLocked(final CallerIdentity caller) { + ensureLocked(); + ComponentName doComponent = mOwners.getDeviceOwnerComponent(); + Preconditions.checkState(doComponent != null, + String.format("No device owner for user %d", caller.getUid())); + + // Use the user ID of the caller instead of mOwners.getDeviceOwnerUserId() because + // secondary, affiliated users will have their own admin. + ActiveAdmin doAdmin = getUserData(caller.getUserId()).mAdminMap.get(doComponent); + Preconditions.checkState(doAdmin != null, + String.format("Device owner %s for user %d not found", doComponent, + caller.getUid())); + + Preconditions.checkSecurity(doAdmin.getUid() == caller.getUid(), + String.format("Admin %s is not owned by uid %d, but uid %d", doComponent, + caller.getUid(), doAdmin.getUid())); + + Preconditions.checkSecurity(doAdmin.info.getComponent().equals(caller.getComponentName()), + String.format("Caller component %s is not device owner", + caller.getComponentName())); + + return doAdmin; + } + + @NonNull ActiveAdmin getProfileOwnerOfCallerLocked(final CallerIdentity caller) { + ensureLocked(); + final ComponentName poAdminComponent = mOwners.getProfileOwnerComponent(caller.getUserId()); + + Preconditions.checkState(poAdminComponent != null, + String.format("No profile owner for user %d", caller.getUid())); + + ActiveAdmin poAdmin = getUserData(caller.getUserId()).mAdminMap.get(poAdminComponent); + Preconditions.checkState(poAdmin != null, + String.format("No device profile owner for caller %d", caller.getUid())); + + Preconditions.checkSecurity(poAdmin.getUid() == caller.getUid(), + String.format("Admin %s is not owned by uid %d", poAdminComponent, + caller.getUid())); + + Preconditions.checkSecurity(poAdmin.info.getComponent().equals(caller.getComponentName()), + String.format("Caller component %s is not profile owner", + caller.getComponentName())); + + return poAdmin; + } + + @NonNull ActiveAdmin getOrganizationOwnedProfileOwnerLocked(final CallerIdentity caller) { + final ActiveAdmin profileOwner = getProfileOwnerOfCallerLocked(caller); + + Preconditions.checkSecurity( + mOwners.isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId()), + String.format("Admin %s is not of an org-owned device", + profileOwner.info.getComponent())); + + return profileOwner; + } + + @NonNull ActiveAdmin getProfileOwnerOrDeviceOwnerLocked(final CallerIdentity caller) { + ensureLocked(); + // Try to find an admin which can use reqPolicy + final ComponentName poAdminComponent = mOwners.getProfileOwnerComponent(caller.getUserId()); + final ComponentName doAdminComponent = mOwners.getDeviceOwnerComponent(); + + if (poAdminComponent == null && doAdminComponent == null) { + throw new IllegalStateException( + String.format("No profile or device owner for user %d", caller.getUid())); + } + + if (poAdminComponent != null) { + return getProfileOwnerOfCallerLocked(caller); + } + + return getDeviceOwnerOfCallerLocked(caller); + } + /** * Finds an active admin for the caller then checks {@code permission} if admin check failed. * @@ -2145,9 +2228,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { ActiveAdmin result = getActiveAdminWithPolicyForUidLocked(who, reqPolicy, callingUid); if (result != null) { return result; - } else if (permission != null - && (mContext.checkCallingPermission(permission) - == PackageManager.PERMISSION_GRANTED)) { + } else if (permission != null && hasCallingPermission(permission)) { return null; } @@ -2844,9 +2925,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle, Bundle onEnableData) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_DEVICE_ADMINS, null); - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization( + hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS)); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); DevicePolicyData policy = getUserData(userHandle); DeviceAdminInfo info = findAdmin(adminReceiver, userHandle, @@ -2986,7 +3070,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return false; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null; } @@ -2997,7 +3085,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return false; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { DevicePolicyData policyData = getUserData(userHandle); return policyData.mRemovingAdmins.contains(adminReceiver); @@ -3009,7 +3101,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return false; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(adminReceiver); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle); if (administrator == null) { @@ -3025,8 +3121,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return Collections.EMPTY_LIST; } + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); - enforceFullCrossUsersPermission(userHandle); synchronized (getLockObject()) { DevicePolicyData policy = getUserData(userHandle); final int N = policy.mAdminList.size(); @@ -3046,7 +3145,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return false; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { DevicePolicyData policy = getUserData(userHandle); final int N = policy.mAdminList.size(); @@ -3156,8 +3259,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); enforceUserUnlocked(userHandle); + synchronized (getLockObject()) { ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle); if (admin == null) { @@ -3309,7 +3416,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return PASSWORD_QUALITY_UNSPECIFIED; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { int mode = PASSWORD_QUALITY_UNSPECIFIED; @@ -3521,7 +3632,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return 0L; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { long timeout = 0L; @@ -3547,12 +3662,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) { - final int userId = UserHandle.getCallingUserId(); + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isProfileOwner(identity)); List<String> changedProviders = null; synchronized (getLockObject()) { - ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin activeAdmin = getProfileOwnerOfCallerLocked(identity); if (activeAdmin.crossProfileWidgetProviders == null) { activeAdmin.crossProfileWidgetProviders = new ArrayList<>(); } @@ -3560,7 +3675,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!providers.contains(packageName)) { providers.add(packageName); changedProviders = new ArrayList<>(providers); - saveSettingsLocked(userId); + saveSettingsLocked(identity.getUserId()); } } @@ -3570,7 +3685,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { .write(); if (changedProviders != null) { - mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders); + mLocalService.notifyCrossProfileProvidersChanged(identity.getUserId(), + changedProviders); return true; } @@ -3579,12 +3695,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) { - final int userId = UserHandle.getCallingUserId(); + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isProfileOwner(identity)); List<String> changedProviders = null; synchronized (getLockObject()) { - ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin activeAdmin = getProfileOwnerOfCallerLocked(identity); if (activeAdmin.crossProfileWidgetProviders == null || activeAdmin.crossProfileWidgetProviders.isEmpty()) { return false; @@ -3592,7 +3708,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { List<String> providers = activeAdmin.crossProfileWidgetProviders; if (providers.remove(packageName)) { changedProviders = new ArrayList<>(providers); - saveSettingsLocked(userId); + saveSettingsLocked(identity.getUserId()); } } @@ -3602,7 +3718,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { .write(); if (changedProviders != null) { - mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders); + mLocalService.notifyCrossProfileProvidersChanged(identity.getUserId(), + changedProviders); return true; } @@ -3611,9 +3728,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public List<String> getCrossProfileWidgetProviders(ComponentName admin) { + final CallerIdentity identity = getCallerIdentity(admin); + Preconditions.checkCallAuthorization(isProfileOwner(identity)); + synchronized (getLockObject()) { - ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin activeAdmin = getProfileOwnerOfCallerLocked(identity); if (activeAdmin.crossProfileWidgetProviders == null || activeAdmin.crossProfileWidgetProviders.isEmpty()) { return null; @@ -3656,7 +3775,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return 0L; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { return getPasswordExpirationLocked(who, userHandle, parent); } @@ -3862,7 +3985,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return 0; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { if (who != null) { final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); @@ -3902,7 +4029,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { new PasswordMetrics(CREDENTIAL_TYPE_NONE); } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + ArrayList<PasswordMetrics> adminMetrics = new ArrayList<>(); synchronized (getLockObject()) { List<ActiveAdmin> admins = @@ -3919,7 +4050,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return true; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); enforceUserUnlocked(userHandle, parent); synchronized (getLockObject()) { @@ -3951,7 +4085,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return true; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); enforceManagedProfile(userHandle, "call APIs refering to the parent profile"); synchronized (getLockObject()) { @@ -3970,7 +4107,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return true; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); enforceNotManagedProfile(userHandle, "check password sufficiency"); enforceUserUnlocked(userHandle); @@ -4058,12 +4198,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mLockPatternUtils.hasSecureLockScreen()) { return 0; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { - if (!isCallerWithSystemUid()) { + if (!isSystemUid(identity)) { // This API can be called by an active device admin or by keyguard code. - if (mContext.checkCallingPermission(permission.ACCESS_KEYGUARD_SECURE_STORAGE) - != PackageManager.PERMISSION_GRANTED) { + if (!hasCallingPermission(permission.ACCESS_KEYGUARD_SECURE_STORAGE)) { getActiveAdminForCallerLocked( null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent); } @@ -4106,7 +4249,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return 0; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { ActiveAdmin admin = (who != null) ? getActiveAdminUncheckedLocked(who, userHandle, parent) @@ -4120,7 +4267,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) { return UserHandle.USER_NULL; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { ActiveAdmin admin = getAdminWithMinimumFailedPasswordsForWipeLocked( userHandle, parent); @@ -4191,8 +4342,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // As of R, only privlleged caller holding RESET_PASSWORD can call resetPassword() to // set password to an unsecured user. - if (mContext.checkCallingPermission(permission.RESET_PASSWORD) - == PackageManager.PERMISSION_GRANTED) { + if (hasCallingPermission(permission.RESET_PASSWORD)) { return setPasswordPrivileged(password, flags, callingUid); } @@ -4392,7 +4542,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return 0; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { if (who != null) { final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent); @@ -4465,12 +4619,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS; } + Preconditions.checkArgumentNonnegative(userId, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userId)); + if (!mLockPatternUtils.hasSecureLockScreen()) { // No strong auth timeout on devices not supporting the // {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature return 0; } - enforceFullCrossUsersPermission(userId); synchronized (getLockObject()) { if (who != null) { ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId, parent); @@ -4504,8 +4662,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void lockNow(int flags, boolean parent) { - if (!mHasFeature && mContext.checkCallingPermission(android.Manifest.permission.LOCK_DEVICE) - != PackageManager.PERMISSION_GRANTED) { + if (!mHasFeature && !hasCallingPermission(permission.LOCK_DEVICE)) { return; } @@ -4597,8 +4754,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private void enforceNetworkStackOrProfileOrDeviceOwner(ComponentName who) { - if (mContext.checkCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK) - == PackageManager.PERMISSION_GRANTED) { + if (hasCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK)) { return; } enforceProfileOrDeviceOwner(who); @@ -5677,8 +5833,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return; } - - enforceFullCrossUsersPermission(mInjector.userHandleGetCallingUserId()); + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(isSystemUid(identity) || isRootUid(identity) + || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL)); final ActiveAdmin admin; synchronized (getLockObject()) { @@ -5854,8 +6011,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { synchronized (getLockObject()) { if (who == null) { if ((frpManagementAgentUid != mInjector.binderGetCallingUid()) - && (mContext.checkCallingPermission(permission.MASTER_CLEAR) - != PackageManager.PERMISSION_GRANTED)) { + && !hasCallingPermission(permission.MASTER_CLEAR)) { throw new SecurityException( "Must be called by the FRP management agent on device"); } @@ -5893,9 +6049,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return; } - enforceFullCrossUsersPermission(userHandle); - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.BIND_DEVICE_ADMIN, null); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = comp != null + ? getCallerIdentity(comp) + : getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN)); synchronized (getLockObject()) { ActiveAdmin admin = getActiveAdminUncheckedLocked(comp, userHandle); @@ -5972,13 +6132,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void reportFailedPasswordAttempt(int userHandle) { - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN)); if (!isSeparateProfileChallengeEnabled(userHandle)) { enforceNotManagedProfile(userHandle, "report failed password attempt if separate profile challenge is not in place"); } - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.BIND_DEVICE_ADMIN, null); boolean wipeData = false; ActiveAdmin strictestAdmin = null; @@ -6051,9 +6213,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void reportSuccessfulPasswordAttempt(int userHandle) { - enforceFullCrossUsersPermission(userHandle); - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.BIND_DEVICE_ADMIN, null); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN)); synchronized (getLockObject()) { DevicePolicyData policy = getUserData(userHandle); @@ -6079,9 +6243,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void reportFailedBiometricAttempt(int userHandle) { - enforceFullCrossUsersPermission(userHandle); - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.BIND_DEVICE_ADMIN, null); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN)); + if (mInjector.securityLogIsLoggingEnabled()) { SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT, /*result*/ 0, /*method strength*/ 0); @@ -6090,9 +6257,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void reportSuccessfulBiometricAttempt(int userHandle) { - enforceFullCrossUsersPermission(userHandle); - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.BIND_DEVICE_ADMIN, null); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN)); + if (mInjector.securityLogIsLoggingEnabled()) { SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT, /*result*/ 1, /*method strength*/ 0); @@ -6101,9 +6271,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void reportKeyguardDismissed(int userHandle) { - enforceFullCrossUsersPermission(userHandle); - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.BIND_DEVICE_ADMIN, null); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN)); if (mInjector.securityLogIsLoggingEnabled()) { SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISSED); @@ -6112,9 +6284,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void reportKeyguardSecured(int userHandle) { - enforceFullCrossUsersPermission(userHandle); - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.BIND_DEVICE_ADMIN, null); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN)); if (mInjector.securityLogIsLoggingEnabled()) { SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_SECURED); @@ -6176,7 +6350,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return null; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM); // Scan through active admins and find if anyone has already @@ -6310,7 +6488,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return false; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = who != null + ? getCallerIdentity(who) + : getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { // Check for permissions if a particular caller is specified if (who != null) { @@ -6340,7 +6524,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { // Ok to return current status. } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = callerPackage != null + ? getCallerIdentity(callerPackage) + : getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); // It's not critical here, but let's make sure the package name is correct, in case // we start using it for different purposes. @@ -6485,24 +6674,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); - final int userHandle = UserHandle.getCallingUserId(); + final CallerIdentity identity = getCallerIdentity(who); + boolean requireAutoTimeChanged = false; synchronized (getLockObject()) { - if (isManagedProfile(userHandle)) { - throw new SecurityException("Managed profile cannot set auto time required"); - } - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + Preconditions.checkSecurity(!isManagedProfile(identity.getUserId()), + "Managed profile cannot set auto time required"); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); if (admin.requireAutoTime != required) { admin.requireAutoTime = required; - saveSettingsLocked(userHandle); + saveSettingsLocked(identity.getUserId()); requireAutoTimeChanged = true; } } // requireAutoTime is now backed by DISALLOW_CONFIG_DATE_TIME restriction, so propagate // updated restrictions to the framework. if (requireAutoTimeChanged) { - pushUserRestrictions(userHandle); + pushUserRestrictions(identity.getUserId()); } // Turn AUTO_TIME on in settings if it is required if (required) { @@ -7033,7 +7221,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return 0; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + final long ident = mInjector.binderClearCallingIdentity(); try { synchronized (getLockObject()) { @@ -7229,6 +7421,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return who != null && who.equals(profileOwner); } + /** + * Returns {@code true} if the provided caller identity is of a profile owner. + * @param identity identity of caller. + * @return true if {@code identity} is a profile owner, false otherwise. + */ + public boolean isProfileOwner(CallerIdentity identity) { + final ComponentName profileOwner = getProfileOwner(identity.getUserId()); + return profileOwner != null && profileOwner.equals(identity.getComponentName()); + } + private boolean hasProfileOwner(int userId) { synchronized (getLockObject()) { return mOwners.hasProfileOwner(userId); @@ -7783,7 +7985,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public ComponentName getProfileOwnerAsUser(int userHandle) { - enforceCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userHandle)); return getProfileOwner(userHandle); } @@ -8140,56 +8345,31 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private void enforceAcrossUsersPermissions() { - final int callingUid = mInjector.binderGetCallingUid(); - final int callingPid = mInjector.binderGetCallingPid(); - final String packageName = mContext.getPackageName(); - - if (isCallerWithSystemUid() || callingUid == Process.ROOT_UID) { - return; - } - if (PermissionChecker.checkPermissionForPreflight( - mContext, permission.INTERACT_ACROSS_PROFILES, callingPid, callingUid, - packageName) == PermissionChecker.PERMISSION_GRANTED) { - return; - } - if (mContext.checkCallingPermission(permission.INTERACT_ACROSS_USERS) - == PackageManager.PERMISSION_GRANTED) { - return; - } - if (mContext.checkCallingPermission(permission.INTERACT_ACROSS_USERS_FULL) - == PackageManager.PERMISSION_GRANTED) { - return; - } - throw new SecurityException("Calling user does not have INTERACT_ACROSS_PROFILES or" - + "INTERACT_ACROSS_USERS or INTERACT_ACROSS_USERS_FULL permissions"); + private boolean hasCallingPermission(String permission) { + return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED; } - private void enforceFullCrossUsersPermission(int userHandle) { - enforceSystemUserOrPermissionIfCrossUser(userHandle, - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + private boolean hasCallingOrSelfPermission(String permission) { + return mContext.checkCallingOrSelfPermission(permission) + == PackageManager.PERMISSION_GRANTED; } - private void enforceCrossUsersPermission(int userHandle) { - enforceSystemUserOrPermissionIfCrossUser(userHandle, - android.Manifest.permission.INTERACT_ACROSS_USERS); + private boolean hasPermissionForPreflight(CallerIdentity identity, String permission) { + final int callingPid = mInjector.binderGetCallingPid(); + final String packageName = mContext.getPackageName(); + + return PermissionChecker.checkPermissionForPreflight(mContext, permission, callingPid, + identity.getUid(), packageName) == PermissionChecker.PERMISSION_GRANTED; } - private void enforceSystemUserOrPermission(String permission) { - if (!(isCallerWithSystemUid() || mInjector.binderGetCallingUid() == Process.ROOT_UID)) { - mContext.enforceCallingOrSelfPermission(permission, - "Must be system or have " + permission + " permission"); - } + private boolean hasFullCrossUsersPermission(CallerIdentity identity, int userHandle) { + return (userHandle == identity.getUserId()) || isSystemUid(identity) || isRootUid(identity) + || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL); } - private void enforceSystemUserOrPermissionIfCrossUser(int userHandle, String permission) { - if (userHandle < 0) { - throw new IllegalArgumentException("Invalid userId " + userHandle); - } - if (userHandle == mInjector.userHandleGetCallingUserId()) { - return; - } - enforceSystemUserOrPermission(permission); + private boolean hasCrossUsersPermission(CallerIdentity identity, int userHandle) { + return (userHandle == identity.getUserId()) || isSystemUid(identity) || isRootUid(identity) + || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS); } private void enforceManagedProfile(int userId, String message) { @@ -8249,19 +8429,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { throw new SecurityException("No active admin found"); } - private void enforceProfileOwnerOrFullCrossUsersPermission(int userId) { - if (userId == mInjector.userHandleGetCallingUserId()) { + private void enforceProfileOwnerOrFullCrossUsersPermission(CallerIdentity identity, + int userId) { + if (userId == identity.getUserId()) { synchronized (getLockObject()) { if (getActiveAdminWithPolicyForUidLocked(null, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid()) - != null) { + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, identity.getUid()) != null) { // Device Owner/Profile Owner may access the user it runs on. return; } } } - // Otherwise, INTERACT_ACROSS_USERS_FULL permission, system UID or root UID is required. - enforceSystemUserOrPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userId)); } private boolean canUserUseLockTaskLocked(int userId) { @@ -8315,6 +8494,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID); } + private boolean isSystemUid(CallerIdentity identity) { + return UserHandle.isSameApp(identity.getUid(), Process.SYSTEM_UID); + } + + private boolean isRootUid(CallerIdentity identity) { + return UserHandle.isSameApp(identity.getUid(), Process.ROOT_UID); + } + + private boolean isShellUid(CallerIdentity identity) { + return UserHandle.isSameApp(identity.getUid(), Process.SHELL_UID); + } + protected int getProfileParentId(int userHandle) { return mInjector.binderWithCleanCallingIdentity(() -> { UserInfo parentUser = mUserManager.getProfileParent(userHandle); @@ -8569,7 +8760,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } Objects.requireNonNull(agent, "agent null"); - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = admin != null + ? getCallerIdentity(admin) + : getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); synchronized (getLockObject()) { final String componentName = agent.flattenToString(); @@ -8769,9 +8965,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); if (packageList != null) { - int userId = UserHandle.getCallingUserId(); + int userId = identity.getUserId(); List<AccessibilityServiceInfo> enabledServices = null; long id = mInjector.binderClearCallingIdentity(); try { @@ -8801,8 +8998,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); admin.permittedAccessiblityServices = packageList; saveSettingsLocked(UserHandle.getCallingUserId()); } @@ -8822,10 +9018,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity)); synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); return admin.permittedAccessiblityServices; } } @@ -8920,17 +9117,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } Objects.requireNonNull(who, "ComponentName is null"); - final int callingUserId = mInjector.userHandleGetCallingUserId(); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity)); + if (packageList != null) { List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get() - .getEnabledInputMethodListAsUser(callingUserId); + .getEnabledInputMethodListAsUser(identity.getUserId()); if (enabledImes != null) { List<String> enabledPackages = new ArrayList<String>(); for (InputMethodInfo ime : enabledImes) { enabledPackages.add(ime.getPackageName()); } if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList, - callingUserId)) { + identity.getUserId())) { Slog.e(LOG_TAG, "Cannot set permitted input methods, " + "because it contains already enabled input method."); return false; @@ -8939,10 +9138,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); admin.permittedInputMethods = packageList; - saveSettingsLocked(callingUserId); + saveSettingsLocked(identity.getUserId()); } final String[] packageArray = packageList != null ? ((List<String>) packageList).toArray(new String[0]) : null; @@ -8960,10 +9158,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity)); synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); return admin.permittedInputMethods; } } @@ -9037,17 +9236,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); - final int callingUserId = mInjector.userHandleGetCallingUserId(); - if (!isManagedProfile(callingUserId)) { + if (!isManagedProfile(identity.getUserId())) { return false; } synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity); admin.permittedNotificationListeners = packageList; - saveSettingsLocked(callingUserId); + saveSettingsLocked(identity.getUserId()); } return true; } @@ -9058,10 +9256,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + // API contract is to return null if there are no permitted cross-profile notification + // listeners, including in Device Owner mode. + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); return admin.permittedNotificationListeners; } } @@ -9922,10 +10122,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public String[] getAccountTypesWithManagementDisabledAsUser(int userId, boolean parent) { - enforceFullCrossUsersPermission(userId); if (!mHasFeature) { return null; } + Preconditions.checkArgumentNonnegative(userId, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userId)); + synchronized (getLockObject()) { final ArraySet<String> resultSet = new ArraySet<>(); @@ -9992,10 +10196,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final int userId = UserHandle.getCallingUserId(); synchronized (getLockObject()) { + //TODO: This is a silly access control check. Remove. if (who != null) { - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + final CallerIdentity caller = getCallerIdentity(who); + Preconditions.checkCallAuthorization( + isProfileOwner(caller) || isDeviceOwner(caller)); } - long id = mInjector.binderClearCallingIdentity(); try { return mIPackageManager.getBlockUninstallForUser(packageName, userId); @@ -10015,12 +10221,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isProfileOwner(identity)); + synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity); if (admin.disableCallerId != disabled) { admin.disableCallerId = disabled; - saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + saveSettingsLocked(identity.getUserId()); } } DevicePolicyEventLogger @@ -10036,16 +10244,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isProfileOwner(identity)); + synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity); return admin.disableCallerId; } } @Override public boolean getCrossProfileCallerIdDisabledForUser(int userId) { - enforceCrossUsersPermission(userId); + Preconditions.checkArgumentNonnegative(userId, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userId)); + synchronized (getLockObject()) { ActiveAdmin admin = getProfileOwnerAdminLocked(userId); return (admin != null) ? admin.disableCallerId : false; @@ -10058,12 +10272,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isProfileOwner(identity)); + synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity); if (admin.disableContactsSearch != disabled) { admin.disableContactsSearch = disabled; - saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + saveSettingsLocked(identity.getUserId()); } } DevicePolicyEventLogger @@ -10079,16 +10295,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isProfileOwner(identity)); + synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity); return admin.disableContactsSearch; } } @Override public boolean getCrossProfileContactsSearchDisabledForUser(int userId) { - enforceCrossUsersPermission(userId); + Preconditions.checkArgumentNonnegative(userId, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userId)); + synchronized (getLockObject()) { ActiveAdmin admin = getProfileOwnerAdminLocked(userId); return (admin != null) ? admin.disableContactsSearch : false; @@ -10159,12 +10381,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity)); + synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); if (admin.disableBluetoothContactSharing != disabled) { admin.disableBluetoothContactSharing = disabled; - saveSettingsLocked(UserHandle.getCallingUserId()); + saveSettingsLocked(identity.getUserId()); } } DevicePolicyEventLogger @@ -10180,9 +10404,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity)); + synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); return admin.disableBluetoothContactSharing; } } @@ -12138,13 +12364,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); - final int userHandle = mInjector.userHandleGetCallingUserId(); - enforceManagedProfile(userHandle, "set organization color"); + final CallerIdentity identity = getCallerIdentity(who); + enforceManagedProfile(identity.getUserId(), "set organization color"); synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); admin.organizationColor = color; - saveSettingsLocked(userHandle); + saveSettingsLocked(identity.getUserId()); } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_ORGANIZATION_COLOR) @@ -12157,7 +12382,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return; } - enforceFullCrossUsersPermission(userId); + Preconditions.checkArgumentNonnegative(userId, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userId)); + enforceManageUsers(); enforceManagedProfile(userId, "set organization color"); synchronized (getLockObject()) { @@ -12173,10 +12402,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return ActiveAdmin.DEF_ORGANIZATION_COLOR; } Objects.requireNonNull(who, "ComponentName is null"); - enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization color"); + final CallerIdentity identity = getCallerIdentity(who); + enforceManagedProfile(identity.getUserId(), "get organization color"); synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); return admin.organizationColor; } } @@ -12186,7 +12415,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return ActiveAdmin.DEF_ORGANIZATION_COLOR; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + enforceManagedProfile(userHandle, "get organization color"); synchronized (getLockObject()) { ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle); @@ -12202,15 +12435,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); - final int userHandle = mInjector.userHandleGetCallingUserId(); + final CallerIdentity identity = getCallerIdentity(who); synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); if (!TextUtils.equals(admin.organizationName, text)) { admin.organizationName = (text == null || text.length() == 0) ? null : text.toString(); - saveSettingsLocked(userHandle); + saveSettingsLocked(identity.getUserId()); } } } @@ -12221,10 +12453,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } Objects.requireNonNull(who, "ComponentName is null"); - enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization name"); + final CallerIdentity identity = getCallerIdentity(who); + enforceManagedProfile(identity.getUserId(), "get organization name"); synchronized (getLockObject()) { - ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); return admin.organizationName; } } @@ -12246,7 +12478,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return null; } - enforceFullCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle)); + enforceManagedProfile(userHandle, "get organization name"); synchronized (getLockObject()) { ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle); @@ -12260,20 +12496,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public List<String> setMeteredDataDisabledPackages(ComponentName who, List<String> packageNames) { Objects.requireNonNull(who); Objects.requireNonNull(packageNames); + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkSecurity(isDeviceOwner(identity) || isProfileOwner(identity), + String.format("Admin %s does not own the profile", identity.getComponentName())); if (!mHasFeature) { return packageNames; } synchronized (getLockObject()) { - final ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - final int callingUserId = mInjector.userHandleGetCallingUserId(); + final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); return mInjector.binderWithCleanCallingIdentity(() -> { - final List<String> excludedPkgs - = removeInvalidPkgsForMeteredDataRestriction(callingUserId, packageNames); + final List<String> excludedPkgs = removeInvalidPkgsForMeteredDataRestriction( + identity.getUserId(), packageNames); admin.meteredDisabledPackages = packageNames; - pushMeteredDisabledPackagesLocked(callingUserId); - saveSettingsLocked(callingUserId); + pushMeteredDisabledPackagesLocked(identity.getUserId()); + saveSettingsLocked(identity.getUserId()); return excludedPkgs; }); } @@ -12310,9 +12547,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return new ArrayList<>(); } + final CallerIdentity identity = getCallerIdentity(who); + Preconditions.checkSecurity(isDeviceOwner(identity) || isProfileOwner(identity), + String.format("Admin %s does not own the profile", identity.getComponentName())); + synchronized (getLockObject()) { - final ActiveAdmin admin = getActiveAdminForCallerLocked(who, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity); return admin.meteredDisabledPackages == null ? new ArrayList<>() : admin.meteredDisabledPackages; } @@ -12337,12 +12577,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } - private boolean hasMarkProfileOwnerOnOrganizationOwnedDevicePermission() { - return mContext.checkCallingPermission( - permission.MARK_DEVICE_ORGANIZATION_OWNED) - == PackageManager.PERMISSION_GRANTED; - } - @Override public void markProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId) { // As the caller is the system, it must specify the component name of the profile owner @@ -12355,7 +12589,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // Only adb or system apps with the right permission can mark a profile owner on // organization-owned device. - if (!(isAdb() || hasMarkProfileOwnerOnOrganizationOwnedDevicePermission())) { + if (!(isAdb() || hasCallingPermission(permission.MARK_DEVICE_ORGANIZATION_OWNED))) { throw new SecurityException( "Only the system can mark a profile owner of organization-owned device."); } @@ -13483,7 +13717,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public StringParceledListSlice getOwnerInstalledCaCerts(@NonNull UserHandle user) { final int userId = user.getIdentifier(); - enforceProfileOwnerOrFullCrossUsersPermission(userId); + final CallerIdentity identity = getCallerIdentity(); + enforceProfileOwnerOrFullCrossUsersPermission(identity, userId); synchronized (getLockObject()) { return new StringParceledListSlice( new ArrayList<>(getUserData(userId).mOwnerInstalledCaCerts)); @@ -14100,12 +14335,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); synchronized (getLockObject()) { - final ActiveAdmin admin = getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + final ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity); admin.mCrossProfileCalendarPackages = packageNames; - saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + saveSettingsLocked(identity.getUserId()); } DevicePolicyEventLogger .createEvent(DevicePolicyEnums.SET_CROSS_PROFILE_CALENDAR_PACKAGES) @@ -14121,10 +14356,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return Collections.emptyList(); } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); synchronized (getLockObject()) { - final ActiveAdmin admin = getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + final ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity); return admin.mCrossProfileCalendarPackages; } } @@ -14136,8 +14371,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } Preconditions.checkStringNotEmpty(packageName, "Package name is null or empty"); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userHandle)); - enforceCrossUsersPermission(userHandle); synchronized (getLockObject()) { if (mInjector.settingsSecureGetIntForUser( Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED, 0, userHandle) == 0) { @@ -14159,7 +14397,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return Collections.emptyList(); } - enforceCrossUsersPermission(userHandle); + Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); + + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userHandle)); + synchronized (getLockObject()) { final ActiveAdmin admin = getProfileOwnerAdminLocked(userHandle); if (admin != null) { @@ -14176,16 +14418,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(packageNames, "Package names is null"); + final CallerIdentity identity = getCallerIdentity(who); + final List<String> previousCrossProfilePackages; synchronized (getLockObject()) { - final ActiveAdmin admin = - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + final ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity); previousCrossProfilePackages = admin.mCrossProfilePackages; if (packageNames.equals(previousCrossProfilePackages)) { return; } admin.mCrossProfilePackages = packageNames; - saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + saveSettingsLocked(identity.getUserId()); } logSetCrossProfilePackages(who, packageNames); final CrossProfileApps crossProfileApps = mContext.getSystemService(CrossProfileApps.class); @@ -14208,10 +14451,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return Collections.emptyList(); } Objects.requireNonNull(who, "ComponentName is null"); + final CallerIdentity identity = getCallerIdentity(who); synchronized (getLockObject()) { - final ActiveAdmin admin = getActiveAdminForCallerLocked( - who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + final ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity); return admin.mCrossProfilePackages; } } @@ -14221,7 +14464,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (!mHasFeature) { return Collections.emptyList(); } - enforceAcrossUsersPermissions(); + final CallerIdentity identity = getCallerIdentity(); + Preconditions.checkCallAuthorization( + isSystemUid(identity) || isRootUid(identity) || hasCallingPermission( + permission.INTERACT_ACROSS_USERS) || hasCallingPermission( + permission.INTERACT_ACROSS_USERS_FULL) || hasPermissionForPreflight( + identity, permission.INTERACT_ACROSS_PROFILES)); synchronized (getLockObject()) { final List<ActiveAdmin> admins = getProfileOwnerAdminsForCurrentProfileGroup(); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 32afe8244eb6..e6fc792c6a9d 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -4465,6 +4465,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 19436); addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; + mServiceContext.permissions.add(permission.INTERACT_ACROSS_USERS_FULL); // Even if the caller is the managed profile, the current user is the user 0 when(getServices().iactivityManager.getCurrentUser()) @@ -5694,6 +5695,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { final long ident = mServiceContext.binder.clearCallingIdentity(); configureContextForAccess(mServiceContext, true); + mServiceContext.permissions.add(permission.MARK_DEVICE_ORGANIZATION_OWNED); mServiceContext.binder.callingUid = UserHandle.getUid(CALLER_USER_HANDLE, diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java index ce7ac9e796d2..09b6d7b0cd7e 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java @@ -259,18 +259,7 @@ public class DpmMockContext extends MockContext { @Override public int checkPermission(String permission, int pid, int uid) { - if (UserHandle.isSameApp(binder.getCallingUid(), SYSTEM_UID)) { - return PackageManager.PERMISSION_GRANTED; // Assume system has all permissions. - } - List<String> permissions = binder.callingPermissions.get(binder.getCallingUid()); - if (permissions == null) { - permissions = callerPermissions; - } - if (permissions.contains(permission)) { - return PackageManager.PERMISSION_GRANTED; - } else { - return PackageManager.PERMISSION_DENIED; - } + return checkPermission(permission); } @Override @@ -480,11 +469,32 @@ public class DpmMockContext extends MockContext { @Override public int checkCallingPermission(String permission) { - return spiedContext.checkCallingPermission(permission); + return checkPermission(permission); + } + + @Override + public int checkCallingOrSelfPermission(String permission) { + return checkPermission(permission); } @Override public void startActivityAsUser(Intent intent, UserHandle userHandle) { spiedContext.startActivityAsUser(intent, userHandle); } + + private int checkPermission(String permission) { + if (UserHandle.isSameApp(binder.getCallingUid(), SYSTEM_UID)) { + return PackageManager.PERMISSION_GRANTED; // Assume system has all permissions. + } + List<String> permissions = binder.callingPermissions.get(binder.getCallingUid()); + if (permissions == null) { + permissions = callerPermissions; + } + if (permissions.contains(permission)) { + return PackageManager.PERMISSION_GRANTED; + } else { + return PackageManager.PERMISSION_DENIED; + } + } + } diff --git a/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java b/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java index 0219f2201675..4c3674767e97 100644 --- a/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java +++ b/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java @@ -15,13 +15,15 @@ */ package com.android.server.job; -import android.util.KeyValueListParser; +import android.annotation.Nullable; +import android.provider.DeviceConfig; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.job.JobSchedulerService.MaxJobCounts; +import org.junit.After; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,19 +31,32 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class MaxJobCountsTest { + @After + public void tearDown() throws Exception { + resetConfig(); + } + + private void resetConfig() { + // DeviceConfig.resetToDefaults() doesn't work here. Need to reset constants manually. + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, "total", "", false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, "maxbg", "", false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, "minbg", "", false); + } - private void check(String config, + private void check(@Nullable DeviceConfig.Properties config, int defaultTotal, int defaultMaxBg, int defaultMinBg, - int expectedTotal, int expectedMaxBg, int expectedMinBg) { - final KeyValueListParser parser = new KeyValueListParser(','); - parser.setString(config); + int expectedTotal, int expectedMaxBg, int expectedMinBg) throws Exception { + resetConfig(); + if (config != null) { + DeviceConfig.setProperties(config); + } final MaxJobCounts counts = new JobSchedulerService.MaxJobCounts( defaultTotal, "total", defaultMaxBg, "maxbg", defaultMinBg, "minbg"); - counts.parse(parser); + counts.update(); Assert.assertEquals(expectedTotal, counts.getMaxTotal()); Assert.assertEquals(expectedMaxBg, counts.getMaxBg()); @@ -49,24 +64,35 @@ public class MaxJobCountsTest { } @Test - public void test() { + public void test() throws Exception { // Tests with various combinations. - check("", /*default*/ 5, 1, 0, /*expected*/ 5, 1, 0); - check("", /*default*/ 5, 0, 0, /*expected*/ 5, 1, 0); - check("", /*default*/ 0, 0, 0, /*expected*/ 1, 1, 0); - check("", /*default*/ -1, -1, -1, /*expected*/ 1, 1, 0); - check("", /*default*/ 5, 5, 5, /*expected*/ 5, 5, 4); - check("", /*default*/ 6, 5, 6, /*expected*/ 6, 5, 5); - check("", /*default*/ 4, 5, 6, /*expected*/ 4, 4, 3); - check("", /*default*/ 5, 1, 1, /*expected*/ 5, 1, 1); - check("", /*default*/ 15, 15, 15, /*expected*/ 15, 15, 14); - check("", /*default*/ 16, 16, 16, /*expected*/ 16, 16, 15); - check("", /*default*/ 20, 20, 20, /*expected*/ 16, 16, 15); + check(null, /*default*/ 5, 1, 0, /*expected*/ 5, 1, 0); + check(null, /*default*/ 5, 0, 0, /*expected*/ 5, 1, 0); + check(null, /*default*/ 0, 0, 0, /*expected*/ 1, 1, 0); + check(null, /*default*/ -1, -1, -1, /*expected*/ 1, 1, 0); + check(null, /*default*/ 5, 5, 5, /*expected*/ 5, 5, 4); + check(null, /*default*/ 6, 5, 6, /*expected*/ 6, 5, 5); + check(null, /*default*/ 4, 5, 6, /*expected*/ 4, 4, 3); + check(null, /*default*/ 5, 1, 1, /*expected*/ 5, 1, 1); + check(null, /*default*/ 15, 15, 15, /*expected*/ 15, 15, 14); + check(null, /*default*/ 16, 16, 16, /*expected*/ 16, 16, 15); + check(null, /*default*/ 20, 20, 20, /*expected*/ 16, 16, 15); // Test for overriding with a setting string. - check("total=5,maxbg=4,minbg=3", /*default*/ 9, 9, 9, /*expected*/ 5, 4, 3); - check("total=5", /*default*/ 9, 9, 9, /*expected*/ 5, 5, 4); - check("maxbg=4", /*default*/ 9, 9, 9, /*expected*/ 9, 4, 4); - check("minbg=3", /*default*/ 9, 9, 9, /*expected*/ 9, 9, 3); + check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER) + .setInt("total", 5) + .setInt("maxbg", 4) + .setInt("minbg", 3) + .build(), + /*default*/ 9, 9, 9, /*expected*/ 5, 4, 3); + check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER) + .setInt("total", 5).build(), + /*default*/ 9, 9, 9, /*expected*/ 5, 5, 4); + check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER) + .setInt("maxbg", 4).build(), + /*default*/ 9, 9, 9, /*expected*/ 9, 4, 4); + check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER) + .setInt("minbg", 3).build(), + /*default*/ 9, 9, 9, /*expected*/ 9, 9, 3); } } diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index 06c34dcf290a..905f90800305 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -50,6 +50,18 @@ public final class CellIdentityNr extends CellIdentity { // a list of additional PLMN-IDs reported for this cell private final ArraySet<String> mAdditionalPlmns; + /** @hide */ + public CellIdentityNr() { + super(TAG, CellInfo.TYPE_NR, null, null, null, null); + mNrArfcn = CellInfo.UNAVAILABLE; + mPci = CellInfo.UNAVAILABLE; + mTac = CellInfo.UNAVAILABLE; + mNci = CellInfo.UNAVAILABLE; + mBands = new int[] {}; + mAdditionalPlmns = new ArraySet(); + mGlobalCellId = null; + } + /** * * @param pci Physical Cell Id in range [0, 1007]. diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java index a7e79f93ae89..e01e8f0d5b51 100644 --- a/telephony/java/android/telephony/CellInfoNr.java +++ b/telephony/java/android/telephony/CellInfoNr.java @@ -29,9 +29,16 @@ import java.util.Objects; public final class CellInfoNr extends CellInfo { private static final String TAG = "CellInfoNr"; - private final CellIdentityNr mCellIdentity; + private CellIdentityNr mCellIdentity; private final CellSignalStrengthNr mCellSignalStrength; + /** @hide */ + public CellInfoNr() { + super(); + mCellIdentity = new CellIdentityNr(); + mCellSignalStrength = new CellSignalStrengthNr(); + } + private CellInfoNr(Parcel in) { super(in); mCellIdentity = CellIdentityNr.CREATOR.createFromParcel(in); @@ -71,6 +78,11 @@ public final class CellInfoNr extends CellInfo { return mCellIdentity; } + /** @hide */ + public void setCellIdentity(CellIdentityNr cid) { + mCellIdentity = cid; + } + /** * @return a {@link CellSignalStrengthNr} instance. */ |