diff options
105 files changed, 1129 insertions, 1194 deletions
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 549badd5ba82..b4238c975d98 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java @@ -16,7 +16,6 @@ package com.android.server.job; -import static com.android.server.job.JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX; import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock; @@ -82,6 +81,11 @@ class JobConcurrencyManager { private static final String TAG = JobSchedulerService.TAG + ".Concurrency"; private static final boolean DEBUG = JobSchedulerService.DEBUG; + /** The maximum number of concurrent jobs we'll aim to run at one time. */ + public static final int STANDARD_CONCURRENCY_LIMIT = 16; + /** The maximum number of objects we should retain in memory when not in use. */ + private static final int MAX_RETAINED_OBJECTS = (int) (1.5 * STANDARD_CONCURRENCY_LIMIT); + static final String CONFIG_KEY_PREFIX_CONCURRENCY = "concurrency_"; private static final String KEY_SCREEN_OFF_ADJUSTMENT_DELAY_MS = CONFIG_KEY_PREFIX_CONCURRENCY + "screen_off_adjustment_delay_ms"; @@ -93,7 +97,7 @@ class JobConcurrencyManager { @VisibleForTesting static final String KEY_PKG_CONCURRENCY_LIMIT_REGULAR = CONFIG_KEY_PREFIX_CONCURRENCY + "pkg_concurrency_limit_regular"; - private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = MAX_JOB_CONTEXTS_COUNT / 2; + private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = STANDARD_CONCURRENCY_LIMIT / 2; /** * Set of possible execution types that a job can have. The actual type(s) of a job are based @@ -309,7 +313,7 @@ class JobConcurrencyManager { private final ArrayList<ContextAssignment> mRecycledStoppable = new ArrayList<>(); private final Pools.Pool<ContextAssignment> mContextAssignmentPool = - new Pools.SimplePool<>(MAX_JOB_CONTEXTS_COUNT); + new Pools.SimplePool<>(MAX_RETAINED_OBJECTS); /** * Set of JobServiceContexts that are actively running jobs. @@ -317,14 +321,16 @@ class JobConcurrencyManager { final List<JobServiceContext> mActiveServices = new ArrayList<>(); /** Set of JobServiceContexts that aren't currently running any jobs. */ - final ArraySet<JobServiceContext> mIdleContexts = new ArraySet<>(); + private final ArraySet<JobServiceContext> mIdleContexts = new ArraySet<>(); + + private int mNumDroppedContexts = 0; private final ArraySet<JobStatus> mRunningJobs = new ArraySet<>(); private final WorkCountTracker mWorkCountTracker = new WorkCountTracker(); private final Pools.Pool<PackageStats> mPkgStatsPool = - new Pools.SimplePool<>(MAX_JOB_CONTEXTS_COUNT); + new Pools.SimplePool<>(MAX_RETAINED_OBJECTS); private final SparseArrayMap<String, PackageStats> mActivePkgStats = new SparseArrayMap<>(); @@ -406,7 +412,7 @@ class JobConcurrencyManager { void onThirdPartyAppsCanStart() { final IBatteryStats batteryStats = IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); - for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) { + for (int i = 0; i < STANDARD_CONCURRENCY_LIMIT; i++) { mIdleContexts.add( new JobServiceContext(mService, this, batteryStats, mService.mJobPackageTracker, mContext.getMainLooper())); @@ -655,13 +661,13 @@ class JobConcurrencyManager { } preferredUidOnly.sort(sDeterminationComparator); stoppable.sort(sDeterminationComparator); - for (int i = numRunningJobs; i < MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = numRunningJobs; i < STANDARD_CONCURRENCY_LIMIT; ++i) { final JobServiceContext jsc; final int numIdleContexts = mIdleContexts.size(); if (numIdleContexts > 0) { jsc = mIdleContexts.removeAt(numIdleContexts - 1); } else { - Slog.wtf(TAG, "Had fewer than " + MAX_JOB_CONTEXTS_COUNT + " in existence"); + Slog.wtf(TAG, "Had fewer than " + STANDARD_CONCURRENCY_LIMIT + " in existence"); jsc = createNewJobServiceContext(); } @@ -681,6 +687,7 @@ class JobConcurrencyManager { JobStatus nextPending; pendingJobQueue.resetIterator(); + int projectedRunningCount = numRunningJobs; while ((nextPending = pendingJobQueue.next()) != null) { if (mRunningJobs.contains(nextPending)) { continue; @@ -694,6 +701,9 @@ class JobConcurrencyManager { ContextAssignment selectedContext = null; final int allWorkTypes = getJobWorkTypes(nextPending); final boolean pkgConcurrencyOkay = !isPkgConcurrencyLimitedLocked(nextPending); + final boolean isTopEj = nextPending.shouldTreatAsExpeditedJob() + && nextPending.lastEvaluatedBias == JobInfo.BIAS_TOP_APP; + final boolean isInOverage = projectedRunningCount > STANDARD_CONCURRENCY_LIMIT; boolean startingJob = false; if (idle.size() > 0) { final int idx = idle.size() - 1; @@ -711,14 +721,36 @@ class JobConcurrencyManager { assignment.newWorkType = workType; } } - if (selectedContext == null) { + if (selectedContext == null && stoppable.size() > 0) { + int topEjCount = 0; + for (int r = mRunningJobs.size() - 1; r >= 0; --r) { + JobStatus js = mRunningJobs.valueAt(r); + if (js.startedAsExpeditedJob && js.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) { + topEjCount++; + } + } for (int s = stoppable.size() - 1; s >= 0; --s) { final ContextAssignment assignment = stoppable.get(s); final JobStatus runningJob = assignment.context.getRunningJobLocked(); - // Maybe stop the job if it has had its day in the sun. Don't let a different - // app preempt jobs started for TOP apps though. - if (runningJob.lastEvaluatedBias < JobInfo.BIAS_TOP_APP - && assignment.shouldStopJobReason != null) { + // Maybe stop the job if it has had its day in the sun. Only allow replacing + // for one of the following conditions: + // 1. We're putting in the current TOP app's EJ + // 2. There aren't too many jobs running AND the current job started when the + // app was in the background + // 3. There aren't too many jobs running AND the current job started when the + // app was on TOP, but the app has since left TOP + // 4. There aren't too many jobs running AND the current job started when the + // app was on TOP, the app is still TOP, but there are too many TOP+EJs + // running (because we don't want them to starve out other apps and the + // current job has already run for the minimum guaranteed time). + boolean canReplace = isTopEj; // Case 1 + if (!canReplace && !isInOverage) { + final int currentJobBias = mService.evaluateJobBiasLocked(runningJob); + canReplace = runningJob.lastEvaluatedBias < JobInfo.BIAS_TOP_APP // Case 2 + || currentJobBias < JobInfo.BIAS_TOP_APP // Case 3 + || topEjCount > .5 * mWorkTypeConfig.getMaxTotal(); // Case 4 + } + if (canReplace) { int replaceWorkType = mWorkCountTracker.canJobStart(allWorkTypes, assignment.context.getRunningJobWorkType()); if (replaceWorkType != WORK_TYPE_NONE) { @@ -736,7 +768,7 @@ class JobConcurrencyManager { } } } - if (selectedContext == null) { + if (selectedContext == null && (!isInOverage || isTopEj)) { int lowestBiasSeen = Integer.MAX_VALUE; for (int p = preferredUidOnly.size() - 1; p >= 0; --p) { final ContextAssignment assignment = preferredUidOnly.get(p); @@ -765,10 +797,43 @@ class JobConcurrencyManager { preferredUidOnly.remove(selectedContext); } } + // Make sure to run EJs for the TOP app immediately. + if (isTopEj) { + if (selectedContext != null + && selectedContext.context.getRunningJobLocked() != null) { + // We're "replacing" a currently running job, but we want TOP EJs to start + // immediately, so we'll start the EJ on a fresh available context and + // stop this currently running job to replace in two steps. + changed.add(selectedContext); + projectedRunningCount--; + selectedContext.newJob = null; + selectedContext.newWorkType = WORK_TYPE_NONE; + selectedContext = null; + } + if (selectedContext == null) { + selectedContext = mContextAssignmentPool.acquire(); + if (selectedContext == null) { + selectedContext = new ContextAssignment(); + } + selectedContext.context = mIdleContexts.size() > 0 + ? mIdleContexts.removeAt(mIdleContexts.size() - 1) + : createNewJobServiceContext(); + selectedContext.newJob = nextPending; + final int workType = mWorkCountTracker.canJobStart(allWorkTypes); + selectedContext.newWorkType = + (workType != WORK_TYPE_NONE) ? workType : WORK_TYPE_TOP; + } + } final PackageStats packageStats = getPkgStatsLocked( nextPending.getSourceUserId(), nextPending.getSourcePackageName()); if (selectedContext != null) { changed.add(selectedContext); + if (selectedContext.context.getRunningJobLocked() != null) { + projectedRunningCount--; + } + if (selectedContext.newJob != null) { + projectedRunningCount++; + } packageStats.adjustStagedCount(true, nextPending.shouldTreatAsExpeditedJob()); } if (startingJob) { @@ -793,7 +858,7 @@ class JobConcurrencyManager { if (DEBUG) { Slog.d(TAG, "preempting job: " + js); } - // preferredUid will be set to uid of currently running job. + // preferredUid will be set to uid of currently running job, if appropriate. assignment.context.cancelExecutingJobLocked( assignment.preemptReasonCode, JobParameters.INTERNAL_STOP_REASON_PREEMPT, assignment.preemptReason); @@ -811,9 +876,6 @@ class JobConcurrencyManager { } for (int s = stoppable.size() - 1; s >= 0; --s) { final ContextAssignment assignment = stoppable.get(s); - // The preferred UID is set when we cancel with PREEMPT reason, but don't preserve the - // UID for any stoppable contexts since we want to open the context up to any/all apps. - assignment.context.clearPreferredUid(); assignment.clear(); mContextAssignmentPool.release(assignment); } @@ -838,6 +900,21 @@ class JobConcurrencyManager { } @GuardedBy("mLock") + void onUidBiasChangedLocked(int prevBias, int newBias) { + if (prevBias != JobInfo.BIAS_TOP_APP && newBias != JobInfo.BIAS_TOP_APP) { + // TOP app didn't change. Nothing to do. + return; + } + if (mService.getPendingJobQueue().size() == 0) { + // Nothing waiting for the top app to leave. Nothing to do. + return; + } + // Don't stop the TOP jobs directly. Instead, see if they would be replaced by some + // pending job (there may not always be something to replace them). + assignJobsToContextsLocked(); + } + + @GuardedBy("mLock") boolean stopJobOnServiceContextLocked(JobStatus job, @JobParameters.StopReason int reason, int internalReasonCode, String debugReason) { if (!mRunningJobs.contains(job)) { @@ -1041,7 +1118,13 @@ class JobConcurrencyManager { mWorkCountTracker.onJobFinished(workType); mRunningJobs.remove(jobStatus); mActiveServices.remove(worker); - mIdleContexts.add(worker); + if (mIdleContexts.size() < MAX_RETAINED_OBJECTS) { + // Don't need to save all new contexts, but keep some extra around in case we need + // extras for another TOP+EJ overage. + mIdleContexts.add(worker); + } else { + mNumDroppedContexts++; + } final PackageStats packageStats = mActivePkgStats.get(jobStatus.getSourceUserId(), jobStatus.getSourcePackageName()); if (packageStats == null) { @@ -1054,6 +1137,14 @@ class JobConcurrencyManager { } } + if (mActiveServices.size() >= STANDARD_CONCURRENCY_LIMIT) { + worker.clearPreferredUid(); + // We're over the limit (because the TOP app scheduled a lot of EJs). Don't start + // running anything new until we get back below the limit. + noteConcurrency(); + return; + } + final PendingJobQueue pendingJobQueue = mService.getPendingJobQueue(); if (worker.getPreferredUid() != JobServiceContext.NO_PREFERRED_UID) { updateCounterConfigLocked(); @@ -1245,6 +1336,18 @@ class JobConcurrencyManager { } } else if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_EJ) > 0) { return "blocking " + workTypeToString(WORK_TYPE_EJ) + " queue"; + } else if (js.startedAsExpeditedJob && js.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) { + // Try not to let TOP + EJ starve out other apps. + int topEjCount = 0; + for (int r = mRunningJobs.size() - 1; r >= 0; --r) { + JobStatus j = mRunningJobs.valueAt(r); + if (j.startedAsExpeditedJob && j.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) { + topEjCount++; + } + } + if (topEjCount > .5 * mWorkTypeConfig.getMaxTotal()) { + return "prevent top EJ dominance"; + } } // No other pending EJs. Return null so we don't let regular jobs preempt an EJ. return null; @@ -1361,10 +1464,10 @@ class JobConcurrencyManager { CONFIG_LIMITS_SCREEN_OFF.low.update(properties); CONFIG_LIMITS_SCREEN_OFF.critical.update(properties); - // Package concurrency limits must in the range [1, MAX_JOB_CONTEXTS_COUNT]. - mPkgConcurrencyLimitEj = Math.max(1, Math.min(MAX_JOB_CONTEXTS_COUNT, + // Package concurrency limits must in the range [1, STANDARD_CONCURRENCY_LIMIT]. + mPkgConcurrencyLimitEj = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT, properties.getInt(KEY_PKG_CONCURRENCY_LIMIT_EJ, DEFAULT_PKG_CONCURRENCY_LIMIT_EJ))); - mPkgConcurrencyLimitRegular = Math.max(1, Math.min(MAX_JOB_CONTEXTS_COUNT, + mPkgConcurrencyLimitRegular = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT, properties.getInt( KEY_PKG_CONCURRENCY_LIMIT_REGULAR, DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR))); } @@ -1492,6 +1595,13 @@ class JobConcurrencyManager { jsc.dumpLocked(pw, nowElapsed); } pw.decreaseIndent(); + + if (mNumDroppedContexts > 0) { + pw.println(); + pw.print("Dropped "); + pw.print(mNumDroppedContexts); + pw.println(" contexts"); + } } public void dumpProtoLocked(ProtoOutputStream proto, long tag, long now, long nowRealtime) { @@ -1600,7 +1710,7 @@ class JobConcurrencyManager { WorkTypeConfig(@NonNull String configIdentifier, int defaultMaxTotal, List<Pair<Integer, Integer>> defaultMin, List<Pair<Integer, Integer>> defaultMax) { mConfigIdentifier = configIdentifier; - mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, MAX_JOB_CONTEXTS_COUNT); + mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, STANDARD_CONCURRENCY_LIMIT); int numReserved = 0; for (int i = defaultMin.size() - 1; i >= 0; --i) { mDefaultMinReservedSlots.put(defaultMin.get(i).first, defaultMin.get(i).second); @@ -1621,8 +1731,8 @@ class JobConcurrencyManager { } void update(@NonNull DeviceConfig.Properties properties) { - // Ensure total in the range [1, MAX_JOB_CONTEXTS_COUNT]. - mMaxTotal = Math.max(1, Math.min(MAX_JOB_CONTEXTS_COUNT, + // Ensure total in the range [1, STANDARD_CONCURRENCY_LIMIT]. + mMaxTotal = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT, properties.getInt(KEY_PREFIX_MAX_TOTAL + mConfigIdentifier, mDefaultMaxTotal))); mMaxAllowedSlots.clear(); 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 fd7d8aa75882..b25832c7d521 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -159,8 +159,6 @@ public class JobSchedulerService extends com.android.server.SystemService public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); public static final boolean DEBUG_STANDBY = DEBUG || false; - /** The maximum number of concurrent jobs we run at one time. */ - static final int MAX_JOB_CONTEXTS_COUNT = 16; /** The maximum number of jobs that we allow an app to schedule */ private static final int MAX_JOBS_PER_APP = 150; /** The number of the most recently completed jobs to keep track of for debugging purposes. */ @@ -1423,6 +1421,7 @@ public class JobSchedulerService extends com.android.server.SystemService for (int c = 0; c < mControllers.size(); ++c) { mControllers.get(c).onUidBiasChangedLocked(uid, prevBias, newBias); } + mConcurrencyManager.onUidBiasChangedLocked(prevBias, newBias); } } } diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java index 54e0a4c6663c..2a79ec4587fc 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java @@ -751,7 +751,8 @@ public final class JobServiceContext implements ServiceConnection { } } mParams.setStopReason(stopReasonCode, internalStopReasonCode, debugReason); - if (internalStopReasonCode == JobParameters.INTERNAL_STOP_REASON_PREEMPT) { + if (stopReasonCode == JobParameters.STOP_REASON_PREEMPT) { + // Only preserve the UID when we're preempting the job for another one of the same UID. mPreferredUid = mRunningJob != null ? mRunningJob.getUid() : NO_PREFERRED_UID; } handleCancelLocked(debugReason); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java index b3e81cb89e52..fdcd2fc82ecc 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java @@ -297,9 +297,9 @@ public final class QuotaController extends StateController { private final SparseBooleanArray mForegroundUids = new SparseBooleanArray(); /** - * List of jobs that started while the UID was in the TOP state. There will be no more than - * 16 ({@link JobSchedulerService#MAX_JOB_CONTEXTS_COUNT}) running at once, so an ArraySet is - * fine. + * List of jobs that started while the UID was in the TOP state. There will usually be no more + * than {@value JobConcurrencyManager#MAX_STANDARD_JOB_CONCURRENCY} running at once, so an + * ArraySet is fine. */ private final ArraySet<JobStatus> mTopStartedJobs = new ArraySet<>(); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java index fd6aa7a1d282..223091a27ee1 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java @@ -289,9 +289,9 @@ public class TareController extends StateController { }; /** - * List of jobs that started while the UID was in the TOP state. There will be no more than - * 16 ({@link JobSchedulerService#MAX_JOB_CONTEXTS_COUNT}) running at once, so an ArraySet is - * fine. + * List of jobs that started while the UID was in the TOP state. There will usually be no more + * than {@value JobConcurrencyManager#MAX_STANDARD_JOB_CONCURRENCY} running at once, so an + * ArraySet is fine. */ @GuardedBy("mLock") private final ArraySet<JobStatus> mTopStartedJobs = new ArraySet<>(); diff --git a/core/api/current.txt b/core/api/current.txt index 92c263624527..c33ee6563a97 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -9225,6 +9225,7 @@ package android.content { field public static final int CLASSIFICATION_NOT_COMPLETE = 1; // 0x1 field public static final int CLASSIFICATION_NOT_PERFORMED = 2; // 0x2 field @NonNull public static final android.os.Parcelable.Creator<android.content.ClipDescription> CREATOR; + field public static final String EXTRA_IS_SENSITIVE = "android.content.extra.IS_SENSITIVE"; field public static final String MIMETYPE_TEXT_HTML = "text/html"; field public static final String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent"; field public static final String MIMETYPE_TEXT_PLAIN = "text/plain"; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 381314e36e66..df5dcda6eb42 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -3262,10 +3262,6 @@ package android.window { field public static final int FEATURE_WINDOW_TOKENS = 2; // 0x2 } - public interface OnBackInvokedDispatcher { - field public static final long DISPATCH_BACK_INVOCATION_AHEAD_OF_TIME = 195946584L; // 0xbade858L - } - public final class SplashScreenView extends android.widget.FrameLayout { method @Nullable public android.view.View getBrandingView(); } diff --git a/core/java/android/accessibilityservice/MagnificationConfig.java b/core/java/android/accessibilityservice/MagnificationConfig.java index 74c91d6097c3..ddafb224a5cd 100644 --- a/core/java/android/accessibilityservice/MagnificationConfig.java +++ b/core/java/android/accessibilityservice/MagnificationConfig.java @@ -42,9 +42,9 @@ import java.lang.annotation.RetentionPolicy; * </p> * * <p> - * When the magnification config uses {@link #MAGNIFICATION_MODE_WINDOW}. - * {@link AccessibilityService} will be able to control the activated window magnifier - * on the display. + * When the magnification config uses {@link #MAGNIFICATION_MODE_WINDOW} and the platform + * supports {@link android.content.pm.PackageManager#FEATURE_WINDOW_MAGNIFICATION} feature. + * {@link AccessibilityService} will be able to control window magnifier on the display. * </p> * * <p> @@ -57,9 +57,12 @@ public final class MagnificationConfig implements Parcelable { /** The controlling magnification mode. It controls the activated magnifier. */ public static final int MAGNIFICATION_MODE_DEFAULT = 0; - /** The controlling magnification mode. It controls fullscreen magnifier. */ + /** The controlling magnification mode. It controls full-screen magnifier. */ public static final int MAGNIFICATION_MODE_FULLSCREEN = 1; - /** The controlling magnification mode. It controls window magnifier. */ + /** + * The controlling magnification mode. It is valid if the platform supports + * {@link android.content.pm.PackageManager#FEATURE_WINDOW_MAGNIFICATION} feature. + */ public static final int MAGNIFICATION_MODE_WINDOW = 2; /** @hide */ diff --git a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl index 3b15bcb9846d..0d9ecfdfe8f6 100644 --- a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl +++ b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl @@ -25,7 +25,7 @@ import android.os.RemoteCallback; * * @hide */ -oneway interface IAmbientContextManager { +interface IAmbientContextManager { void registerObserver(in AmbientContextEventRequest request, in PendingIntent resultPendingIntent, in RemoteCallback statusCallback); @@ -33,4 +33,4 @@ oneway interface IAmbientContextManager { void queryServiceStatus(in int[] eventTypes, in String callingPackage, in RemoteCallback statusCallback); void startConsentActivity(in int[] eventTypes, in String callingPackage); -}
\ No newline at end of file +} diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java index 2ecd71bc1f06..bf466116009b 100644 --- a/core/java/android/content/ClipDescription.java +++ b/core/java/android/content/ClipDescription.java @@ -134,6 +134,26 @@ public class ClipDescription implements Parcelable { public static final String EXTRA_LOGGING_INSTANCE_ID = "android.intent.extra.LOGGING_INSTANCE_ID"; + /** + * Indicates that a ClipData contains potentially sensitive information, such as a + * password or credit card number. + * <p> + * Type: boolean + * </p> + * <p> + * This extra can be used to indicate that a ClipData contains sensitive information that + * should be redacted or hidden from view until a user takes explicit action to reveal it + * (e.g., by pasting). + * </p> + * <p> + * Adding this extra does not change clipboard behavior or add additional security to + * the ClipData. Its purpose is essentially a rendering hint from the source application, + * asking that the data within be obfuscated or redacted, unless the user has taken action + * to make it visible. + * </p> + */ + public static final String EXTRA_IS_SENSITIVE = "android.content.extra.IS_SENSITIVE"; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 227ac1a02890..a90f6d625c51 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4188,6 +4188,8 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device * supports window magnification. + * + * @see android.accessibilityservice.MagnificationConfig#MAGNIFICATION_MODE_WINDOW */ @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_WINDOW_MAGNIFICATION = diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 7dc4f22000b8..9591e4125ee7 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -8093,14 +8093,17 @@ public final class ViewRootImpl implements ViewParent, private void setFrame(Rect frame) { mWinFrame.set(frame); + final WindowConfiguration winConfig = getConfiguration().windowConfiguration; + mPendingBackDropFrame.set(mPendingDragResizing && !winConfig.useWindowFrameForBackdrop() + ? winConfig.getMaxBounds() + : frame); // Surface position is now inherited from parent, and BackdropFrameRenderer uses backdrop // frame to position content. Thus, we just keep the size of backdrop frame, and remove the // offset to avoid double offset from display origin. - mPendingBackDropFrame.set(frame); mPendingBackDropFrame.offsetTo(0, 0); mInsetsController.onFrameChanged(mOverrideInsetsFrame != null ? - mOverrideInsetsFrame : frame); + mOverrideInsetsFrame : frame); } /** diff --git a/core/java/android/window/OnBackInvokedDispatcher.java b/core/java/android/window/OnBackInvokedDispatcher.java index 5eed8cde8c7c..c254a9df3b4c 100644 --- a/core/java/android/window/OnBackInvokedDispatcher.java +++ b/core/java/android/window/OnBackInvokedDispatcher.java @@ -21,9 +21,6 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; -import android.annotation.TestApi; -import android.compat.annotation.ChangeId; -import android.compat.annotation.EnabledSince; import android.os.Build; import java.lang.annotation.Retention; @@ -38,23 +35,6 @@ import java.lang.annotation.RetentionPolicy; * target (a.k.a. the callback to be invoked next), or its behavior. */ public interface OnBackInvokedDispatcher { - /** - * Enables dispatching the "back" action via {@link OnBackInvokedDispatcher}. - * - * When enabled, the following APIs are no longer invoked: - * <ul> - * <li> {@link android.app.Activity#onBackPressed} - * <li> {@link android.app.Dialog#onBackPressed} - * <li> {@link android.view.KeyEvent#KEYCODE_BACK} is no longer dispatched. - * </ul> - * - * @hide - */ - @TestApi - @ChangeId - @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) - long DISPATCH_BACK_INVOCATION_AHEAD_OF_TIME = 195946584L; - /** @hide */ String TAG = "OnBackInvokedDispatcher"; diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index e0bee96002b8..8811116b25ad 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -18,7 +18,6 @@ package android.window; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.compat.CompatChanges; import android.content.Context; import android.os.Debug; import android.os.Handler; @@ -253,21 +252,20 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { * {@link OnBackInvokedCallback}. */ public static boolean isOnBackInvokedCallbackEnabled(@Nullable Context context) { - // new back is enabled if the app targets T AND the feature flag is enabled AND the app - // does not explicitly request legacy back. - boolean targetsT = CompatChanges.isChangeEnabled(DISPATCH_BACK_INVOCATION_AHEAD_OF_TIME); + // new back is enabled if the feature flag is enabled AND the app does not explicitly + // request legacy back. boolean featureFlagEnabled = IS_BACK_PREDICTABILITY_ENABLED; // If the context is null, we assume true and fallback on the two other conditions. - boolean appRequestsLegacy = - context == null || !context.getApplicationInfo().isOnBackInvokedCallbackEnabled(); + boolean appRequestsPredictiveBack = + context != null && context.getApplicationInfo().isOnBackInvokedCallbackEnabled(); if (DEBUG) { - Log.d(TAG, TextUtils.formatSimple("App: %s isChangeEnabled=%s featureFlagEnabled=%s " - + "onBackInvokedEnabled=%s", + Log.d(TAG, TextUtils.formatSimple("App: %s featureFlagEnabled=%s " + + "appRequestsPredictiveBack=%s", context != null ? context.getApplicationInfo().packageName : "null context", - targetsT, featureFlagEnabled, !appRequestsLegacy)); + featureFlagEnabled, appRequestsPredictiveBack)); } - return targetsT && featureFlagEnabled && !appRequestsLegacy; + return featureFlagEnabled && appRequestsPredictiveBack; } } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index a316669aa516..88089b5b85f2 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -1158,9 +1158,7 @@ public class ChooserActivity extends ResolverActivity implements -1); // Action bar is user-independent, always start as primary safelyStartActivityAsUser(ti, getPersonalProfileUserHandle()); - if (!mAwaitingDelegateResponse) { - finish(); - } + finish(); } ); b.setId(R.id.chooser_nearby_button); @@ -1182,9 +1180,7 @@ public class ChooserActivity extends ResolverActivity implements -1); // Action bar is user-independent, always start as primary safelyStartActivityAsUser(ti, getPersonalProfileUserHandle()); - if (!mAwaitingDelegateResponse) { - finish(); - } + finish(); } ); b.setId(R.id.chooser_edit_button); @@ -2231,9 +2227,7 @@ public class ChooserActivity extends ResolverActivity implements TargetInfo clonedTarget = selectedTarget.cloneFilledIn(matchingIntent, 0); if (super.onTargetSelected(clonedTarget, false)) { updateModelAndChooserCounts(clonedTarget); - if (!mAwaitingDelegateResponse) { - finish(); - } + finish(); return; } } diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 1815ca69a55c..ec1307908af0 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -210,7 +210,7 @@ public class ResolverActivity extends Activity implements private UserHandle mWorkProfileUserHandle; - protected boolean mAwaitingDelegateResponse; + /** * Get the string resource to be used as a label for the link to the resolver activity for an @@ -682,9 +682,7 @@ public class ResolverActivity extends Activity implements mProfileSwitchMessage = null; onTargetSelected(dri, false); - if (!mAwaitingDelegateResponse) { - finish(); - } + finish(); } /** @@ -974,7 +972,7 @@ public class ResolverActivity extends Activity implements } final Intent intent = getIntent(); if ((intent.getFlags() & FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction() - && !mResolvingHome && !mRetainInOnStop && !mAwaitingDelegateResponse) { + && !mResolvingHome && !mRetainInOnStop) { // This resolver is in the unusual situation where it has been // launched at the top of a new task. We don't let it be added // to the recent tasks shown to the user, and we need to make sure @@ -1143,9 +1141,7 @@ public class ResolverActivity extends Activity implements mMultiProfilePagerAdapter.getActiveListAdapter().hasFilteredItem() ? MetricsProto.MetricsEvent.ACTION_HIDE_APP_DISAMBIG_APP_FEATURED : MetricsProto.MetricsEvent.ACTION_HIDE_APP_DISAMBIG_NONE_FEATURED); - if (!mAwaitingDelegateResponse) { - finish(); - } + finish(); } } @@ -2365,9 +2361,7 @@ public class ResolverActivity extends Activity implements .getItem(selections[0].getIndex()); if (ra.onTargetSelected(ti, false)) { ra.mPickOptionRequest = null; - if (!ra.mAwaitingDelegateResponse) { - ra.finish(); - } + ra.finish(); } } } diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index 0ada13a73ad2..f19bfc669997 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -514,9 +514,10 @@ public final class SystemUiDeviceConfigFlags { "is_nearby_share_first_target_in_ranked_app"; /** - * (boolean) Whether to enable the new unbundled "delegate chooser" implementation. + * (boolean) Whether to enable the new unbundled sharesheet + * (com.android.intentresolver.ChooserActivity). */ - public static final String USE_DELEGATE_CHOOSER = "use_delegate_chooser"; + public static final String USE_UNBUNDLED_SHARESHEET = "use_unbundled_sharesheet"; /** * (string) Name of the default QR code scanner activity. On the eligible devices this activity diff --git a/core/java/com/android/internal/widget/CachingIconView.java b/core/java/com/android/internal/widget/CachingIconView.java index d1156979ee07..8ddd4ffd3065 100644 --- a/core/java/com/android/internal/widget/CachingIconView.java +++ b/core/java/com/android/internal/widget/CachingIconView.java @@ -122,7 +122,10 @@ public class CachingIconView extends ImageView { public Runnable setImageIconAsync(@Nullable final Icon icon) { resetCache(); Drawable drawable = loadSizeRestrictedIcon(icon); - return () -> setImageDrawable(drawable); + if (drawable != null) { + return () -> setImageDrawable(drawable); + } + return super.setImageIconAsync(icon); } @Override diff --git a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java index fb0880ce3521..bbaf0862f923 100644 --- a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java +++ b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java @@ -19,7 +19,10 @@ package android.security.identity; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.os.RemoteException; import android.os.ServiceManager; +import android.security.GenerateRkpKey; +import android.security.keymaster.KeymasterDefs; class CredstoreIdentityCredentialStore extends IdentityCredentialStore { @@ -104,6 +107,16 @@ class CredstoreIdentityCredentialStore extends IdentityCredentialStore { try { IWritableCredential wc; wc = mStore.createCredential(credentialName, docType); + try { + GenerateRkpKey keyGen = new GenerateRkpKey(mContext); + // We don't know what the security level is for the backing keymint, so go ahead and + // poke the provisioner for both TEE and SB. + keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT); + keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_STRONGBOX); + } catch (RemoteException e) { + // Not really an error state. Does not apply at all if RKP is unsupported or + // disabled on a given device. + } return new CredstoreWritableIdentityCredential(mContext, credentialName, docType, wc); } catch (android.os.RemoteException e) { throw new RuntimeException("Unexpected RemoteException ", e); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java index 7cf359729ee8..e71a59d26740 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java @@ -16,6 +16,7 @@ package com.android.wm.shell.back; +import android.view.KeyEvent; import android.view.MotionEvent; import android.window.BackEvent; @@ -29,8 +30,14 @@ public interface BackAnimation { /** * Called when a {@link MotionEvent} is generated by a back gesture. + * + * @param event the original {@link MotionEvent} + * @param action the original {@link KeyEvent#getAction()} when the event was dispatched to + * the process. This is forwarded separately because the input pipeline may mutate + * the {#event} action state later. + * @param swipeEdge the edge from which the swipe begins. */ - void onBackMotion(MotionEvent event, @BackEvent.SwipeEdge int swipeEdge); + void onBackMotion(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge); /** * Sets whether the back gesture is past the trigger threshold or not. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 08cb252cdf43..93ee3f5378e8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -138,8 +138,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } @Override - public void onBackMotion(MotionEvent event, @BackEvent.SwipeEdge int swipeEdge) { - mShellExecutor.execute(() -> onMotionEvent(event, swipeEdge)); + public void onBackMotion( + MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) { + mShellExecutor.execute(() -> onMotionEvent(event, action, swipeEdge)); } @Override @@ -209,13 +210,13 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont * Called when a new motion event needs to be transferred to this * {@link BackAnimationController} */ - public void onMotionEvent(MotionEvent event, @BackEvent.SwipeEdge int swipeEdge) { - int action = event.getActionMasked(); + public void onMotionEvent(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) { if (action == MotionEvent.ACTION_DOWN) { initAnimation(event); } else if (action == MotionEvent.ACTION_MOVE) { onMove(event, swipeEdge); } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Finishing gesture with event: %s", event); onGestureFinished(); } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt index f6abc75037ed..b137e92881a5 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt @@ -28,9 +28,6 @@ import com.android.server.wm.flicker.FlickerParametersRunnerFactory import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.annotation.Group4 import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before import org.junit.runner.RunWith import org.junit.Test import org.junit.runners.Parameterized @@ -52,11 +49,6 @@ open class DismissBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScree private val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager private val displaySize = DisplayMetrics() - @Before - open fun before() { - Assume.assumeFalse(isShellTransitionsEnabled) - } - override val transition: FlickerBuilder.() -> Unit get() = buildTransition { setup { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenShellTransit.kt deleted file mode 100644 index dd744b3c45ab..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenShellTransit.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2022 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.wm.shell.flicker.bubble - -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice - -import com.android.server.wm.flicker.FlickerParametersRunnerFactory -import com.android.server.wm.flicker.FlickerTestParameter -import com.android.server.wm.flicker.annotation.Group4 -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before - -import org.junit.runner.RunWith -import org.junit.runners.Parameterized - -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@Group4 -@FlakyTest(bugId = 217777115) -class DismissBubbleScreenShellTransit( - testSpec: FlickerTestParameter -) : DismissBubbleScreen(testSpec) { - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } -} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt index 2ec743c10413..f288b0a24d9d 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt @@ -24,9 +24,6 @@ import com.android.server.wm.flicker.FlickerParametersRunnerFactory import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.annotation.Group4 import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before import org.junit.runner.RunWith import org.junit.Test import org.junit.runners.Parameterized @@ -47,11 +44,6 @@ import org.junit.runners.Parameterized @Group4 open class ExpandBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen(testSpec) { - @Before - open fun before() { - Assume.assumeFalse(isShellTransitionsEnabled) - } - override val transition: FlickerBuilder.() -> Unit get() = buildTransition { setup { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenShellTransit.kt deleted file mode 100644 index d92ec7781005..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenShellTransit.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2022 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.wm.shell.flicker.bubble - -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.FlickerParametersRunnerFactory -import com.android.server.wm.flicker.FlickerTestParameter -import com.android.server.wm.flicker.annotation.Group4 -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before -import org.junit.runner.RunWith -import org.junit.runners.Parameterized - -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@Group4 -@FlakyTest(bugId = 217777115) -class ExpandBubbleScreenShellTransit( - testSpec: FlickerTestParameter -) : ExpandBubbleScreen(testSpec) { - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } -}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt index c43230e77683..0bb4d398bff4 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt @@ -17,15 +17,11 @@ package com.android.wm.shell.flicker.bubble import android.platform.test.annotations.Presubmit -import androidx.test.filters.FlakyTest import android.platform.test.annotations.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.annotation.Group4 import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized @@ -45,11 +41,6 @@ import org.junit.runners.Parameterized @Group4 open class LaunchBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen(testSpec) { - @Before - open fun before() { - Assume.assumeFalse(isShellTransitionsEnabled) - } - override val transition: FlickerBuilder.() -> Unit get() = buildTransition { transitions { @@ -61,16 +52,6 @@ open class LaunchBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen @Presubmit @Test open fun testAppIsAlwaysVisible() { - Assume.assumeFalse(isShellTransitionsEnabled) - testSpec.assertLayers { - this.isVisible(testApp.component) - } - } - - @FlakyTest(bugId = 218642026) - @Test - open fun testAppIsAlwaysVisible_ShellTransit() { - Assume.assumeTrue(isShellTransitionsEnabled) testSpec.assertLayers { this.isVisible(testApp.component) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenShellTransit.kt deleted file mode 100644 index 9350868a99f4..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenShellTransit.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2022 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.wm.shell.flicker.bubble - -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.FlickerParametersRunnerFactory -import com.android.server.wm.flicker.FlickerTestParameter -import com.android.server.wm.flicker.annotation.Group4 -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before -import org.junit.runner.RunWith -import org.junit.runners.Parameterized - -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@Group4 -@FlakyTest(bugId = 217777115) -class LaunchBubbleScreenShellTransit( - testSpec: FlickerTestParameter -) : LaunchBubbleScreen(testSpec) { - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } -} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt index 87e927fd50ea..8729bb6776f0 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt @@ -24,10 +24,7 @@ import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled import com.android.server.wm.flicker.traces.region.RegionSubject -import org.junit.Assume -import org.junit.Before import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -61,11 +58,6 @@ import org.junit.runners.Parameterized open class MovePipDownShelfHeightChangeTest( testSpec: FlickerTestParameter ) : MovePipShelfHeightTransition(testSpec) { - @Before - open fun before() { - Assume.assumeFalse(isShellTransitionsEnabled) - } - /** * Defines the transition used to run the test */ diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest_ShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest_ShellTransit.kt deleted file mode 100644 index 0ff260b94dc8..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest_ShellTransit.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.flicker.pip - -import androidx.test.filters.FlakyTest -import android.platform.test.annotations.RequiresDevice -import com.android.server.wm.flicker.FlickerParametersRunnerFactory -import com.android.server.wm.flicker.FlickerTestParameter -import com.android.server.wm.flicker.annotation.Group3 -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before -import org.junit.FixMethodOrder -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test Pip movement with Launcher shelf height change (decrease). - * - * To run this test: `atest WMShellFlickerTests:MovePipDownShelfHeightChangeTest` - * - * Actions: - * Launch [pipApp] in pip mode - * Launch [testApp] - * Press home - * Check if pip window moves down (visually) - * - * Notes: - * 1. Some default assertions (e.g., nav bar, status bar and screen covered) - * are inherited [PipTransition] - * 2. Part of the test setup occurs automatically via - * [com.android.server.wm.flicker.TransitionRunnerWithRules], - * including configuring navigation mode, initial orientation and ensuring no - * apps are running before setup - */ -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Group3 -@FlakyTest(bugId = 219693385) -class MovePipDownShelfHeightChangeTest_ShellTransit( - testSpec: FlickerTestParameter -) : MovePipDownShelfHeightChangeTest(testSpec) { - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } -} diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt index c8ced1c9df12..6af01e24f58c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt @@ -64,7 +64,6 @@ import org.junit.runners.Parameterized @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group4 -@FlakyTest(bugId = 218604389) open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) { private val fixedApp = FixedAppHelper(instrumentation) private val screenBoundsStart = WindowUtils.getDisplayBounds(testSpec.startRotation) @@ -138,7 +137,7 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS */ @Presubmit @Test - fun pipLayerRotates_StartingBounds() { + open fun pipLayerRotates_StartingBounds() { testSpec.assertLayersStart { visibleRegion(pipApp.component).coversAtMost(screenBoundsStart) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestShellTransit.kt index a017f56af5bd..2252a949ba00 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestShellTransit.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestShellTransit.kt @@ -34,10 +34,12 @@ import org.junit.runners.Parameterized @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group4 -@FlakyTest(bugId = 217777115) class PipRotationTestShellTransit(testSpec: FlickerTestParameter) : PipRotationTest(testSpec) { @Before override fun before() { Assume.assumeTrue(isShellTransitionsEnabled) } + + @FlakyTest(bugId = 227214914) + override fun pipLayerRotates_StartingBounds() = super.pipLayerRotates_StartingBounds() } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt index f7384e742a04..81403d08ff20 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt @@ -28,13 +28,10 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen import com.android.server.wm.flicker.helpers.WindowUtils -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE import com.android.wm.shell.flicker.testapp.Components import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION -import org.junit.Assume -import org.junit.Before import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -57,11 +54,6 @@ open class SetRequestedOrientationWhilePinnedTest( private val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0) private val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90) - @Before - open fun before() { - Assume.assumeFalse(isShellTransitionsEnabled) - } - override val transition: FlickerBuilder.() -> Unit get() = { setup { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTestShellTransit.kt deleted file mode 100644 index 8d764a8d0e69..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTestShellTransit.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2022 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.wm.shell.flicker.pip - -import androidx.test.filters.FlakyTest -import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.FlickerParametersRunnerFactory -import com.android.server.wm.flicker.FlickerTestParameter -import com.android.server.wm.flicker.annotation.Group4 -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before -import org.junit.FixMethodOrder -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test exiting Pip with orientation changes. - * To run this test: `atest WMShellFlickerTests:SetRequestedOrientationWhilePinnedTestShellTransit` - */ -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Group4 -@FlakyTest(bugId = 217777115) -class SetRequestedOrientationWhilePinnedTestShellTransit( - testSpec: FlickerTestParameter -) : SetRequestedOrientationWhilePinnedTest(testSpec) { - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } -} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java index 05230a9417bb..7c1fae3a849b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java @@ -118,6 +118,7 @@ public class BackAnimationControllerTest { BackNavigationInfo.TYPE_CROSS_ACTIVITY); mController.onMotionEvent( MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0), + MotionEvent.ACTION_DOWN, BackEvent.EDGE_LEFT); verify(mTransaction).setBuffer(screenshotSurface, hardwareBuffer); verify(mTransaction).setVisibility(screenshotSurface, true); @@ -133,9 +134,11 @@ public class BackAnimationControllerTest { BackNavigationInfo.TYPE_CROSS_ACTIVITY); mController.onMotionEvent( MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0), + MotionEvent.ACTION_DOWN, BackEvent.EDGE_LEFT); mController.onMotionEvent( MotionEvent.obtain(10, 0, MotionEvent.ACTION_MOVE, 100, 100, 0), + MotionEvent.ACTION_MOVE, BackEvent.EDGE_LEFT); verify(mTransaction).setPosition(animationTarget.leash, 100, 100); verify(mTransaction, atLeastOnce()).apply(); @@ -151,12 +154,14 @@ public class BackAnimationControllerTest { // Check that back start is dispatched. mController.onMotionEvent( MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0), + MotionEvent.ACTION_DOWN, BackEvent.EDGE_LEFT); verify(mIOnBackInvokedCallback).onBackStarted(); // Check that back progress is dispatched. mController.onMotionEvent( MotionEvent.obtain(10, 0, MotionEvent.ACTION_MOVE, 100, 100, 0), + MotionEvent.ACTION_MOVE, BackEvent.EDGE_LEFT); ArgumentCaptor<BackEvent> backEventCaptor = ArgumentCaptor.forClass(BackEvent.class); verify(mIOnBackInvokedCallback).onBackProgressed(backEventCaptor.capture()); @@ -166,6 +171,7 @@ public class BackAnimationControllerTest { mController.setTriggerBack(true); // Fake trigger back mController.onMotionEvent( MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0), + MotionEvent.ACTION_UP, BackEvent.EDGE_LEFT); verify(mIOnBackInvokedCallback).onBackInvoked(); } diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index 0e4a1f945b85..99fd463b0660 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -74,7 +74,15 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con if (backBuffer.get() == nullptr) { return false; } - LightingInfo::updateLighting(lightGeometry, lightInfo); + + // update the coordinates of the global light position based on surface rotation + SkPoint lightCenter = mVkSurface->getCurrentPreTransform().mapXY(lightGeometry.center.x, + lightGeometry.center.y); + LightGeometry localGeometry = lightGeometry; + localGeometry.center.x = lightCenter.fX; + localGeometry.center.y = lightCenter.fY; + + LightingInfo::updateLighting(localGeometry, lightInfo); renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer, mVkSurface->getCurrentPreTransform()); diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp index 00c4a9782f33..a2826cb58ccf 100644 --- a/media/jni/soundpool/SoundPool.cpp +++ b/media/jni/soundpool/SoundPool.cpp @@ -85,12 +85,13 @@ bool checkLoop(int32_t *loop) } // namespace SoundPool::SoundPool( - int32_t maxStreams, const audio_attributes_t* attributes, const std::string& opPackageName) + int32_t maxStreams, const audio_attributes_t& attributes, + const std::string& opPackageName) : mStreamManager(maxStreams, kStreamManagerThreads, attributes, opPackageName) { ALOGV("%s(maxStreams=%d, attr={ content_type=%d, usage=%d, flags=0x%x, tags=%s })", __func__, maxStreams, - attributes->content_type, attributes->usage, attributes->flags, attributes->tags); + attributes.content_type, attributes.usage, attributes.flags, attributes.tags); } SoundPool::~SoundPool() diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h index ffb1c997393a..6bb971b07e43 100644 --- a/media/jni/soundpool/SoundPool.h +++ b/media/jni/soundpool/SoundPool.h @@ -31,7 +31,7 @@ namespace android { */ class SoundPool { public: - SoundPool(int32_t maxStreams, const audio_attributes_t* attributes, + SoundPool(int32_t maxStreams, const audio_attributes_t& attributes, const std::string& opPackageName = {}); ~SoundPool(); diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp index 7f987e31d1d8..487a696d8765 100644 --- a/media/jni/soundpool/StreamManager.cpp +++ b/media/jni/soundpool/StreamManager.cpp @@ -106,10 +106,10 @@ int32_t StreamMap::getNextIdForStream(Stream* stream) const { #pragma clang diagnostic ignored "-Wthread-safety-analysis" StreamManager::StreamManager( - int32_t streams, size_t threads, const audio_attributes_t* attributes, + int32_t streams, size_t threads, const audio_attributes_t& attributes, std::string opPackageName) : StreamMap(streams) - , mAttributes(*attributes) + , mAttributes(attributes) , mOpPackageName(std::move(opPackageName)) , mLockStreamManagerStop(streams == 1 || kForceLockStreamManagerStop) { diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h index 85b468cd2cbc..ec65b0c49dc4 100644 --- a/media/jni/soundpool/StreamManager.h +++ b/media/jni/soundpool/StreamManager.h @@ -387,7 +387,7 @@ class StreamManager : public StreamMap { public: // Note: the SoundPool pointer is only used for stream initialization. // It is not stored in StreamManager. - StreamManager(int32_t streams, size_t threads, const audio_attributes_t* attributes, + StreamManager(int32_t streams, size_t threads, const audio_attributes_t& attributes, std::string opPackageName); ~StreamManager(); diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp index 14b0c11c986a..5264772be7c3 100644 --- a/media/jni/soundpool/android_media_SoundPool.cpp +++ b/media/jni/soundpool/android_media_SoundPool.cpp @@ -520,7 +520,7 @@ android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz, (audio_flags_mask_t) env->GetIntField(jaa, javaAudioAttrFields.fieldFlags); ScopedUtfChars opPackageNameStr(env, opPackageName); auto soundPool = std::make_shared<SoundPool>( - maxChannels, &audioAttributes, opPackageNameStr.c_str()); + maxChannels, audioAttributes, opPackageNameStr.c_str()); soundPool->setCallback(android_media_callback, nullptr /* user */); // register with SoundPoolManager. diff --git a/media/jni/soundpool/tests/soundpool_stress.cpp b/media/jni/soundpool/tests/soundpool_stress.cpp index 7d9b6a21b5c4..0116a99b2ba9 100644 --- a/media/jni/soundpool/tests/soundpool_stress.cpp +++ b/media/jni/soundpool/tests/soundpool_stress.cpp @@ -274,7 +274,7 @@ int main(int argc, char *argv[]) .content_type = AUDIO_CONTENT_TYPE_MUSIC, .usage = AUDIO_USAGE_MEDIA, }; - auto soundPool = std::make_unique<SoundPool>(maxStreams, &aa); + auto soundPool = std::make_unique<SoundPool>(maxStreams, aa); gCallbackManager.setSoundPool(soundPool.get()); soundPool->setCallback(StaticCallbackManager, &gCallbackManager); diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java index 2af7e00f9128..38d851eb76aa 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java @@ -41,6 +41,10 @@ import java.util.Arrays; import java.util.Enumeration; import java.util.List; import java.util.Locale; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -51,8 +55,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { private static final String TAG = "InstallationAsyncTask"; private static final int MIN_SHARED_MEMORY_SIZE = 8 << 10; // 8KiB - private static final int MAX_SHARED_MEMORY_SIZE = 1024 << 10; // 1MiB - private static final int DEFAULT_SHARED_MEMORY_SIZE = 64 << 10; // 64KiB + private static final int MAX_SHARED_MEMORY_SIZE = 8 << 20; // 8MiB + private static final int DEFAULT_SHARED_MEMORY_SIZE = 512 << 10; // 512KiB private static final String SHARED_MEMORY_SIZE_PROP = "dynamic_system.data_transfer.shared_memory.size"; @@ -488,7 +492,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { installWritablePartition("userdata", mUserdataSize); } - private void installImages() throws IOException, ImageValidationException { + private void installImages() throws ExecutionException, IOException, ImageValidationException { if (mStream != null) { if (mIsZip) { installStreamingZipUpdate(); @@ -500,7 +504,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } } - private void installStreamingGzUpdate() throws IOException, ImageValidationException { + private void installStreamingGzUpdate() + throws ExecutionException, IOException, ImageValidationException { Log.d(TAG, "To install a streaming GZ update"); installImage("system", mSystemSize, new GZIPInputStream(mStream)); } @@ -528,7 +533,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { return total; } - private void installStreamingZipUpdate() throws IOException, ImageValidationException { + private void installStreamingZipUpdate() + throws ExecutionException, IOException, ImageValidationException { Log.d(TAG, "To install a streaming ZIP update"); ZipInputStream zis = new ZipInputStream(mStream); @@ -548,7 +554,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } } - private void installLocalZipUpdate() throws IOException, ImageValidationException { + private void installLocalZipUpdate() + throws ExecutionException, IOException, ImageValidationException { Log.d(TAG, "To install a local ZIP update"); Enumeration<? extends ZipEntry> entries = mZipFile.entries(); @@ -569,7 +576,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } private void installImageFromAnEntry(ZipEntry entry, InputStream is) - throws IOException, ImageValidationException { + throws ExecutionException, IOException, ImageValidationException { String name = entry.getName(); Log.d(TAG, "ZipEntry: " + name); @@ -581,7 +588,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } private void installImage(String partitionName, long uncompressedSize, InputStream is) - throws IOException, ImageValidationException { + throws ExecutionException, IOException, ImageValidationException { SparseInputStream sis = new SparseInputStream(new BufferedInputStream(is)); @@ -637,27 +644,51 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { long prevInstalledSize = 0; long installedSize = 0; byte[] bytes = new byte[memoryFile.length()]; - int numBytesRead; + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Boolean> submitPromise = null; + + while (true) { + final int numBytesRead = sis.read(bytes, 0, bytes.length); + + if (submitPromise != null) { + // Wait until the previous submit task is complete. + while (true) { + try { + if (!submitPromise.get()) { + throw new IOException("Failed submitFromAshmem() to DynamicSystem"); + } + break; + } catch (InterruptedException e) { + // Ignore. + } + } + + // Publish the progress of the previous submit task. + if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) { + publishProgress(installedSize); + prevInstalledSize = installedSize; + } + } + + // Ensure the previous submit task (submitPromise) is complete before exiting the loop. + if (numBytesRead < 0) { + break; + } - while ((numBytesRead = sis.read(bytes, 0, bytes.length)) != -1) { if (isCancelled()) { return; } memoryFile.writeBytes(bytes, 0, 0, numBytesRead); + submitPromise = + executor.submit(() -> mInstallationSession.submitFromAshmem(numBytesRead)); - if (!mInstallationSession.submitFromAshmem(numBytesRead)) { - throw new IOException("Failed write() to DynamicSystem"); - } - + // Even though we update the bytes counter here, the actual progress is updated only + // after the submit task (submitPromise) is complete. installedSize += numBytesRead; - - if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) { - publishProgress(installedSize); - prevInstalledSize = installedSize; - } } + // Ensure a 100% mark is published. if (prevInstalledSize != partitionSize) { publishProgress(partitionSize); } diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index a9f5f8582403..804b8f187405 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1434,6 +1434,8 @@ <string name="guest_remove_guest_dialog_title">Remove guest?</string> <!-- Label for button in confirmation dialog when resetting guest user [CHAR LIMIT=35] --> <string name="guest_reset_guest_confirm_button">Reset</string> + <!-- Label for button in confirmation dialog when removing guest session [CHAR LIMIT=35] --> + <string name="guest_remove_guest_confirm_button">Remove</string> <!-- Status message indicating the device is in the process of resetting the guest user. [CHAR_LIMIT=NONE] --> <string name="guest_resetting">Resetting guest\u2026</string> <!-- An option in a photo selection dialog to take a new photo [CHAR LIMIT=50] --> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 1fc2b8563dc1..e8b87f57dfc6 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -671,6 +671,9 @@ <!-- Permission required for CTS test - CtsTelephonyTestCases --> <uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" /> + <!-- Permission required for CTS test - CtsPersistentDataBlockManagerTestCases --> + <uses-permission android:name="android.permission.ACCESS_PDB_STATE" /> + <!-- Permission required for CTS test - CtsAppEnumerationTestCases --> <uses-permission android:name="android.permission.MAKE_UID_VISIBLE" /> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 8df614d3c522..9767f04ac9d4 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -873,9 +873,6 @@ <!-- Message of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] --> <string name="guest_exit_guest_dialog_message">All apps and data in this session will be deleted.</string> - <!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] --> - <string name="guest_exit_guest_dialog_remove">Remove</string> - <!-- Title of the notification when resuming an existing guest session [CHAR LIMIT=NONE] --> <string name="guest_wipe_session_title">Welcome back, guest!</string> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index fcabbbca6e34..3b8a29bfe8c4 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -3562,8 +3562,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab pw.println(" udfpsEnrolled=" + isUdfpsEnrolled()); pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true)); pw.println(" bouncerVisible=" + mBouncer); - pw.println(" mStatusBarState=" - + StatusBarState.toShortString(mStatusBarState)); + pw.println(" mStatusBarState=" + StatusBarState.toString(mStatusBarState)); } } if (mFaceManager != null && mFaceManager.isHardwareDetected()) { diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 6f0cd47a3f70..ea366eaf4568 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -394,7 +394,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme pw.println(" mUserUnlockedWithBiometric: " + mUserUnlockedWithBiometric); pw.println(" mRunningFPS: " + mRunningFPS); pw.println(" mCanDismissLockScreen: " + mCanDismissLockScreen); - pw.println(" mStatusBarState: " + StatusBarState.toShortString(mStatusBarState)); + pw.println(" mStatusBarState: " + StatusBarState.toString(mStatusBarState)); pw.println(" mQsExpanded: " + mQsExpanded); pw.println(" mInterpolatedDarkAmount: " + mInterpolatedDarkAmount); diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt index 22c69373336f..011881354e35 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt @@ -369,10 +369,15 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec * Update the rounded corner size. */ fun updateRoundedCornerSize(top: Int, bottom: Int) { + if (roundedCornerTopSize == top && roundedCornerBottomSize == bottom) { + return + } roundedCornerTopSize = top roundedCornerBottomSize = bottom updateRoundedCornerDrawableBounds() - invalidate() + + // Use requestLayout() to trigger transparent region recalculated + requestLayout() } private fun updateRoundedCornerDrawableBounds() { diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index 2ec9174caee6..ede2945be29a 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -1045,13 +1045,22 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab mExecutor.execute(() -> { if (mOverlays == null) return; if (SIZE.equals(key)) { + boolean hasReloadRoundedCornerRes = false; if (newValue != null) { try { mRoundedCornerResDelegate.updateTuningSizeFactor( Integer.parseInt(newValue)); + hasReloadRoundedCornerRes = true; } catch (Exception e) { } } + + // When onTuningChanged() is not called through updateRoundedCornerRadii(), + // we need to reload rounded corner res to prevent incorrect dimen + if (!hasReloadRoundedCornerRes) { + mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId); + } + updateRoundedCornerSize( mRoundedCornerResDelegate.getTopRoundedSize(), mRoundedCornerResDelegate.getBottomRoundedSize()); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java index b8334a02e5f2..2a945ded08ef 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java @@ -185,7 +185,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud super.dump(fd, pw, args); pw.println("mShowingUdfpsBouncer=" + mShowingUdfpsBouncer); pw.println("mFaceDetectRunning=" + mFaceDetectRunning); - pw.println("mStatusBarState=" + StatusBarState.toShortString(mStatusBarState)); + pw.println("mStatusBarState=" + StatusBarState.toString(mStatusBarState)); pw.println("mQsExpanded=" + mQsExpanded); pw.println("mIsBouncerVisible=" + mIsBouncerVisible); pw.println("mInputBouncerHiddenAmount=" + mInputBouncerHiddenAmount); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index be326da8d3bf..b325700954c2 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -77,7 +77,7 @@ class FalsingCollectorImpl implements FalsingCollector { new StatusBarStateController.StateListener() { @Override public void onStateChanged(int newState) { - logDebug("StatusBarState=" + StatusBarState.toShortString(newState)); + logDebug("StatusBarState=" + StatusBarState.toString(newState)); mState = newState; updateSessionActive(); } diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt index c817f89c7a9b..4c444175eca1 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt @@ -56,17 +56,17 @@ class RoundedCornerResDelegate( private set init { - reloadDrawables() + reloadRes() reloadMeasures() } fun reloadAll(newDisplayUniqueId: String?) { displayUniqueId = newDisplayUniqueId - reloadDrawables() + reloadRes() reloadMeasures() } - private fun reloadDrawables() { + private fun reloadRes() { val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId) isMultipleRadius = getIsMultipleRadius(configIdx) @@ -85,34 +85,6 @@ class RoundedCornerResDelegate( arrayResId = R.array.config_roundedCornerBottomDrawableArray, backupDrawableId = R.drawable.rounded_corner_bottom ) ?: roundedDrawable - - // If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the - // (width, height) size of drawable/rounded.xml instead of rounded_corner_radius - if (isMultipleRadius) { - roundedSize = Size( - roundedDrawable?.intrinsicWidth ?: 0, - roundedDrawable?.intrinsicHeight ?: 0) - topRoundedDrawable?.let { - topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight) - } - bottomRoundedDrawable?.let { - bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight) - } - } else { - val defaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId) - val topRadius = RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId) - val bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId) - roundedSize = Size(defaultRadius, defaultRadius) - topRoundedSize = Size(topRadius, topRadius) - bottomRoundedSize = Size(bottomRadius, bottomRadius) - } - - if (topRoundedSize.width == 0) { - topRoundedSize = roundedSize - } - if (bottomRoundedSize.width == 0) { - bottomRoundedSize = roundedSize - } } private fun reloadMeasures(roundedSizeFactor: Int? = null) { @@ -137,17 +109,18 @@ class RoundedCornerResDelegate( bottomRoundedSize = Size(bottomRadius, bottomRadius) } - roundedSizeFactor ?.let { - val length: Int = (it * density).toInt() - roundedSize = Size(length, length) - } - if (topRoundedSize.width == 0) { topRoundedSize = roundedSize } if (bottomRoundedSize.width == 0) { bottomRoundedSize = roundedSize } + + if (roundedSizeFactor != null && roundedSizeFactor > 0) { + val length: Int = (roundedSizeFactor * density).toInt() + topRoundedSize = Size(length, length) + bottomRoundedSize = Size(length, length) + } } fun updateTuningSizeFactor(factor: Int) { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java index a1258df7a12c..03652412c129 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java @@ -480,7 +480,9 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl public void onMotionEvent(MotionEvent event) { if (mBackAnimation != null) { mBackAnimation.onBackMotion( - event, mIsLeftPanel ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT); + event, + event.getActionMasked(), + mIsLeftPanel ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT); } if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 8d0494afbb89..7f49bcd9d926 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -26,6 +26,7 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; import android.os.Trace; +import android.util.IndentingPrintWriter; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; @@ -38,6 +39,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.keyguard.BouncerPanelExpansionCalculator; +import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; import com.android.systemui.animation.ShadeInterpolation; @@ -58,13 +60,16 @@ import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; import com.android.systemui.util.LifecycleFragment; import com.android.systemui.util.Utils; +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.Arrays; import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Named; public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Callbacks, - StatusBarStateController.StateListener { + StatusBarStateController.StateListener, Dumpable { private static final String TAG = "QS"; private static final boolean DEBUG = false; private static final String EXTRA_EXPANDED = "expanded"; @@ -135,7 +140,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca */ private boolean mAnimateNextQsUpdate; - private DumpManager mDumpManager; + private final DumpManager mDumpManager; /** * Progress of pull down from the center of the lock screen. @@ -256,15 +261,26 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mDumpManager.registerDumpable(getClass().getName(), this); + } + + @Override public void onDestroy() { super.onDestroy(); mStatusBarStateController.removeCallback(this); if (mListening) { setListening(false); } - mQSCustomizerController.setQs(null); + if (mQSCustomizerController != null) { + mQSCustomizerController.setQs(null); + } mScrollListener = null; - mDumpManager.unregisterDumpable(mContainer.getClass().getName()); + if (mContainer != null) { + mDumpManager.unregisterDumpable(mContainer.getClass().getName()); + } + mDumpManager.unregisterDumpable(getClass().getName()); } @Override @@ -272,7 +288,9 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca super.onSaveInstanceState(outState); outState.putBoolean(EXTRA_EXPANDED, mQsExpanded); outState.putBoolean(EXTRA_LISTENING, mListening); - mQSCustomizerController.saveInstanceState(outState); + if (mQSCustomizerController != null) { + mQSCustomizerController.saveInstanceState(outState); + } if (mQsExpanded) { mQSPanelController.getTileLayout().saveInstanceState(outState); } @@ -594,7 +612,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } else if (progress > 0 && view.getVisibility() != View.VISIBLE) { view.setVisibility((View.VISIBLE)); } - float alpha = (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) + float alpha = mQSPanelController.bouncerInTransit() ? BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(progress) : ShadeInterpolation.getContentAlpha(progress); view.setAlpha(alpha); @@ -787,4 +805,62 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca setKeyguardShowing(newState == StatusBarState.KEYGUARD); updateShowCollapsedOnKeyguard(); } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + IndentingPrintWriter indentingPw = new IndentingPrintWriter(pw, /* singleIndent= */ " "); + indentingPw.println("QSFragment:"); + indentingPw.increaseIndent(); + indentingPw.println("mQsBounds: " + mQsBounds); + indentingPw.println("mQsExpanded: " + mQsExpanded); + indentingPw.println("mHeaderAnimating: " + mHeaderAnimating); + indentingPw.println("mStackScrollerOverscrolling: " + mStackScrollerOverscrolling); + indentingPw.println("mListening: " + mListening); + indentingPw.println("mLayoutDirection: " + mLayoutDirection); + indentingPw.println("mLastQSExpansion: " + mLastQSExpansion); + indentingPw.println("mLastPanelFraction: " + mLastPanelFraction); + indentingPw.println("mSquishinessFraction: " + mSquishinessFraction); + indentingPw.println("mQsDisabled: " + mQsDisabled); + indentingPw.println("mTemp: " + Arrays.toString(mTemp)); + indentingPw.println("mShowCollapsedOnKeyguard: " + mShowCollapsedOnKeyguard); + indentingPw.println("mLastKeyguardAndExpanded: " + mLastKeyguardAndExpanded); + indentingPw.println("mState: " + StatusBarState.toString(mState)); + indentingPw.println("mTmpLocation: " + Arrays.toString(mTmpLocation)); + indentingPw.println("mLastViewHeight: " + mLastViewHeight); + indentingPw.println("mLastHeaderTranslation: " + mLastHeaderTranslation); + indentingPw.println("mInSplitShade: " + mInSplitShade); + indentingPw.println("mTransitioningToFullShade: " + mTransitioningToFullShade); + indentingPw.println("mFullShadeProgress: " + mFullShadeProgress); + indentingPw.println("mOverScrolling: " + mOverScrolling); + indentingPw.println("isCustomizing: " + mQSCustomizerController.isCustomizing()); + View view = getView(); + if (view != null) { + indentingPw.println("top: " + view.getTop()); + indentingPw.println("y: " + view.getY()); + indentingPw.println("translationY: " + view.getTranslationY()); + indentingPw.println("alpha: " + view.getAlpha()); + indentingPw.println("height: " + view.getHeight()); + indentingPw.println("measuredHeight: " + view.getMeasuredHeight()); + indentingPw.println("clipBounds: " + view.getClipBounds()); + } else { + indentingPw.println("getView(): null"); + } + QuickStatusBarHeader header = mHeader; + if (header != null) { + indentingPw.println("headerHeight: " + header.getHeight()); + indentingPw.println("Header visibility: " + visibilityToString(header.getVisibility())); + } else { + indentingPw.println("mHeader: null"); + } + } + + private static String visibilityToString(int visibility) { + if (visibility == View.VISIBLE) { + return "VISIBLE"; + } + if (visibility == View.INVISIBLE) { + return "INVISIBLE"; + } + return "GONE"; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java index dd2929c9a67a..10d792098608 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -43,6 +43,7 @@ import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.settings.brightness.BrightnessController; import com.android.systemui.settings.brightness.BrightnessMirrorHandler; import com.android.systemui.settings.brightness.BrightnessSliderController; +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.tuner.TunerService; @@ -65,6 +66,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { private final BrightnessSliderController mBrightnessSliderController; private final BrightnessMirrorHandler mBrightnessMirrorHandler; private final FeatureFlags mFeatureFlags; + private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private boolean mGridContentVisible = true; @@ -101,7 +103,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory, BrightnessSliderController.Factory brightnessSliderFactory, - FalsingManager falsingManager, FeatureFlags featureFlags) { + FalsingManager falsingManager, FeatureFlags featureFlags, + StatusBarKeyguardViewManager statusBarKeyguardViewManager) { super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, uiEventLogger, qsLogger, dumpManager); mQSFgsManagerFooter = qsFgsManagerFooter; @@ -117,6 +120,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController); mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController); mFeatureFlags = featureFlags; + mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; view.setUseNewFooter(featureFlags.isEnabled(Flags.NEW_FOOTER)); } @@ -281,5 +285,14 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { void setPageMargin(int pageMargin) { mView.setPageMargin(pageMargin); } + + /** + * Determines if bouncer expansion is between 0 and 1 non-inclusive. + * + * @return if bouncer is in transit + */ + public boolean bouncerInTransit() { + return mStatusBarKeyguardViewManager.bouncerIsInTransit(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt index 5c1d332df7a7..86ef85824eb0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt @@ -73,7 +73,7 @@ class QSLogger @Inject constructor( log(DEBUG, { str1 = tileSpec int1 = statusBarState - str2 = StatusBarState.toShortString(statusBarState) + str2 = StatusBarState.toString(statusBarState) str3 = toStateString(state) }, { "[$str1] Tile clicked. StatusBarState=$str2. TileState=$str3" @@ -84,7 +84,7 @@ class QSLogger @Inject constructor( log(DEBUG, { str1 = tileSpec int1 = statusBarState - str2 = StatusBarState.toShortString(statusBarState) + str2 = StatusBarState.toString(statusBarState) str3 = toStateString(state) }, { "[$str1] Tile long clicked. StatusBarState=$str2. TileState=$str3" @@ -95,7 +95,7 @@ class QSLogger @Inject constructor( log(DEBUG, { str1 = tileSpec int1 = statusBarState - str2 = StatusBarState.toShortString(statusBarState) + str2 = StatusBarState.toString(statusBarState) str3 = toStateString(state) }, { "[$str1] Tile long clicked. StatusBarState=$str2. TileState=$str3" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java index 16bc951e0323..718bc5caf414 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java @@ -37,16 +37,19 @@ public class StatusBarState { */ public static final int SHADE_LOCKED = 2; - public static String toShortString(int x) { - switch (x) { + /** + * Returns the textual representation of the status bar state. + */ + public static String toString(int state) { + switch (state) { case SHADE: - return "SHD"; + return "SHADE"; case SHADE_LOCKED: - return "SHD_LCK"; + return "SHADE_LOCKED"; case KEYGUARD: - return "KGRD"; + return "KEYGUARD"; default: - return "bad_value_" + x; + return "UNKNOWN: " + state; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java index 2763bd711338..19f59f76f8a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java @@ -508,7 +508,7 @@ public class StatusBarStateControllerImpl implements * Returns String readable state of status bar from {@link StatusBarState} */ public static String describe(int state) { - return StatusBarState.toShortString(state); + return StatusBarState.toString(state); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 32d37d18f407..c0553b5c3c2d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -347,7 +347,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable setDimAmount((Float) animation.getAnimatedValue()); } }; - protected ViewGroup mQsContainer; + protected ViewGroup mQsHeader; + // Rect of QsHeader. Kept as a field just to avoid creating a new one each time. + private Rect mQsHeaderBound = new Rect(); private boolean mContinuousShadowUpdate; private boolean mContinuousBackgroundUpdate; private ViewTreeObserver.OnPreDrawListener mShadowUpdater @@ -1598,8 +1600,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } @ShadeViewRefactor(RefactorComponent.ADAPTER) - public void setQsContainer(ViewGroup qsContainer) { - mQsContainer = qsContainer; + public void setQsHeader(ViewGroup qsHeader) { + mQsHeader = qsHeader; } @ShadeViewRefactor(RefactorComponent.ADAPTER) @@ -3458,7 +3460,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (!isScrollingEnabled()) { return false; } - if (isInsideQsContainer(ev) && !mIsBeingDragged) { + if (isInsideQsHeader(ev) && !mIsBeingDragged) { return false; } mForcedScroll = null; @@ -3611,8 +3613,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } @ShadeViewRefactor(RefactorComponent.INPUT) - protected boolean isInsideQsContainer(MotionEvent ev) { - return ev.getY() < mQsContainer.getBottom(); + protected boolean isInsideQsHeader(MotionEvent ev) { + mQsHeader.getBoundsOnScreen(mQsHeaderBound); + return mQsHeaderBound.contains((int) ev.getX(), (int) ev.getY()); } @ShadeViewRefactor(RefactorComponent.INPUT) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 5bc50ae11fb7..3e630cdf8f97 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -1234,8 +1234,9 @@ public class NotificationStackScrollLayoutController { mView.setExpandedHeight(expandedHeight); } - public void setQsContainer(ViewGroup view) { - mView.setQsContainer(view); + /** Sets the QS header. Used to check if a touch is within its bounds. */ + public void setQsHeader(ViewGroup view) { + mView.setQsHeader(view); } public void setAnimationsEnabled(boolean enabled) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 2d16b52839eb..11628cb75e87 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -3592,7 +3592,7 @@ public class NotificationPanelViewController extends PanelViewController { } }); mLockscreenShadeTransitionController.setQS(mQs); - mNotificationStackScrollLayoutController.setQsContainer((ViewGroup) mQs.getView()); + mNotificationStackScrollLayoutController.setQsHeader((ViewGroup) mQs.getHeader()); mQs.setScrollListener(mScrollListener); updateQsExpansion(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index be50a17b8536..71f199f330a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -797,10 +797,9 @@ public abstract class PanelViewController { } mExpandedFraction = Math.min(1f, maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); - mAmbientState.setExpansionFraction(mKeyguardStateController.isUnlocked() - ? mExpandedFraction - : BouncerPanelExpansionCalculator - .getBackScrimScaledExpansion(mExpandedFraction)); + mAmbientState.setExpansionFraction(mStatusBarKeyguardViewManager.bouncerIsInTransit() + ? BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(mExpandedFraction) + : mExpandedFraction); onHeightUpdated(mExpandedHeight); updatePanelExpansionAndVisibility(); }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 8272ed926255..a98ec58dc94c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -204,6 +204,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump private final Executor mMainExecutor; private final ScreenOffAnimationController mScreenOffAnimationController; private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private GradientColors mColors; private boolean mNeedsDrawableColorUpdate; @@ -266,7 +267,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump ConfigurationController configurationController, @Main Executor mainExecutor, ScreenOffAnimationController screenOffAnimationController, PanelExpansionStateManager panelExpansionStateManager, - KeyguardUnlockAnimationController keyguardUnlockAnimationController) { + KeyguardUnlockAnimationController keyguardUnlockAnimationController, + StatusBarKeyguardViewManager statusBarKeyguardViewManager) { mScrimStateListener = lightBarController::setScrimState; mDefaultScrimAlpha = BUSY_SCRIM_ALPHA; @@ -292,6 +294,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump keyguardStateController.getKeyguardFadingAwayDuration()); } }); + mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; configurationController.addCallback(new ConfigurationController.ConfigurationListener() { @Override public void onThemeChanged() { @@ -1021,6 +1024,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump if (aodWallpaperTimeout || occludedKeyguard) { mBehindAlpha = 1; } + // Prevent notification scrim flicker when transitioning away from keyguard. + if (mKeyguardStateController.isKeyguardGoingAway()) { + mNotificationsAlpha = 0; + } setScrimAlpha(mScrimInFront, mInFrontAlpha); setScrimAlpha(mScrimBehind, mBehindAlpha); setScrimAlpha(mNotificationsScrim, mNotificationsAlpha); @@ -1057,7 +1064,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump } private float getInterpolatedFraction() { - if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED) { + if (mStatusBarKeyguardViewManager.bouncerIsInTransit()) { return BouncerPanelExpansionCalculator .getBackScrimScaledExpansion(mPanelExpansionFraction); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 23401618e1f3..a1cbba47e822 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -1368,6 +1368,15 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } /** + * Returns if bouncer expansion is between 0 and 1 non-inclusive. + */ + public boolean bouncerIsInTransit() { + if (mBouncer == null) return false; + + return mBouncer.inTransit(); + } + + /** * Delegate used to send show/reset events to an alternate authentication method instead of the * regular pin/pattern/password bouncer. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index 8396639fe0f5..2c05a4ea8238 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -1155,7 +1155,8 @@ public class UserSwitcherController implements Dumpable { setButton(DialogInterface.BUTTON_POSITIVE, context.getString(mGuestUserAutoCreated ? com.android.settingslib.R.string.guest_reset_guest_confirm_button - : R.string.guest_exit_guest_dialog_remove), this); + : com.android.settingslib.R.string.guest_remove_guest_confirm_button), + this); SystemUIDialog.setWindowOnTop(this, mKeyguardStateController.isShowing()); setCanceledOnTouchOutside(false); mGuestId = guestId; diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt index b536bfdb944e..2effaec58a86 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt @@ -75,7 +75,7 @@ class RoundedCornerResDelegateTest : SysuiTestCase() { fun testUpdateTuningSizeFactor() { mContext.orCreateTestableResources.addOverrides( mockTypeArray = mockTypedArray, - radiusTop = 0, + radiusTop = 2, radiusBottom = 0, multipleRadius = false) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index 534c7e7f2029..777198b43d4a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -14,37 +14,41 @@ package com.android.systemui.qs; -import static org.junit.Assert.assertEquals; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.app.Fragment; import android.content.Context; +import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.testing.AndroidTestingRunner; -import android.testing.LayoutInflaterBuilder; -import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import android.view.LayoutInflater; import android.view.View; -import android.widget.FrameLayout; +import android.view.ViewGroup; import androidx.test.filters.SmallTest; -import androidx.test.filters.Suppress; -import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; -import com.android.keyguard.CarrierText; -import com.android.systemui.Dependency; +import com.android.keyguard.BouncerPanelExpansionCalculator; +import com.android.systemui.R; import com.android.systemui.SysuiBaseFragmentTest; +import com.android.systemui.animation.ShadeInterpolation; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dump.DumpManager; import com.android.systemui.media.MediaHost; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.qs.customize.QSCustomizerController; import com.android.systemui.qs.dagger.QSFragmentComponent; import com.android.systemui.qs.external.CustomTileStatePersister; import com.android.systemui.qs.external.TileLifecycleManager; @@ -54,19 +58,18 @@ import com.android.systemui.qs.tileimpl.QSFactoryImpl; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.AutoTileManager; -import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.CentralSurfaces; +import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.StatusBarIconController; -import com.android.systemui.statusbar.policy.Clock; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; -import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.tuner.TunerService; +import com.android.systemui.util.animation.UniqueObjectHostView; import com.android.systemui.util.settings.SecureSettings; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -75,77 +78,69 @@ import org.mockito.MockitoAnnotations; import java.util.Optional; @RunWith(AndroidTestingRunner.class) -@RunWithLooper +@RunWithLooper(setAsMainLooper = true) @SmallTest -@Suppress public class QSFragmentTest extends SysuiBaseFragmentTest { - private MetricsLogger mMockMetricsLogger; - @Mock - private QSFragmentComponent.Factory mQsComponentFactory; - @Mock - private QSFragmentComponent mQsFragmentComponent; - @Mock - private QSPanelController mQSPanelController; - @Mock - private MediaHost mQSMediaHost; - @Mock - private MediaHost mQQSMediaHost; - @Mock - private KeyguardBypassController mBypassController; - @Mock - private FalsingManager mFalsingManager; - @Mock - private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder; - @Mock - private TileServiceRequestController mTileServiceRequestController; + @Mock private QSFragmentComponent.Factory mQsComponentFactory; + @Mock private QSFragmentComponent mQsFragmentComponent; + @Mock private QSPanelController mQSPanelController; + @Mock private MediaHost mQSMediaHost; + @Mock private MediaHost mQQSMediaHost; + @Mock private KeyguardBypassController mBypassController; + @Mock private FalsingManager mFalsingManager; + @Mock private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder; + @Mock private TileServiceRequestController mTileServiceRequestController; + @Mock private QSCustomizerController mQsCustomizerController; + @Mock private QuickQSPanelController mQuickQSPanelController; + @Mock private FooterActionsController mQSFooterActionController; + @Mock private QSContainerImplController mQSContainerImplController; + @Mock private QSContainerImpl mContainer; + @Mock private QSFooter mFooter; + @Mock private LayoutInflater mLayoutInflater; + @Mock private NonInterceptingScrollView mQSPanelScrollView; + @Mock private QuickStatusBarHeader mHeader; + @Mock private QSPanel.QSTileLayout mQsTileLayout; + @Mock private QSPanel.QSTileLayout mQQsTileLayout; + @Mock private QSAnimator mQSAnimator; + private View mQsFragmentView; + @Mock private StatusBarStateController mStatusBarStateController; public QSFragmentTest() { super(QSFragment.class); - injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); } @Before - @Ignore("failing") - public void addLeakCheckDependencies() { - MockitoAnnotations.initMocks(this); - when(mQsComponentFactory.create(any(QSFragment.class))).thenReturn(mQsFragmentComponent); - when(mQsFragmentComponent.getQSPanelController()).thenReturn(mQSPanelController); - - when(mTileServiceRequestControllerBuilder.create(any())) - .thenReturn(mTileServiceRequestController); - - mMockMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class); - mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, - new LayoutInflaterBuilder(mContext) - .replace("com.android.systemui.statusbar.policy.SplitClockView", - FrameLayout.class) - .replace("TextClock", View.class) - .replace(CarrierText.class, View.class) - .replace(Clock.class, View.class) - .build()); - - mDependency.injectTestDependency(Dependency.BG_LOOPER, - TestableLooper.get(this).getLooper()); - mDependency.injectMockDependency(UserSwitcherController.class); + public void setup() { + injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); } @Test - @Ignore("failing") public void testListening() { - assertEquals(Looper.myLooper(), Looper.getMainLooper()); QSFragment qs = (QSFragment) mFragment; mFragments.dispatchResume(); processAllMessages(); - QSTileHost host = new QSTileHost(mContext, mock(StatusBarIconController.class), - mock(QSFactoryImpl.class), new Handler(), Looper.myLooper(), - mock(PluginManager.class), mock(TunerService.class), - () -> mock(AutoTileManager.class), mock(DumpManager.class), - mock(BroadcastDispatcher.class), Optional.of(mock(CentralSurfaces.class)), - mock(QSLogger.class), mock(UiEventLogger.class), mock(UserTracker.class), - mock(SecureSettings.class), mock(CustomTileStatePersister.class), - mTileServiceRequestControllerBuilder, mock(TileLifecycleManager.Factory.class)); + QSTileHost host = + new QSTileHost( + mContext, + mock(StatusBarIconController.class), + mock(QSFactoryImpl.class), + new Handler(), + Looper.myLooper(), + mock(PluginManager.class), + mock(TunerService.class), + () -> mock(AutoTileManager.class), + mock(DumpManager.class), + mock(BroadcastDispatcher.class), + Optional.of(mock(CentralSurfaces.class)), + mock(QSLogger.class), + mock(UiEventLogger.class), + mock(UserTracker.class), + mock(SecureSettings.class), + mock(CustomTileStatePersister.class), + mTileServiceRequestControllerBuilder, + mock(TileLifecycleManager.Factory.class)); qs.setListening(true); processAllMessages(); @@ -157,13 +152,11 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { } @Test - @Ignore("failing") public void testSaveState() { - QSFragment qs = (QSFragment) mFragment; - mFragments.dispatchResume(); processAllMessages(); + QSFragment qs = (QSFragment) mFragment; qs.setListening(true); qs.setExpanded(true); processAllMessages(); @@ -176,14 +169,91 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { assertTrue(qs.isExpanded()); } + @Test + public void transitionToFullShade_inSplitShade_setsAlphaBasedOnProgress() { + QSFragment fragment = resumeAndGetFragment(); + enableSplitShade(); + int transitionPxAmount = 123; + float transitionProgress = 0.5f; + + fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + + assertThat(mQsFragmentView.getAlpha()) + .isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress)); + } + + @Test + public void + transitionToFullShade_inSplitShade_onKeyguard_bouncerNotActive_usesShadeInterpolator() { + QSFragment fragment = resumeAndGetFragment(); + enableSplitShade(); + setStatusBarState(StatusBarState.KEYGUARD); + when(mQSPanelController.bouncerInTransit()).thenReturn(false); + int transitionPxAmount = 123; + float transitionProgress = 0.5f; + + fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + + assertThat(mQsFragmentView.getAlpha()) + .isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress)); + } + + @Test + public void + transitionToFullShade_inSplitShade_onKeyguard_bouncerActive_usesBouncerInterpolator() { + QSFragment fragment = resumeAndGetFragment(); + enableSplitShade(); + setStatusBarState(StatusBarState.KEYGUARD); + when(mQSPanelController.bouncerInTransit()).thenReturn(true); + int transitionPxAmount = 123; + float transitionProgress = 0.5f; + + fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + + assertThat(mQsFragmentView.getAlpha()) + .isEqualTo( + BouncerPanelExpansionCalculator.getBackScrimScaledExpansion( + transitionProgress)); + } + + @Test + public void transitionToFullShade_notInSplitShade_alwaysSetsAlphaTo1() { + QSFragment fragment = resumeAndGetFragment(); + disableSplitShade(); + + int transitionPxAmount = 12; + float transitionProgress = 0.1f; + fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + assertThat(mQsFragmentView.getAlpha()).isEqualTo(1); + + transitionPxAmount = 123; + transitionProgress = 0.5f; + fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + assertThat(mQsFragmentView.getAlpha()).isEqualTo(1); + assertThat(mQsFragmentView.getAlpha()).isEqualTo(1); + + transitionPxAmount = 234; + transitionProgress = 0.7f; + fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + assertThat(mQsFragmentView.getAlpha()).isEqualTo(1); + } + @Override protected Fragment instantiate(Context context, String className, Bundle arguments) { + MockitoAnnotations.initMocks(this); CommandQueue commandQueue = new CommandQueue(context); + + setupQsComponent(); + setUpViews(); + setUpInflater(); + setUpMedia(); + setUpOther(); + return new QSFragment( - new RemoteInputQuickSettingsDisabler(context, commandQueue, - mock(ConfigurationController.class)), + new RemoteInputQuickSettingsDisabler( + context, commandQueue, mock(ConfigurationController.class)), mock(QSTileHost.class), - mock(StatusBarStateController.class), + mStatusBarStateController, commandQueue, mQSMediaHost, mQQSMediaHost, @@ -193,4 +263,73 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { mFalsingManager, mock(DumpManager.class)); } + + private void setUpOther() { + when(mTileServiceRequestControllerBuilder.create(any())) + .thenReturn(mTileServiceRequestController); + when(mQSContainerImplController.getView()).thenReturn(mContainer); + when(mQSPanelController.getTileLayout()).thenReturn(mQQsTileLayout); + when(mQuickQSPanelController.getTileLayout()).thenReturn(mQsTileLayout); + } + + private void setUpMedia() { + when(mQSMediaHost.getCurrentClipping()).thenReturn(new Rect()); + when(mQSMediaHost.getHostView()).thenReturn(new UniqueObjectHostView(mContext)); + when(mQQSMediaHost.getHostView()).thenReturn(new UniqueObjectHostView(mContext)); + } + + private void setUpViews() { + mQsFragmentView = spy(new View(mContext)); + when(mQsFragmentView.findViewById(R.id.expanded_qs_scroll_view)) + .thenReturn(mQSPanelScrollView); + when(mQsFragmentView.findViewById(R.id.header)).thenReturn(mHeader); + when(mQsFragmentView.findViewById(android.R.id.edit)).thenReturn(new View(mContext)); + } + + private void setUpInflater() { + when(mLayoutInflater.cloneInContext(any(Context.class))).thenReturn(mLayoutInflater); + when(mLayoutInflater.inflate(anyInt(), any(ViewGroup.class), anyBoolean())) + .thenReturn(mQsFragmentView); + mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater); + } + + private void setupQsComponent() { + when(mQsComponentFactory.create(any(QSFragment.class))).thenReturn(mQsFragmentComponent); + when(mQsFragmentComponent.getQSPanelController()).thenReturn(mQSPanelController); + when(mQsFragmentComponent.getQuickQSPanelController()).thenReturn(mQuickQSPanelController); + when(mQsFragmentComponent.getQSCustomizerController()).thenReturn(mQsCustomizerController); + when(mQsFragmentComponent.getQSContainerImplController()) + .thenReturn(mQSContainerImplController); + when(mQsFragmentComponent.getQSFooter()).thenReturn(mFooter); + when(mQsFragmentComponent.getQSFooterActionController()) + .thenReturn(mQSFooterActionController); + when(mQsFragmentComponent.getQSAnimator()).thenReturn(mQSAnimator); + } + + private QSFragment getFragment() { + return ((QSFragment) mFragment); + } + + private QSFragment resumeAndGetFragment() { + mFragments.dispatchResume(); + processAllMessages(); + return getFragment(); + } + + private void setStatusBarState(int statusBarState) { + when(mStatusBarStateController.getState()).thenReturn(statusBarState); + getFragment().onStateChanged(statusBarState); + } + + private void enableSplitShade() { + setSplitShadeEnabled(true); + } + + private void disableSplitShade() { + setSplitShadeEnabled(false); + } + + private void setSplitShadeEnabled(boolean enabled) { + getFragment().setInSplitShade(enabled); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt index e9488e9ad98c..58a070db9a95 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt @@ -15,7 +15,9 @@ import com.android.systemui.qs.customize.QSCustomizerController import com.android.systemui.qs.logging.QSLogger import com.android.systemui.settings.brightness.BrightnessController import com.android.systemui.settings.brightness.BrightnessSliderController +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.tuner.TunerService +import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before import org.junit.Test @@ -52,6 +54,7 @@ class QSPanelControllerTest : SysuiTestCase() { @Mock private lateinit var mediaHost: MediaHost @Mock private lateinit var tile: QSTile @Mock private lateinit var otherTile: QSTile + @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager private lateinit var controller: QSPanelController @@ -62,6 +65,7 @@ class QSPanelControllerTest : SysuiTestCase() { whenever(brightnessSliderFactory.create(any(), any())).thenReturn(brightnessSlider) whenever(brightnessControllerFactory.create(any())).thenReturn(brightnessController) whenever(qsPanel.resources).thenReturn(mContext.orCreateTestableResources.resources) + whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false) controller = QSPanelController( qsPanel, @@ -80,7 +84,8 @@ class QSPanelControllerTest : SysuiTestCase() { brightnessControllerFactory, brightnessSliderFactory, falsingManager, - featureFlags + featureFlags, + statusBarKeyguardViewManager ) } @@ -109,4 +114,12 @@ class QSPanelControllerTest : SysuiTestCase() { verify(tile).refreshState() verify(otherTile, Mockito.never()).refreshState() } + + @Test + fun testBouncerIsInTransit() { + whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true) + assertThat(controller.bouncerInTransit()).isEqualTo(true) + whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false) + assertThat(controller.bouncerInTransit()).isEqualTo(false) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 5eef1df8c7a3..81a5f11b1553 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -119,6 +119,8 @@ public class ScrimControllerTest extends SysuiTestCase { // event-dispatch-on-registration pattern caused some of these unit tests to fail.) @Mock private PanelExpansionStateManager mPanelExpansionStateManager; + @Mock + private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private static class AnimatorListener implements Animator.AnimatorListener { @@ -233,7 +235,8 @@ public class ScrimControllerTest extends SysuiTestCase { mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()), mScreenOffAnimationController, mPanelExpansionStateManager, - mKeyguardUnlockAnimationController); + mKeyguardUnlockAnimationController, + mStatusBarKeyguardViewManager); mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible); mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront); mScrimController.setAnimatorListener(mAnimatorListener); @@ -1234,6 +1237,8 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void testNotificationTransparency_followsPanelExpansionInShadeLockedState() { + when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true); + mScrimController.transitionTo(ScrimState.SHADE_LOCKED); assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0f, /* expansion */ 0.8f); @@ -1242,6 +1247,8 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void testNotificationTransparency_unnocclusion() { + when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true); + mScrimController.transitionTo(ScrimState.KEYGUARD); mScrimController.setUnocclusionAnimationRunning(true); @@ -1255,6 +1262,8 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void testNotificationTransparency_inKeyguardState() { + when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true); + mScrimController.transitionTo(ScrimState.KEYGUARD); assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 1f, /* expansion */ 0.8f); @@ -1351,6 +1360,15 @@ public class ScrimControllerTest extends SysuiTestCase { )); } + @Test + public void keyguardGoingAwayUpdateScrims() { + when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true); + mScrimController.updateScrims(); + finishAnimationsImmediately(); + assertThat(mNotificationsScrim.getViewAlpha()).isEqualTo(TRANSPARENT); + } + + private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) { mScrimController.setRawPanelExpansionFraction(expansion); finishAnimationsImmediately(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index ede3de83b572..90cbf540004e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -55,6 +55,8 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.unfold.SysUIUnfoldComponent; +import com.google.common.truth.Truth; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -434,4 +436,14 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { verify(mBouncer).updateKeyguardPosition(1.0f); } + + @Test + public void testBouncerIsInTransit() { + when(mBouncer.inTransit()).thenReturn(true); + Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isTrue(); + when(mBouncer.inTransit()).thenReturn(false); + Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isFalse(); + mBouncer = null; + Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isFalse(); + } } diff --git a/services/core/java/com/android/server/display/OWNERS b/services/core/java/com/android/server/display/OWNERS index 09d96be43a43..8e3460175158 100644 --- a/services/core/java/com/android/server/display/OWNERS +++ b/services/core/java/com/android/server/display/OWNERS @@ -3,5 +3,6 @@ dangittik@google.com hackbod@google.com ogunwale@google.com santoscordon@google.com +flc@google.com per-file ColorDisplayService.java=christyfranks@google.com diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 6cfaf9cce092..78cffa6f4f79 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -635,7 +635,7 @@ public class LockSettingsService extends ILockSettings.Stub { * If the account is credential-encrypted, show notification requesting the user to unlock the * device. */ - private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId) { + private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId, String reason) { final UserInfo user = mUserManager.getUserInfo(userId); if (!user.isManagedProfile()) { // When the user is locked, we communicate it loud-and-clear @@ -659,28 +659,35 @@ public class LockSettingsService extends ILockSettings.Stub { !mUserManager.isQuietModeEnabled(userHandle)) { // Only show notifications for managed profiles once their parent // user is unlocked. - showEncryptionNotificationForProfile(userHandle); + showEncryptionNotificationForProfile(userHandle, reason); } } } - private void showEncryptionNotificationForProfile(UserHandle user) { + private void showEncryptionNotificationForProfile(UserHandle user, String reason) { Resources r = mContext.getResources(); CharSequence title = getEncryptionNotificationTitle(); CharSequence message = getEncryptionNotificationMessage(); CharSequence detail = getEncryptionNotificationDetail(); final KeyguardManager km = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE); - final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, - user.getIdentifier()); + final Intent unlockIntent = + km.createConfirmDeviceCredentialIntent(null, null, user.getIdentifier()); if (unlockIntent == null) { return; } + + // Suppress all notifications on non-FBE devices for now + if (!StorageManager.isFileEncryptedNativeOrEmulated()) return; + unlockIntent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED); + Slog.d(TAG, String.format("showing encryption notification, user: %d; reason: %s", + user.getIdentifier(), reason)); + showEncryptionNotification(user, title, message, detail, intent); } @@ -704,11 +711,6 @@ public class LockSettingsService extends ILockSettings.Stub { private void showEncryptionNotification(UserHandle user, CharSequence title, CharSequence message, CharSequence detail, PendingIntent intent) { - if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier()); - - // Suppress all notifications on non-FBE devices for now - if (!StorageManager.isFileEncryptedNativeOrEmulated()) return; - Notification notification = new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN) .setSmallIcon(com.android.internal.R.drawable.ic_user_secure) @@ -728,7 +730,7 @@ public class LockSettingsService extends ILockSettings.Stub { } private void hideEncryptionNotification(UserHandle userHandle) { - if (DEBUG) Slog.v(TAG, "hide encryption notification, user: " + userHandle.getIdentifier()); + Slog.d(TAG, "hide encryption notification, user: " + userHandle.getIdentifier()); mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION, userHandle); } @@ -746,7 +748,7 @@ public class LockSettingsService extends ILockSettings.Stub { } public void onStartUser(final int userId) { - maybeShowEncryptionNotificationForUser(userId); + maybeShowEncryptionNotificationForUser(userId, "user started"); } /** @@ -1497,7 +1499,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (!alreadyUnlocked) { final long ident = clearCallingIdentity(); try { - maybeShowEncryptionNotificationForUser(profile.id); + maybeShowEncryptionNotificationForUser(profile.id, "parent unlocked"); } finally { restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 5fadd00b77ad..2a66e026438a 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -692,6 +692,20 @@ public class Installer extends SystemService { } } + /** + * Deletes the reference profile with the given name of the given package. + * @throws InstallerException if the deletion fails. + */ + public void deleteReferenceProfile(String packageName, String profileName) + throws InstallerException { + if (!checkBeforeRemote()) return; + try { + mInstalld.deleteReferenceProfile(packageName, profileName); + } catch (Exception e) { + throw InstallerException.from(e); + } + } + public void createUserData(String uuid, int userId, int userSerial, int flags) throws InstallerException { if (!checkBeforeRemote()) return; diff --git a/services/core/java/com/android/server/pm/IntentResolverInterceptor.java b/services/core/java/com/android/server/pm/IntentResolverInterceptor.java index 5597c9af7362..603badb276b2 100644 --- a/services/core/java/com/android/server/pm/IntentResolverInterceptor.java +++ b/services/core/java/com/android/server/pm/IntentResolverInterceptor.java @@ -81,7 +81,7 @@ public final class IntentResolverInterceptor { private void updateUseDelegateChooser() { mUseDelegateChooser = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.USE_DELEGATE_CHOOSER, + SystemUiDeviceConfigFlags.USE_UNBUNDLED_SHARESHEET, false); } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 27c6d9bec2e8..af0a20ddf337 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -324,12 +324,12 @@ public class PackageDexOptimizer { String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter()); // If the app is used by other apps, we must not use the existing profile because it // may contain user data, unless the profile is newly created on install. - final boolean resetProfile = isProfileGuidedCompilerFilter(compilerFilter) + final boolean useCloudProfile = isProfileGuidedCompilerFilter(compilerFilter) && isUsedByOtherApps && options.getCompilationReason() != PackageManagerService.REASON_INSTALL; String dexMetadataPath = null; - if (options.isDexoptInstallWithDexMetadata() || resetProfile) { + if (options.isDexoptInstallWithDexMetadata() || useCloudProfile) { File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(new File(path)); dexMetadataPath = dexMetadataFile == null ? null : dexMetadataFile.getAbsolutePath(); @@ -339,65 +339,87 @@ public class PackageDexOptimizer { // PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA which will be a no-op with respect to // profiles. int profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; - if (resetProfile) { - if (!resetProfile(pkg, profileName, path, dexMetadataPath)) { - // Fall back to use the shared filter. - compilerFilter = - PackageManagerServiceCompilerMapping.getCompilerFilterForReason( - PackageManagerService.REASON_SHARED); - } - } else if (options.isCheckForProfileUpdates()) { + if (options.isCheckForProfileUpdates()) { profileAnalysisResult = analyseProfiles(pkg, sharedGid, profileName, compilerFilter); } - - // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct - // flags. - final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, resetProfile, - options); - - for (String dexCodeIsa : dexCodeInstructionSets) { - int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter, - profileAnalysisResult, classLoaderContexts[i], dexoptFlags, sharedGid, - packageStats, options.isDowngrade(), profileName, dexMetadataPath, - options.getCompilationReason()); - // OTAPreopt doesn't have stats so don't report in that case. - if (packageStats != null) { - Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "dex2oat-metrics"); - try { - long sessionId = sRandom.nextLong(); - ArtStatsLogUtils.writeStatsLog( - mArtStatsLogger, - sessionId, - compilerFilter, - pkg.getUid(), - packageStats.getCompileTime(path), - dexMetadataPath, - options.getCompilationReason(), - newResult, - ArtStatsLogUtils.getApkType(path, pkg.getBaseApkPath(), - pkg.getSplitCodePaths()), - dexCodeIsa, - path); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER); + String cloudProfileName = null; + try { + if (useCloudProfile) { + cloudProfileName = "cloud-" + profileName; + if (prepareCloudProfile(pkg, cloudProfileName, path, dexMetadataPath)) { + profileName = cloudProfileName; + } else { + // Fall back to use the shared filter. + compilerFilter = + PackageManagerServiceCompilerMapping.getCompilerFilterForReason( + PackageManagerService.REASON_SHARED); + profileName = null; } + + // We still run `analyseProfiles` even if `useCloudProfile` is true because it + // merges profiles into the reference profile, which a system API + // `ArtManager.snapshotRuntimeProfile` takes snapshots from. However, we don't + // want the result to affect the decision of whether dexopt is needed. + profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA; } - // Should stop the operation immediately. - if (newResult == DEX_OPT_CANCELLED) { - // Even for the cancellation, return failed if has failed. - if (result == DEX_OPT_FAILED) { - return result; + // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct + // flags. + final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, + useCloudProfile, options); + + for (String dexCodeIsa : dexCodeInstructionSets) { + int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter, + profileAnalysisResult, classLoaderContexts[i], dexoptFlags, sharedGid, + packageStats, options.isDowngrade(), profileName, dexMetadataPath, + options.getCompilationReason()); + // OTAPreopt doesn't have stats so don't report in that case. + if (packageStats != null) { + Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "dex2oat-metrics"); + try { + long sessionId = sRandom.nextLong(); + ArtStatsLogUtils.writeStatsLog( + mArtStatsLogger, + sessionId, + compilerFilter, + pkg.getUid(), + packageStats.getCompileTime(path), + dexMetadataPath, + options.getCompilationReason(), + newResult, + ArtStatsLogUtils.getApkType(path, pkg.getBaseApkPath(), + pkg.getSplitCodePaths()), + dexCodeIsa, + path); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER); + } + } + + // Should stop the operation immediately. + if (newResult == DEX_OPT_CANCELLED) { + // Even for the cancellation, return failed if has failed. + if (result == DEX_OPT_FAILED) { + return result; + } + return newResult; + } + // The end result is: + // - FAILED if any path failed, + // - PERFORMED if at least one path needed compilation, + // - SKIPPED when all paths are up to date + if ((result != DEX_OPT_FAILED) && (newResult != DEX_OPT_SKIPPED)) { + result = newResult; } - return newResult; } - // The end result is: - // - FAILED if any path failed, - // - PERFORMED if at least one path needed compilation, - // - SKIPPED when all paths are up to date - if ((result != DEX_OPT_FAILED) && (newResult != DEX_OPT_SKIPPED)) { - result = newResult; + } finally { + if (cloudProfileName != null) { + try { + mInstaller.deleteReferenceProfile(pkg.getPackageName(), cloudProfileName); + } catch (InstallerException e) { + Slog.w(TAG, "Failed to cleanup cloud profile", e); + } } } } @@ -405,22 +427,25 @@ public class PackageDexOptimizer { } /** - * Resets the profiles of the dex file at {@code path} belonging to the package {@code pkg} to - * the initial state as if the package is newly installed. Returns true on success, or false - * otherwise. + * Creates a profile with the name {@code profileName} from the dex metadata file at {@code + * dexMetadataPath} for the dex file at {@code path} belonging to the package {@code pkg}. + * + * @return true on success, or false otherwise. */ @GuardedBy("mInstallLock") - private boolean resetProfile(AndroidPackage pkg, String profileName, String path, + private boolean prepareCloudProfile(AndroidPackage pkg, String profileName, String path, @Nullable String dexMetadataPath) { if (dexMetadataPath != null) { try { - mInstaller.clearAppProfiles(pkg.getPackageName(), profileName); + // Make sure we don't keep any existing contents. + mInstaller.deleteReferenceProfile(pkg.getPackageName(), profileName); + final int appId = UserHandle.getAppId(pkg.getUid()); - mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL, - appId, profileName, path, dexMetadataPath); + mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL, appId, + profileName, path, dexMetadataPath); return true; } catch (InstallerException e) { - Slog.w(TAG, "Failed to reset profile", e); + Slog.w(TAG, "Failed to prepare cloud profile", e); return false; } } else { @@ -835,16 +860,16 @@ public class PackageDexOptimizer { private int getDexFlags(ApplicationInfo info, String compilerFilter, DexoptOptions options) { return getDexFlags((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0, info.getHiddenApiEnforcementPolicy(), info.splitDependencies, - info.requestsIsolatedSplitLoading(), compilerFilter, false /* resetProfile */, + info.requestsIsolatedSplitLoading(), compilerFilter, false /* useCloudProfile */, options); } private int getDexFlags(AndroidPackage pkg, @NonNull PackageStateInternal pkgSetting, - String compilerFilter, boolean resetProfile, DexoptOptions options) { + String compilerFilter, boolean useCloudProfile, DexoptOptions options) { return getDexFlags(pkg.isDebuggable(), AndroidPackageUtils.getHiddenApiEnforcementPolicy(pkg, pkgSetting), pkg.getSplitDependencies(), pkg.isIsolatedSplitLoading(), compilerFilter, - resetProfile, options); + useCloudProfile, options); } /** @@ -853,15 +878,15 @@ public class PackageDexOptimizer { */ private int getDexFlags(boolean debuggable, int hiddenApiEnforcementPolicy, SparseArray<int[]> splitDependencies, boolean requestsIsolatedSplitLoading, - String compilerFilter, boolean resetProfile, DexoptOptions options) { + String compilerFilter, boolean useCloudProfile, DexoptOptions options) { // Profile guide compiled oat files should not be public unles they are based // on profiles from dex metadata archives. // The flag isDexoptInstallWithDexMetadata applies only on installs when we know that // the user does not have an existing profile. - // The flag resetProfile applies only when the existing profile is already reset. + // The flag useCloudProfile applies only when the cloud profile should be used. boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter); boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata() - || resetProfile; + || useCloudProfile; int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0; // Some apps are executed with restrictions on hidden API usage. If this app is one // of them, pass a flag to dexopt to enable the same restrictions during compilation. diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java index b181cdd92379..baa3a9d85b0a 100644 --- a/services/core/java/com/android/server/pm/RemovePackageHelper.java +++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java @@ -17,6 +17,7 @@ package com.android.server.pm; import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN; +import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static android.os.incremental.IncrementalManager.isIncrementalPath; import static android.os.storage.StorageManager.FLAG_STORAGE_CE; import static android.os.storage.StorageManager.FLAG_STORAGE_DE; @@ -29,6 +30,7 @@ import static com.android.server.pm.PackageManagerService.TAG; import android.annotation.NonNull; import android.content.pm.PackageManager; +import android.os.Trace; import android.os.UserHandle; import android.os.incremental.IncrementalManager; import android.util.Log; @@ -334,10 +336,19 @@ final class RemovePackageHelper { mPm.mSettings.writeKernelMappingLPr(deletedPs); } } + if (removedAppId != -1) { - // A user ID was deleted here. Go through all users and remove it - // from KeyStore. - mAppDataHelper.clearKeystoreData(UserHandle.USER_ALL, removedAppId); + // A user ID was deleted here. Go through all users and remove it from KeyStore. + final int appIdToRemove = removedAppId; + mPm.mInjector.getBackgroundHandler().post(() -> { + try { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, + "clearKeystoreData:" + appIdToRemove); + mAppDataHelper.clearKeystoreData(UserHandle.USER_ALL, appIdToRemove); + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + }); } } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 999428a5f35b..b14214189833 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -4526,6 +4526,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the PowerManager's Notifier thread. @Override + public void onPowerGroupWakefulnessChanged(int groupId, int wakefulness, + @PowerManager.GoToSleepReason int pmSleepReason, int globalWakefulness) { + if (wakefulness != globalWakefulness + && wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE + && groupId == Display.DEFAULT_DISPLAY_GROUP + && mKeyguardDelegate != null) { + mKeyguardDelegate.doKeyguardTimeout(null); + } + } + + // Called on the PowerManager's Notifier thread. + @Override public void startedWakingUp(@PowerManager.WakeReason int pmWakeReason) { EventLogTags.writeScreenToggled(1); if (DEBUG_WAKEUP) { diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 4571cf395287..7ca09ab5154f 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -773,6 +773,20 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { public void finishedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason); /** + * Called when a particular PowerGroup has changed wakefulness. + * + * @param groupId The id of the PowerGroup. + * @param wakefulness One of PowerManagerInternal.WAKEFULNESS_* indicating the wake state for + * the group + * @param pmSleepReason One of PowerManager.GO_TO_SLEEP_REASON_*, detailing the reason this + * group is going to sleep. + * @param globalWakefulness The global wakefulness, which may or may not match that of this + * group. One of PowerManagerInternal.WAKEFULNESS_* + */ + void onPowerGroupWakefulnessChanged(int groupId, int wakefulness, + @PowerManager.GoToSleepReason int pmSleepReason, int globalWakefulness); + + /** * Called when the display is about to turn on to show content. * When waking up, this method will be called once after the call to wakingUp(). * When dozing, the method will be called sometime after the call to goingToSleep() and diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 77d63100032c..aede4b1e2f5d 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -553,6 +553,15 @@ public class Notifier { } /** + * Called when an individual PowerGroup changes wakefulness. + */ + public void onPowerGroupWakefulnessChanged(int groupId, int groupWakefulness, int changeReason, + int globalWakefulness) { + mHandler.post(() -> mPolicy.onPowerGroupWakefulnessChanged(groupId, groupWakefulness, + changeReason, globalWakefulness)); + } + + /** * Called when there has been user activity. */ public void onUserActivity(int displayGroupId, int event, int uid) { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index c04d6082877a..57f13829b557 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -674,6 +674,8 @@ public final class PowerManagerService extends SystemService } mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS; updateGlobalWakefulnessLocked(eventTime, reason, uid, opUid, opPackageName, details); + mNotifier.onPowerGroupWakefulnessChanged(groupId, wakefulness, reason, + getGlobalWakefulnessLocked()); updatePowerStateLocked(); } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 52651b9fd076..62d284ae1aeb 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -53,6 +53,7 @@ import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.View.GONE; +import static android.view.ViewRootImpl.LOCAL_LAYOUT; import static android.view.WindowInsets.Type.displayCutout; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.systemBars; @@ -2647,29 +2648,27 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mCurrentPrivacyIndicatorBounds = mCurrentPrivacyIndicatorBounds.updateStaticBounds(staticBounds); if (!Objects.equals(oldBounds, mCurrentPrivacyIndicatorBounds)) { - final DisplayInfo info = mDisplayInfo; - if (mDisplayFrames.onDisplayInfoUpdated(info, - calculateDisplayCutoutForRotation(info.rotation), - calculateRoundedCornersForRotation(info.rotation), - calculatePrivacyIndicatorBoundsForRotation(info.rotation))) { - mInsetsStateController.onDisplayInfoUpdated(true); - } + updateDisplayFrames(false /* insetsSourceMayChange */, true /* notifyInsetsChange */); } } void onDisplayInfoChanged() { - final DisplayInfo info = mDisplayInfo; - if (mDisplayFrames.onDisplayInfoUpdated(info, - calculateDisplayCutoutForRotation(info.rotation), - calculateRoundedCornersForRotation(info.rotation), - calculatePrivacyIndicatorBoundsForRotation(info.rotation))) { - // TODO(b/161810301): Set notifyInsetsChange to true while the server no longer performs - // layout. - mInsetsStateController.onDisplayInfoUpdated(false /* notifyInsetsChanged */); - } + updateDisplayFrames(LOCAL_LAYOUT, LOCAL_LAYOUT); mMinSizeOfResizeableTaskDp = getMinimalTaskSizeDp(); - mInputMonitor.layoutInputConsumers(info.logicalWidth, info.logicalHeight); - mDisplayPolicy.onDisplayInfoChanged(info); + mInputMonitor.layoutInputConsumers(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + mDisplayPolicy.onDisplayInfoChanged(mDisplayInfo); + } + + private void updateDisplayFrames(boolean insetsSourceMayChange, boolean notifyInsetsChange) { + if (mDisplayFrames.update(mDisplayInfo, + calculateDisplayCutoutForRotation(mDisplayInfo.rotation), + calculateRoundedCornersForRotation(mDisplayInfo.rotation), + calculatePrivacyIndicatorBoundsForRotation(mDisplayInfo.rotation))) { + if (insetsSourceMayChange) { + mDisplayPolicy.updateInsetsSourceFramesExceptIme(mDisplayFrames); + } + mInsetsStateController.onDisplayFramesUpdated(notifyInsetsChange); + } } @Override diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java index 45d7141fd556..76aa7f963aa6 100644 --- a/services/core/java/com/android/server/wm/DisplayFrames.java +++ b/services/core/java/com/android/server/wm/DisplayFrames.java @@ -64,26 +64,26 @@ public class DisplayFrames { PrivacyIndicatorBounds indicatorBounds) { mDisplayId = displayId; mInsetsState = insetsState; - onDisplayInfoUpdated(info, displayCutout, roundedCorners, indicatorBounds); + update(info, displayCutout, roundedCorners, indicatorBounds); } /** - * Update {@link DisplayFrames} when {@link DisplayInfo} is updated. + * This is called when {@link DisplayInfo} or {@link PrivacyIndicatorBounds} is updated. * * @param info the updated {@link DisplayInfo}. * @param displayCutout the updated {@link DisplayCutout}. * @param roundedCorners the updated {@link RoundedCorners}. - * @return {@code true} if the insets state has been changed; {@code false} otherwise. + * @param indicatorBounds the updated {@link PrivacyIndicatorBounds}. + * @return {@code true} if anything has been changed; {@code false} otherwise. */ - public boolean onDisplayInfoUpdated(DisplayInfo info, @NonNull WmDisplayCutout displayCutout, + public boolean update(DisplayInfo info, @NonNull WmDisplayCutout displayCutout, @NonNull RoundedCorners roundedCorners, @NonNull PrivacyIndicatorBounds indicatorBounds) { - mRotation = info.rotation; - final InsetsState state = mInsetsState; final Rect safe = mDisplayCutoutSafe; final DisplayCutout cutout = displayCutout.getDisplayCutout(); if (mDisplayWidth == info.logicalWidth && mDisplayHeight == info.logicalHeight + && mRotation != info.rotation && state.getDisplayCutout().equals(cutout) && state.getRoundedCorners().equals(roundedCorners) && state.getPrivacyIndicatorBounds().equals(indicatorBounds)) { @@ -91,6 +91,7 @@ public class DisplayFrames { } mDisplayWidth = info.logicalWidth; mDisplayHeight = info.logicalHeight; + mRotation = info.rotation; final Rect unrestricted = mUnrestricted; unrestricted.set(0, 0, mDisplayWidth, mDisplayHeight); state.setDisplayFrame(unrestricted); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 4573ede13f7f..3d826bf99df0 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -1498,10 +1498,6 @@ public class DisplayPolicy { } } - // TODO(b/161810301): No one is calling this since we haven't moved window layout to the client. - // When that happens, this should be called when the display rotation is - // changed, so that we can dispatch the correct insets to all the clients - // before the insets source windows report their frames to the server. void updateInsetsSourceFramesExceptIme(DisplayFrames displayFrames) { for (int i = mInsetsSourceWindowsExceptIme.size() - 1; i >= 0; i--) { final WindowState win = mInsetsSourceWindowsExceptIme.valueAt(i); diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index a19d72e37124..ed771c202c04 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -177,7 +177,7 @@ class InsetsStateController { } } - void onDisplayInfoUpdated(boolean notifyInsetsChange) { + void onDisplayFramesUpdated(boolean notifyInsetsChange) { final ArrayList<WindowState> insetsChangedWindows = new ArrayList<>(); mDisplayContent.forAllWindows(w -> { w.mAboveInsetsState.set(mState, displayCutout()); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 4175da89cf8b..7d3c784e4f16 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -278,7 +278,6 @@ import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Build; import android.os.Bundle; -import android.os.CancellationSignal; import android.os.Environment; import android.os.Handler; import android.os.IBinder; @@ -7235,47 +7234,45 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Preconditions.checkState(admin != null, "Lost mode location updates can only be sent on an organization-owned device."); mInjector.binderWithCleanCallingIdentity(() -> { - final List<String> providers = - mInjector.getLocationManager().getAllProviders().stream() - .filter(mInjector.getLocationManager()::isProviderEnabled) - .collect(Collectors.toList()); - if (providers.isEmpty()) { - future.complete(false); - return; - } - - final CancellationSignal cancellationSignal = new CancellationSignal(); - List<String> providersWithNullLocation = new ArrayList<String>(); - for (String provider : providers) { - mInjector.getLocationManager().getCurrentLocation(provider, cancellationSignal, - mContext.getMainExecutor(), location -> { - if (cancellationSignal.isCanceled()) { - return; - } else if (location != null) { - sendLostModeLocationUpdate(admin, location); - cancellationSignal.cancel(); - future.complete(true); - } else { - // location == null, provider wasn't able to get location, see - // if there are more providers - providersWithNullLocation.add(provider); - if (providers.size() == providersWithNullLocation.size()) { - future.complete(false); - } - } - } - ); - } + String[] providers = {LocationManager.FUSED_PROVIDER, + LocationManager.NETWORK_PROVIDER, LocationManager.GPS_PROVIDER}; + tryRetrieveAndSendLocationUpdate(admin, future, providers, /* index= */ 0); }); } } - private void sendLostModeLocationUpdate(ActiveAdmin admin, Location location) { + /** Send lost mode location updates recursively, in order of the list of location providers. */ + private void tryRetrieveAndSendLocationUpdate(ActiveAdmin admin, + AndroidFuture<Boolean> future, String[] providers, int index) { + // None of the providers were able to get location, return false + if (index == providers.length) { + future.complete(false); + return; + } + if (mInjector.getLocationManager().isProviderEnabled(providers[index])) { + mInjector.getLocationManager().getCurrentLocation(providers[index], + /* cancellationSignal= */ null, mContext.getMainExecutor(), location -> { + if (location != null) { + mContext.sendBroadcastAsUser( + newLostModeLocationUpdateIntent(admin, location), + admin.getUserHandle()); + future.complete(true); + } else { + tryRetrieveAndSendLocationUpdate(admin, future, providers, index + 1); + } + } + ); + } else { + tryRetrieveAndSendLocationUpdate(admin, future, providers, index + 1); + } + } + + private Intent newLostModeLocationUpdateIntent(ActiveAdmin admin, Location location) { final Intent intent = new Intent( DevicePolicyManager.ACTION_LOST_MODE_LOCATION_UPDATE); intent.putExtra(DevicePolicyManager.EXTRA_LOST_MODE_LOCATION, location); intent.setPackage(admin.info.getPackageName()); - mContext.sendBroadcastAsUser(intent, admin.getUserHandle()); + return intent; } /** diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java index 04fe777cd909..b354c7b3d1f3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java @@ -116,14 +116,14 @@ public final class JobConcurrencyManagerTest { assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob)); // Pending jobs shouldn't affect TOP job's status. - for (int i = 1; i <= JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i); mPendingJobQueue.add(job); } assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob)); // Already running jobs shouldn't affect TOP job's status. - for (int i = 1; i <= JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE, i); mJobConcurrencyManager.addRunningJobForTesting(job); } @@ -183,9 +183,9 @@ public final class JobConcurrencyManagerTest { spyOn(testEj); doReturn(true).when(testEj).shouldTreatAsExpeditedJob(); - setConcurrencyConfig(JobSchedulerService.MAX_JOB_CONTEXTS_COUNT); + setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT); - for (int i = 0; i < JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i, i + 1); mPendingJobQueue.add(job); } diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt index 1af6fb7a4027..0567f58b1bbe 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt @@ -203,6 +203,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) { val domainVerificationManagerInternal: DomainVerificationManagerInternal = mock() val handler = TestHandler(null) val defaultAppProvider: DefaultAppProvider = mock() + val backgroundHandler = TestHandler(null) } companion object { @@ -286,6 +287,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) { .thenReturn(mocks.domainVerificationManagerInternal) whenever(mocks.injector.handler) { mocks.handler } whenever(mocks.injector.defaultAppProvider) { mocks.defaultAppProvider } + whenever(mocks.injector.backgroundHandler) { mocks.backgroundHandler } wheneverStatic { SystemConfig.getInstance() }.thenReturn(mocks.systemConfig) whenever(mocks.systemConfig.availableFeatures).thenReturn(DEFAULT_AVAILABLE_FEATURES_MAP) whenever(mocks.systemConfig.sharedLibraries).thenReturn(DEFAULT_SHARED_LIBRARIES_LIST) 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 197c21fad74a..ef7aaca203f7 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -48,6 +48,9 @@ import static android.app.admin.DevicePolicyManager.WIFI_SECURITY_PERSONAL; import static android.app.admin.DevicePolicyManager.WIPE_EUICC; import static android.app.admin.PasswordMetrics.computeForPasswordOrPin; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; +import static android.location.LocationManager.FUSED_PROVIDER; +import static android.location.LocationManager.GPS_PROVIDER; +import static android.location.LocationManager.NETWORK_PROVIDER; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK; @@ -8462,34 +8465,44 @@ public class DevicePolicyManagerTest extends DpmTestBase { @Test public void testSendLostModeLocationUpdate_asDeviceOwner() throws Exception { - final String TEST_PROVIDER = "network"; mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE); setDeviceOwner(); - when(getServices().locationManager.getAllProviders()).thenReturn(List.of(TEST_PROVIDER)); - when(getServices().locationManager.isProviderEnabled(TEST_PROVIDER)).thenReturn(true); + when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(true); dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {}); verify(getServices().locationManager, times(1)).getCurrentLocation( - eq(TEST_PROVIDER), any(), eq(getServices().executor), any()); + eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } @Test public void testSendLostModeLocationUpdate_asProfileOwnerOfOrgOwnedDevice() throws Exception { - final String TEST_PROVIDER = "network"; final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE); addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE); - when(getServices().locationManager.getAllProviders()).thenReturn(List.of(TEST_PROVIDER)); - when(getServices().locationManager.isProviderEnabled(TEST_PROVIDER)).thenReturn(true); + when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(true); dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {}); verify(getServices().locationManager, times(1)).getCurrentLocation( - eq(TEST_PROVIDER), any(), eq(getServices().executor), any()); + eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); + } + + @Test + public void testSendLostModeLocationUpdate_noProviderIsEnabled() throws Exception { + mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE); + setDeviceOwner(); + when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(false); + when(getServices().locationManager.isProviderEnabled(NETWORK_PROVIDER)).thenReturn(false); + when(getServices().locationManager.isProviderEnabled(GPS_PROVIDER)).thenReturn(false); + + dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {}); + + verify(getServices().locationManager, never()).getCurrentLocation( + eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { diff --git a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java index bda7cf66f685..e886e7dc1d60 100644 --- a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java +++ b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java @@ -57,14 +57,14 @@ public class BiasSchedulingTest extends AndroidTestCase { } public void testLowerBiasJobPreempted() throws Exception { - for (int i = 0; i < JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent) .setBias(LOW_BIAS) .setOverrideDeadline(0) .build(); mJobScheduler.schedule(job); } - final int higherBiasJobId = 100 + JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; + final int higherBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; JobInfo jobHigher = new JobInfo.Builder(higherBiasJobId, sJobServiceComponent) .setBias(HIGH_BIAS) .setMinimumLatency(2000) @@ -88,14 +88,14 @@ public class BiasSchedulingTest extends AndroidTestCase { } public void testHigherBiasJobNotPreempted() throws Exception { - for (int i = 0; i < JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent) .setBias(HIGH_BIAS) .setOverrideDeadline(0) .build(); mJobScheduler.schedule(job); } - final int lowerBiasJobId = 100 + JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; + final int lowerBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; JobInfo jobLower = new JobInfo.Builder(lowerBiasJobId, sJobServiceComponent) .setBias(LOW_BIAS) .setMinimumLatency(2000) diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index 89450ffbc11d..9f5e79db84c8 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -1697,6 +1697,99 @@ public class PowerManagerServiceTest { } @Test + public void testMultiDisplay_onlyOneDisplaySleeps_onWakefulnessChangedEventFires() { + createService(); + startSystem(); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + forceSleep(); + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_ASLEEP); + + verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP), + eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_ASLEEP)); + } + + @Test + public void testMultiDisplay_bothDisplaysSleep_onWakefulnessChangedEventFiresCorrectly() { + final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; + final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1; + final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = + new AtomicReference<>(); + doAnswer((Answer<Void>) invocation -> { + listener.set(invocation.getArgument(0)); + return null; + }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any()); + final DisplayInfo info = new DisplayInfo(); + info.displayGroupId = nonDefaultDisplayGroupId; + when(mDisplayManagerInternalMock.getDisplayInfo(nonDefaultDisplay)).thenReturn(info); + + createService(); + startSystem(); + + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); + + mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, 0, 0, 0, 0, + null, null); + mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0, + null, null); + + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_ASLEEP); + assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( + WAKEFULNESS_ASLEEP); + + verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(nonDefaultDisplayGroupId), + eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_AWAKE)); + verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP), + eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_ASLEEP)); + } + + @Test + public void testMultiDisplay_separateWakeStates_onWakefulnessChangedEventFiresCorrectly() { + final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; + final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1; + final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = + new AtomicReference<>(); + doAnswer((Answer<Void>) invocation -> { + listener.set(invocation.getArgument(0)); + return null; + }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any()); + final DisplayInfo info = new DisplayInfo(); + info.displayGroupId = nonDefaultDisplayGroupId; + when(mDisplayManagerInternalMock.getDisplayInfo(nonDefaultDisplay)).thenReturn(info); + + createService(); + startSystem(); + + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); + + final String pkg = mContextSpy.getOpPackageName(); + final Binder token = new Binder(); + final String tag = + "testMultiDisplay_separateWakeStates_onWakefulnessChangedEventFiresCorrectly"; + mService.getBinderServiceInstance().acquireWakeLock(token, + PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg, + null /* workSource */, null /* historyTag */, nonDefaultDisplay, null); + + forceSleep(); + + // The wakelock should have kept the second display awake, and we should notify that the + // default display went to sleep. + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_ASLEEP); + assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( + WAKEFULNESS_AWAKE); + verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP), + eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_AWAKE)); + verify(mNotifierMock, never()).onPowerGroupWakefulnessChanged( + eq(nonDefaultDisplayGroupId), anyInt(), anyInt(), anyInt()); + } + + @Test public void testGetFullPowerSavePolicy_returnsStateMachineResult() { createService(); startSystem(); diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java index f570005f99cc..ea98b6b17e83 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -131,6 +131,11 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override + public void onPowerGroupWakefulnessChanged(int groupId, int wakefulness, + @GoToSleepReason int pmSleepReason, int globalWakefulness) { + } + + @Override public void screenTurningOn(int displayId, ScreenOnListener screenOnListener) { } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 8880bc492de7..8d7fab4d101f 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -4379,12 +4379,14 @@ public class CarrierConfigManager { * The data stall recovery timers array in milliseconds, each element is the delay before * performining next recovery action. * - * The default value of timers array are: [180000ms, 180000ms, 180000ms] (3 minutes) + * The default value of timers array are: [180000ms, 180000ms, 180000ms, 180000ms] (3 minutes) * Array[0]: It's the timer between RECOVERY_ACTION GET_DATA_CALL_LIST and CLEANUP, if data * stall symptom still occurred, it will perform next recovery action after 180000ms. - * Array[1]: It's the timer between RECOVERY_ACTION CLEANUP and RADIO_RESTART, if data stall + * Array[1]: It's the timer between RECOVERY_ACTION CLEANUP and RE-REGISTER, if data stall * symptom still occurred, it will perform next recovery action after 180000ms. - * Array[2]: It's the timer between RECOVERY_ACTION RADIO_RESTART and RESET_MODEM, if data stall + * Array[2]: It's the timer between RECOVERY_ACTION RE-REGISTER and RADIO_RESTART, if data stall + * symptom still occurred, it will perform next recovery action after 180000ms. + * Array[3]: It's the timer between RECOVERY_ACTION RADIO_RESTART and RESET_MODEM, if data stall * symptom still occurred, it will perform next recovery action after 180000ms. * * See the {@code RECOVERY_ACTION_*} constants in @@ -4404,7 +4406,7 @@ public class CarrierConfigManager { * RECOVERY_ACTION_CLEANUP to true, then it can be ignored to speed up the recovery * action procedure. * - * The default value of boolean array are: [false, false, false, false] + * The default value of boolean array are: [false, false, true, false, false] * Array[0]: When performing the recovery action, we can use this boolean value to determine * if we need to perform RECOVERY_ACTION_GET_DATA_CALL_LIST. * Array[1]: If data stall symptom still occurred, we can use this boolean value to determine @@ -4414,8 +4416,10 @@ public class CarrierConfigManager { * variable of action RECOVERY_ACTION_CLEANUP to true, then it can be ignored to speed up the * recovery action procedure. * Array[2]: If data stall symptom still occurred, we can use this boolean value to determine - * if we need to perform RECOVERY_ACTION_RADIO_RESTART. + * if we need to perform RE-REGISTER. * Array[3]: If data stall symptom still occurred, we can use this boolean value to determine + * if we need to perform RECOVERY_ACTION_RADIO_RESTART. + * Array[4]: If data stall symptom still occurred, we can use this boolean value to determine * if we need to perform RECOVERY_ACTION_MODEM_RESET. * * See the {@code RECOVERY_ACTION_*} constants in @@ -9159,9 +9163,9 @@ public class CarrierConfigManager { SubscriptionManager.USAGE_SETTING_UNKNOWN); // Default data stall recovery configurations. sDefaults.putLongArray(KEY_DATA_STALL_RECOVERY_TIMERS_LONG_ARRAY, - new long[] {180000, 180000, 180000}); + new long[] {180000, 180000, 180000, 180000}); sDefaults.putBooleanArray(KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY, - new boolean[] {false, false, false, false}); + new boolean[] {false, false, true, false, false}); } /** diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index fc9acb81d408..7c7bf0a21c3f 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -3216,6 +3216,11 @@ public class SubscriptionManager { * * @param subId sub id * @param callbackIntent pending intent that will be sent after operation is done. + * + * to-be-deprecated this API is a duplicate of {@link EuiccManager#switchToSubscription(int, + * PendingIntent)} and does not support Multiple Enabled Profile(MEP). Apps should use + * {@link EuiccManager#switchToSubscription(int, PendingIntent)} or + * {@link EuiccManager#switchToSubscription(int, int, PendingIntent)} instead. */ @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void switchToSubscription(int subId, @NonNull PendingIntent callbackIntent) { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt index a425ee0ed969..d1319ac095ed 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt @@ -17,7 +17,6 @@ package com.android.server.wm.flicker.close -import android.platform.test.annotations.Presubmit import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory @@ -99,38 +98,6 @@ class CloseAppBackButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio super.statusBarLayerRotatesScales() } - /** {@inheritDoc} */ - @Presubmit - @Test - override fun launcherLayerReplacesApp() { - // This test doesn't work in shell transitions because of b/206086894 - assumeFalse(isShellTransitionsEnabled) - super.launcherLayerReplacesApp() - } - - @FlakyTest(bugId = 214452854) - @Test - fun launcherLayerReplacesApp_shellTransit() { - assumeTrue(isShellTransitionsEnabled) - super.launcherLayerReplacesApp() - } - - /** {@inheritDoc} */ - @Presubmit - @Test - override fun entireScreenCovered() { - // This test doesn't work in shell transitions because of b/206086894 - assumeFalse(isShellTransitionsEnabled) - super.entireScreenCovered() - } - - @FlakyTest(bugId = 214452854) - @Test - fun entireScreenCovered_shellTransit() { - assumeTrue(isShellTransitionsEnabled) - super.entireScreenCovered() - } - companion object { /** * Creates the test configurations. diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt index a0892612f4e4..b4dcb43e86a9 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt @@ -16,7 +16,6 @@ package com.android.server.wm.flicker.close -import android.platform.test.annotations.Presubmit import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.FlickerParametersRunnerFactory @@ -98,54 +97,6 @@ class CloseAppHomeButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio super.statusBarLayerRotatesScales() } - /** {@inheritDoc} */ - @Presubmit - @Test - override fun launcherLayerReplacesApp() { - // This test doesn't work in shell transitions because of b/206086894 - assumeFalse(isShellTransitionsEnabled) - super.launcherLayerReplacesApp() - } - - @FlakyTest(bugId = 214452854) - @Test - fun launcherLayerReplacesApp_shellTransit() { - assumeTrue(isShellTransitionsEnabled) - super.launcherLayerReplacesApp() - } - - /** {@inheritDoc} */ - @Presubmit - @Test - override fun entireScreenCovered() { - // This test doesn't work in shell transitions because of b/206086894 - assumeFalse(isShellTransitionsEnabled) - super.entireScreenCovered() - } - - @FlakyTest(bugId = 214452854) - @Test - fun entireScreenCovered_shellTransit() { - assumeTrue(isShellTransitionsEnabled) - super.entireScreenCovered() - } - - /** {@inheritDoc} */ - @Presubmit - @Test - override fun visibleLayersShownMoreThanOneConsecutiveEntry() { - // This test doesn't work in shell transitions because of b/215885246 - assumeFalse(isShellTransitionsEnabled) - super.visibleLayersShownMoreThanOneConsecutiveEntry() - } - - @FlakyTest(bugId = 214452854) - @Test - fun visibleLayersShownMoreThanOneConsecutiveEntry_shellTransit() { - assumeTrue(isShellTransitionsEnabled) - super.visibleLayersShownMoreThanOneConsecutiveEntry() - } - companion object { /** * Creates the test configurations. diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt index f8348203599f..2f6b8f008119 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt @@ -24,11 +24,8 @@ import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.annotation.Group1 import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled import com.android.server.wm.flicker.helpers.setRotation import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome -import org.junit.Assume -import org.junit.Before import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -59,11 +56,6 @@ import org.junit.runners.Parameterized @Group1 open class OpenAppColdTest(testSpec: FlickerTestParameter) : OpenAppFromLauncherTransition(testSpec) { - @Before - open fun before() { - Assume.assumeFalse(isShellTransitionsEnabled) - } - /** * Defines the transition used to run the test */ @@ -121,7 +113,7 @@ open class OpenAppColdTest(testSpec: FlickerTestParameter) override fun navBarWindowIsVisible() = super.navBarWindowIsVisible() /** {@inheritDoc} */ - @FlakyTest(bugId = 213852103) + @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest_ShellTransit.kt deleted file mode 100644 index 0d2869cbd178..000000000000 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest_ShellTransit.kt +++ /dev/null @@ -1,60 +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.server.wm.flicker.launch - -import androidx.test.filters.FlakyTest -import android.platform.test.annotations.RequiresDevice -import com.android.server.wm.flicker.FlickerParametersRunnerFactory -import com.android.server.wm.flicker.FlickerTestParameter -import com.android.server.wm.flicker.annotation.Group1 -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before -import org.junit.FixMethodOrder -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test cold launching an app from launcher - * - * To run this test: `atest FlickerTests:OpenAppColdTest` - * - * Actions: - * Make sure no apps are running on the device - * Launch an app [testApp] and wait animation to complete - * - * Notes: - * 1. Some default assertions (e.g., nav bar, status bar and screen covered) - * are inherited [OpenAppTransition] - * 2. Part of the test setup occurs automatically via - * [com.android.server.wm.flicker.TransitionRunnerWithRules], - * including configuring navigation mode, initial orientation and ensuring no - * apps are running before setup - */ -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Group1 -@FlakyTest(bugId = 219688533) -class OpenAppColdTest_ShellTransit(testSpec: FlickerTestParameter) : OpenAppColdTest(testSpec) { - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } -} diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt index 00fee82adf76..ee0f3d8cd945 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt @@ -135,7 +135,7 @@ open class OpenAppFromOverviewTest(testSpec: FlickerTestParameter) override fun appLayerBecomesVisible() = super.appLayerBecomesVisible_warmStart() /** {@inheritDoc} */ - @FlakyTest(bugId = 218624176) + @Presubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible_warmStart() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest_ShellTransit.kt index 1c06495cf473..55e1e9ba8557 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest_ShellTransit.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest_ShellTransit.kt @@ -54,7 +54,6 @@ import org.junit.runners.Parameterized @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group1 -@FlakyTest(bugId = 219688533) class OpenAppFromOverviewTest_ShellTransit(testSpec: FlickerTestParameter) : OpenAppFromOverviewTest(testSpec) { @Before @@ -65,6 +64,11 @@ class OpenAppFromOverviewTest_ShellTransit(testSpec: FlickerTestParameter) /** {@inheritDoc} */ @FlakyTest(bugId = 216266712) @Test + override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow() + + /** {@inheritDoc} */ + @FlakyTest(bugId = 216266712) + @Test override fun appWindowReplacesLauncherAsTopWindow() = super.appWindowReplacesLauncherAsTopWindow() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt index 2562098a10ff..48f6aeb4d824 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt @@ -24,10 +24,7 @@ import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.annotation.Group1 import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled import com.android.server.wm.flicker.helpers.setRotation -import org.junit.Assume -import org.junit.Before import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -59,11 +56,6 @@ import org.junit.runners.Parameterized @Group1 open class OpenAppWarmTest(testSpec: FlickerTestParameter) : OpenAppFromLauncherTransition(testSpec) { - @Before - open fun before() { - Assume.assumeFalse(isShellTransitionsEnabled) - } - /** * Defines the transition used to run the test */ diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest_ShellTransit.kt deleted file mode 100644 index 3958dd2c89b4..000000000000 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest_ShellTransit.kt +++ /dev/null @@ -1,62 +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.server.wm.flicker.launch - -import androidx.test.filters.FlakyTest -import android.platform.test.annotations.RequiresDevice -import com.android.server.wm.flicker.FlickerParametersRunnerFactory -import com.android.server.wm.flicker.FlickerTestParameter -import com.android.server.wm.flicker.annotation.Group1 -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before -import org.junit.FixMethodOrder -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test warm launching an app from launcher - * - * To run this test: `atest FlickerTests:OpenAppWarmTest` - * - * Actions: - * Launch [testApp] - * Press home - * Relaunch an app [testApp] and wait animation to complete (only this action is traced) - * - * Notes: - * 1. Some default assertions (e.g., nav bar, status bar and screen covered) - * are inherited [OpenAppTransition] - * 2. Part of the test setup occurs automatically via - * [com.android.server.wm.flicker.TransitionRunnerWithRules], - * including configuring navigation mode, initial orientation and ensuring no - * apps are running before setup - */ -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Group1 -@FlakyTest(bugId = 219688533) -class OpenAppWarmTest_ShellTransit(testSpec: FlickerTestParameter) - : OpenAppWarmTest(testSpec) { - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } -} diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt index c89e6a44ab6c..1eb3d8da9f1e 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt @@ -33,15 +33,12 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.NonResizeableAppHelper import com.android.server.wm.flicker.helpers.SimpleAppHelper import com.android.server.wm.flicker.helpers.WindowUtils -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled import com.android.server.wm.flicker.navBarLayerIsVisible import com.android.server.wm.flicker.navBarLayerRotatesAndScales import com.android.server.wm.flicker.navBarWindowIsVisible import com.android.server.wm.flicker.statusBarLayerIsVisible import com.android.server.wm.flicker.statusBarWindowIsVisible import com.android.server.wm.traces.common.FlickerComponentName -import org.junit.Assume -import org.junit.Before import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -73,11 +70,6 @@ open class QuickSwitchBetweenTwoAppsBackTest(private val testSpec: FlickerTestPa private val startDisplayBounds = WindowUtils.getDisplayBounds(testSpec.startRotation) - @Before - open fun before() { - Assume.assumeFalse(isShellTransitionsEnabled) - } - @FlickerBuilderProvider fun buildFlicker(): FlickerBuilder { return FlickerBuilder(instrumentation).apply { diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt deleted file mode 100644 index cffed81f6cb9..000000000000 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm.flicker.quickswitch - -import androidx.test.filters.FlakyTest -import android.platform.test.annotations.RequiresDevice -import com.android.server.wm.flicker.FlickerParametersRunnerFactory -import com.android.server.wm.flicker.FlickerTestParameter -import com.android.server.wm.flicker.annotation.Group1 -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before -import org.junit.FixMethodOrder -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test quick switching back to previous app from last opened app - * - * To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsBackTest` - * - * Actions: - * Launch an app [testApp1] - * Launch another app [testApp2] - * Swipe right from the bottom of the screen to quick switch back to the first app [testApp1] - * - */ -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Group1 -@FlakyTest(bugId = 219690120) -class QuickSwitchBetweenTwoAppsBackTest_ShellTransit(testSpec: FlickerTestParameter) - : QuickSwitchBetweenTwoAppsBackTest(testSpec) { - @Before - override fun before() { - Assume.assumeTrue(isShellTransitionsEnabled) - } -} diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt index b449dd227ad3..5474a42ccf52 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt @@ -32,7 +32,6 @@ import com.android.server.wm.flicker.annotation.Group1 import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.NonResizeableAppHelper import com.android.server.wm.flicker.helpers.SimpleAppHelper -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled import com.android.server.wm.flicker.navBarLayerIsVisible import com.android.server.wm.flicker.navBarLayerRotatesAndScales import com.android.server.wm.flicker.navBarWindowIsVisible @@ -40,8 +39,6 @@ import com.android.server.wm.flicker.statusBarLayerIsVisible import com.android.server.wm.flicker.statusBarWindowIsVisible import com.android.server.wm.traces.common.FlickerComponentName import com.android.server.wm.traces.common.Rect -import org.junit.Assume -import org.junit.Before import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -114,12 +111,6 @@ open class QuickSwitchBetweenTwoAppsForwardTest(private val testSpec: FlickerTes } } - @Before - open fun setup() { - // This test doesn't work in shell transitions because of b/213867585 - Assume.assumeFalse(isShellTransitionsEnabled) - } - /** * Checks that the transition starts with [testApp1]'s windows filling/covering exactly the * entirety of the display. diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt deleted file mode 100644 index 49b973390e7c..000000000000 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm.flicker.quickswitch - -import android.platform.test.annotations.RequiresDevice -import androidx.test.filters.FlakyTest -import com.android.server.wm.flicker.FlickerParametersRunnerFactory -import com.android.server.wm.flicker.FlickerTestParameter -import com.android.server.wm.flicker.annotation.Group1 -import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled -import org.junit.Assume -import org.junit.Before -import org.junit.FixMethodOrder -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test quick switching back to previous app from last opened app - * - * To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsForwardTestShellTransit` - * - * Actions: - * Launch an app [testApp1] - * Launch another app [testApp2] - * Swipe right from the bottom of the screen to quick switch back to the first app [testApp1] - * Swipe left from the bottom of the screen to quick switch forward to the second app [testApp2] - */ -@RequiresDevice -@RunWith(Parameterized::class) -@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -@Group1 -class QuickSwitchBetweenTwoAppsForwardTestShellTransit(private val testSpec: FlickerTestParameter) - : QuickSwitchBetweenTwoAppsForwardTest(testSpec) { - - @Before - override fun setup() { - // This test class should be removed after b/213867585 is fixed. - Assume.assumeTrue(isShellTransitionsEnabled) - } - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun startsWithApp1WindowsCoverFullScreen() = - super.startsWithApp1WindowsCoverFullScreen() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun startsWithApp1LayersCoverFullScreen() = super.startsWithApp1LayersCoverFullScreen() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun startsWithApp1WindowBeingOnTop() = super.startsWithApp1WindowBeingOnTop() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun endsWithApp2WindowsCoveringFullScreen() = - super.endsWithApp2WindowsCoveringFullScreen() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun endsWithApp2LayersCoveringFullScreen() = - super.endsWithApp2LayersCoveringFullScreen() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun endsWithApp2BeingOnTop() = super.endsWithApp2BeingOnTop() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun app2WindowBecomesAndStaysVisible() = super.app2WindowBecomesAndStaysVisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun app2LayerBecomesAndStaysVisible() = super.app2LayerBecomesAndStaysVisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun app1WindowBecomesAndStaysInvisible() = super.app1WindowBecomesAndStaysInvisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun app1LayerBecomesAndStaysInvisible() = super.app1LayerBecomesAndStaysInvisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun app2WindowIsVisibleOnceApp1WindowIsInvisible() = - super.app2WindowIsVisibleOnceApp1WindowIsInvisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun app2LayerIsVisibleOnceApp1LayerIsInvisible() = - super.app2LayerIsVisibleOnceApp1LayerIsInvisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun navBarLayerAlwaysIsVisible() = super.navBarLayerAlwaysIsVisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun navbarIsAlwaysInRightPosition() = super.navbarIsAlwaysInRightPosition() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible() - - /** {@inheritDoc} */ - @FlakyTest(bugId = 214452854) - @Test - override fun statusBarLayerIsAlwaysVisible() = super.statusBarLayerIsAlwaysVisible() -}
\ No newline at end of file |