Merge "Fix PipRotation tests"
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
new file mode 100644
index 0000000..687693c
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
@@ -0,0 +1,312 @@
+/*
+ * 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.server.job.controllers;
+
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.NonNull;
+import android.app.job.JobInfo;
+import android.content.Context;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.JobSchedulerBackgroundThread;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.utils.AlarmQueue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Controller that tracks the number of flexible constraints being actively satisfied.
+ * Drops constraint for TOP apps and lowers number of required constraints with time.
+ *
+ * TODO: Plug in to other controllers (b/239047584), handle prefetch (b/238887951)
+ */
+public final class FlexibilityController extends StateController {
+ /**
+ * List of all potential flexible constraints
+ */
+ @VisibleForTesting
+ static final int FLEXIBLE_CONSTRAINTS = JobStatus.CONSTRAINT_BATTERY_NOT_LOW
+ | JobStatus.CONSTRAINT_CHARGING
+ | JobStatus.CONSTRAINT_CONNECTIVITY
+ | JobStatus.CONSTRAINT_IDLE;
+
+ /** Hard cutoff to remove flexible constraints */
+ private static final long DEADLINE_PROXIMITY_LIMIT_MS = 15 * MINUTE_IN_MILLIS;
+
+ /**
+ * Keeps track of what flexible constraints are satisfied at the moment.
+ * Is updated by the other controllers.
+ */
+ private int mSatisfiedFlexibleConstraints;
+
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ final FlexibilityTracker mFlexibilityTracker;
+
+ private final FlexibilityAlarmQueue mFlexibilityAlarmQueue;
+ private final long mMinTimeBetweenAlarmsMs = MINUTE_IN_MILLIS;
+
+ /**
+ * The percent of a Jobs lifecycle to drop number of required constraints.
+ * mPercentToDropConstraints[i] denotes that at x% of a Jobs lifecycle,
+ * the controller should have i+1 constraints dropped.
+ */
+ private final int[] mPercentToDropConstraints = {50, 60, 70, 80};
+
+ /** The default deadline that all flexible constraints should be dropped by. */
+ private final long mDefaultFlexibleDeadline = 72 * HOUR_IN_MILLIS;
+
+ public FlexibilityController(JobSchedulerService service) {
+ super(service);
+ mFlexibilityTracker = new FlexibilityTracker(FLEXIBLE_CONSTRAINTS);
+ mFlexibilityAlarmQueue = new FlexibilityAlarmQueue(
+ mContext, JobSchedulerBackgroundThread.get().getLooper());
+ }
+
+ /**
+ * StateController interface
+ */
+ @Override
+ public void maybeStartTrackingJobLocked(JobStatus js, JobStatus lastJob) {
+ if (js.hasFlexibilityConstraint()) {
+ mFlexibilityTracker.add(js);
+ js.setTrackingController(JobStatus.TRACKING_FLEXIBILITY);
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
+ mFlexibilityAlarmQueue.addAlarm(js, getNextConstraintDropTimeElapsed(js));
+ }
+ }
+
+ @Override
+ public void maybeStopTrackingJobLocked(JobStatus js, JobStatus incomingJob, boolean forUpdate) {
+ if (js.clearTrackingController(JobStatus.TRACKING_FLEXIBILITY)) {
+ mFlexibilityAlarmQueue.removeAlarmForKey(js);
+ mFlexibilityTracker.remove(js);
+ }
+ }
+
+ /** Checks if the flexibility constraint is actively satisfied for a given job. */
+ @VisibleForTesting
+ boolean isFlexibilitySatisfiedLocked(JobStatus js) {
+ synchronized (mLock) {
+ return mService.getUidBias(js.getUid()) == JobInfo.BIAS_TOP_APP
+ || mService.isCurrentlyRunningLocked(js)
+ || getNumSatisfiedRequiredConstraintsLocked(js)
+ >= js.getNumRequiredFlexibleConstraints();
+ }
+ }
+
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ int getNumSatisfiedRequiredConstraintsLocked(JobStatus js) {
+ return Integer.bitCount(js.getFlexibleConstraints() & mSatisfiedFlexibleConstraints);
+ }
+
+ /**
+ * Sets the controller's constraint to a given state.
+ * Changes flexibility constraint satisfaction for affected jobs.
+ */
+ @VisibleForTesting
+ void setConstraintSatisfied(int constraint, boolean state) {
+ synchronized (mLock) {
+ final boolean old = (mSatisfiedFlexibleConstraints & constraint) != 0;
+ if (old == state) {
+ return;
+ }
+
+ final int prevSatisfied = Integer.bitCount(mSatisfiedFlexibleConstraints);
+ mSatisfiedFlexibleConstraints =
+ (mSatisfiedFlexibleConstraints & ~constraint) | (state ? constraint : 0);
+ final int curSatisfied = Integer.bitCount(mSatisfiedFlexibleConstraints);
+
+ // Only the max of the number of required flexible constraints will need to be updated
+ // The rest did not have a change in state and are still satisfied or unsatisfied.
+ final int numConstraintsToUpdate = Math.max(curSatisfied, prevSatisfied);
+
+ final ArraySet<JobStatus> jobs = mFlexibilityTracker.getJobsByNumRequiredConstraints(
+ numConstraintsToUpdate);
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+
+ for (int i = 0; i < jobs.size(); i++) {
+ JobStatus js = jobs.valueAt(i);
+ js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
+ }
+ }
+ }
+
+ /** Checks if the given constraint is satisfied in the flexibility controller. */
+ @VisibleForTesting
+ boolean isConstraintSatisfied(int constraint) {
+ return (mSatisfiedFlexibleConstraints & constraint) != 0;
+ }
+
+ /** The elapsed time that marks when the next constraint should be dropped. */
+ @VisibleForTesting
+ @ElapsedRealtimeLong
+ long getNextConstraintDropTimeElapsed(JobStatus js) {
+ final long earliest = js.getEarliestRunTime() == JobStatus.NO_EARLIEST_RUNTIME
+ ? js.enqueueTime : js.getEarliestRunTime();
+ final long latest = js.getLatestRunTimeElapsed() == JobStatus.NO_LATEST_RUNTIME
+ ? earliest + mDefaultFlexibleDeadline
+ : js.getLatestRunTimeElapsed();
+ final int percent = mPercentToDropConstraints[js.getNumDroppedFlexibleConstraints()];
+ final long percentInTime = ((latest - earliest) * percent) / 100;
+ return earliest + percentInTime;
+ }
+
+ @Override
+ @GuardedBy("mLock")
+ public void onUidBiasChangedLocked(int uid, int prevBias, int newBias) {
+ if (prevBias != JobInfo.BIAS_TOP_APP && newBias != JobInfo.BIAS_TOP_APP) {
+ return;
+ }
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ List<JobStatus> jobsByUid = mService.getJobStore().getJobsByUid(uid);
+ for (int i = 0; i < jobsByUid.size(); i++) {
+ JobStatus js = jobsByUid.get(i);
+ if (js.hasFlexibilityConstraint()) {
+ js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
+ }
+ }
+ }
+
+ @VisibleForTesting
+ class FlexibilityTracker {
+ final ArrayList<ArraySet<JobStatus>> mTrackedJobs;
+
+ FlexibilityTracker(int flexibleConstraints) {
+ mTrackedJobs = new ArrayList<>();
+ int numFlexibleConstraints = Integer.bitCount(flexibleConstraints);
+ for (int i = 0; i <= numFlexibleConstraints; i++) {
+ mTrackedJobs.add(new ArraySet<JobStatus>());
+ }
+ }
+
+ /** Gets every tracked job with a given number of required constraints. */
+ public ArraySet<JobStatus> getJobsByNumRequiredConstraints(int numRequired) {
+ return mTrackedJobs.get(numRequired - 1);
+ }
+
+ /** adds a JobStatus object based on number of required flexible constraints. */
+ public void add(JobStatus js) {
+ if (js.getNumRequiredFlexibleConstraints() <= 0) {
+ return;
+ }
+ mTrackedJobs.get(js.getNumRequiredFlexibleConstraints() - 1).add(js);
+ }
+
+ /** Removes a JobStatus object. */
+ public void remove(JobStatus js) {
+ if (js.getNumRequiredFlexibleConstraints() == 0) {
+ return;
+ }
+ mTrackedJobs.get(js.getNumRequiredFlexibleConstraints() - 1).remove(js);
+ }
+
+ /** Returns all tracked jobs. */
+ public ArrayList<ArraySet<JobStatus>> getArrayList() {
+ return mTrackedJobs;
+ }
+
+ /**
+ * Adjusts number of required flexible constraints and sorts it into the tracker.
+ * Returns false if the job status's number of flexible constraints is now 0.
+ * Jobs with 0 required flexible constraints are removed from the tracker.
+ */
+ public boolean adjustJobsRequiredConstraints(JobStatus js, int n) {
+ remove(js);
+ js.adjustNumRequiredFlexibleConstraints(n);
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
+ if (js.getNumRequiredFlexibleConstraints() <= 0) {
+ maybeStopTrackingJobLocked(js, null, false);
+ return false;
+ }
+ add(js);
+ return true;
+ }
+
+ public void dump(IndentingPrintWriter pw, Predicate<JobStatus> predicate) {
+ for (int i = 0; i < mTrackedJobs.size(); i++) {
+ ArraySet<JobStatus> jobs = mTrackedJobs.get(i);
+ for (int j = 0; j < mTrackedJobs.size(); j++) {
+ final JobStatus js = jobs.valueAt(j);
+ if (!predicate.test(js)) {
+ continue;
+ }
+ pw.print("#");
+ js.printUniqueId(pw);
+ pw.print(" from ");
+ UserHandle.formatUid(pw, js.getSourceUid());
+ pw.println();
+ }
+ }
+ }
+ }
+
+ private class FlexibilityAlarmQueue extends AlarmQueue<JobStatus> {
+ private FlexibilityAlarmQueue(Context context, Looper looper) {
+ super(context, looper, "*job.flexibility_check*",
+ "Flexible Constraint Check", false, mMinTimeBetweenAlarmsMs);
+ }
+
+ @Override
+ protected boolean isForUser(@NonNull JobStatus js, int userId) {
+ return js.getSourceUserId() == userId;
+ }
+
+ @Override
+ protected void processExpiredAlarms(@NonNull ArraySet<JobStatus> expired) {
+ synchronized (mLock) {
+ JobStatus js;
+ for (int i = 0; i < expired.size(); i++) {
+ js = expired.valueAt(i);
+ long time = getNextConstraintDropTimeElapsed(js);
+ if (js.getLatestRunTimeElapsed() - time < DEADLINE_PROXIMITY_LIMIT_MS) {
+ mFlexibilityTracker.adjustJobsRequiredConstraints(js,
+ -js.getNumRequiredFlexibleConstraints());
+ continue;
+ }
+ if (mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1)) {
+ mFlexibilityAlarmQueue.addAlarm(js, time);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ @GuardedBy("mLock")
+ public void dumpControllerStateLocked(IndentingPrintWriter pw, Predicate<JobStatus> predicate) {
+ pw.println("# Constraints Satisfied: " + Integer.bitCount(mSatisfiedFlexibleConstraints));
+ pw.println();
+
+ mFlexibilityTracker.dump(pw, predicate);
+ }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index e0f58e3..41cf4212 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -16,6 +16,9 @@
package com.android.server.job.controllers;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+
import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
import static com.android.server.job.JobSchedulerService.EXEMPTED_INDEX;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
@@ -99,6 +102,7 @@
static final int CONSTRAINT_WITHIN_QUOTA = 1 << 24; // Implicit constraint
static final int CONSTRAINT_PREFETCH = 1 << 23;
static final int CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 1 << 22; // Implicit constraint
+ static final int CONSTRAINT_FLEXIBLE = 1 << 21; // Implicit constraint
// The following set of dynamic constraints are for specific use cases (as explained in their
// relative naming and comments). Right now, they apply different constraints, which is fine,
@@ -118,6 +122,22 @@
| CONSTRAINT_IDLE;
/**
+ * The set of constraints that are required to satisfy flexible constraints.
+ * Constraints explicitly requested by the job will not be added to the set.
+ */
+ private int mFlexibleConstraints;
+
+ /**
+ * Keeps track of how many flexible constraints must be satisfied for the job to execute.
+ */
+ private int mNumRequiredFlexibleConstraints;
+
+ /**
+ * Number of required flexible constraints that have been dropped.
+ */
+ private int mNumDroppedFlexibleConstraints;
+
+ /**
* The additional set of dynamic constraints that must be met if this is an expedited job that
* had a long enough run while the device was Dozing or in battery saver.
*/
@@ -305,6 +325,12 @@
public static final int TRACKING_QUOTA = 1 << 6;
/**
+ * Flag for {@link #trackingControllers}: the flexibility controller is currently tracking this
+ * job.
+ */
+ public static final int TRACKING_FLEXIBILITY = 1 << 7;
+
+ /**
* Bit mask of controllers that are currently tracking the job.
*/
private int trackingControllers;
@@ -318,6 +344,8 @@
*/
public static final int INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION = 1 << 0;
+ /** Minimum difference between start and end time to have flexible constraint */
+ private static final long MIN_WINDOW_FOR_FLEXIBILITY_MS = HOUR_IN_MILLIS;
/**
* Versatile, persistable flags for a job that's updated within the system server,
* as opposed to {@link JobInfo#flags} that's set by callers.
@@ -525,6 +553,33 @@
}
}
mHasExemptedMediaUrisOnly = exemptedMediaUrisOnly;
+
+ if (isRequestedExpeditedJob()
+ || ((latestRunTimeElapsedMillis - earliestRunTimeElapsedMillis)
+ < MIN_WINDOW_FOR_FLEXIBILITY_MS)
+ || job.isPrefetch()) {
+ mFlexibleConstraints = 0;
+ } else {
+ if ((requiredConstraints & CONSTRAINT_CHARGING) == 0) {
+ mFlexibleConstraints |= CONSTRAINT_CHARGING;
+ }
+ if ((requiredConstraints & CONSTRAINT_BATTERY_NOT_LOW) == 0) {
+ mFlexibleConstraints |= CONSTRAINT_BATTERY_NOT_LOW;
+ }
+ if ((requiredConstraints & CONSTRAINT_IDLE) == 0) {
+ mFlexibleConstraints |= CONSTRAINT_IDLE;
+ }
+ if (job.getRequiredNetwork() != null
+ && !job.getRequiredNetwork().hasCapability(NET_CAPABILITY_NOT_METERED)) {
+ mFlexibleConstraints |= CONSTRAINT_CONNECTIVITY;
+ }
+ }
+ if (mFlexibleConstraints != 0) {
+ // TODO(b/239047584): Uncomment once Flexibility Controller is plugged in.
+ // requiredConstraints |= CONSTRAINT_FLEXIBLE;
+ mNumRequiredFlexibleConstraints = Integer.bitCount(mFlexibleConstraints);
+ }
+
this.requiredConstraints = requiredConstraints;
mRequiredConstraintsOfInterest = requiredConstraints & CONSTRAINTS_OF_INTEREST;
addDynamicConstraints(dynamicConstraints);
@@ -1082,12 +1137,35 @@
return hasConstraint(CONSTRAINT_IDLE);
}
+ /** Returns true if the job has a prefetch constraint */
+ public boolean hasPrefetchConstraint() {
+ return hasConstraint(CONSTRAINT_PREFETCH);
+ }
+
public boolean hasContentTriggerConstraint() {
// No need to check mDynamicConstraints since content trigger will only be in that list if
// it's already in the requiredConstraints list.
return (requiredConstraints&CONSTRAINT_CONTENT_TRIGGER) != 0;
}
+ /** Returns true if the job has flexible job constraints enabled */
+ public boolean hasFlexibilityConstraint() {
+ return (requiredConstraints & CONSTRAINT_FLEXIBLE) != 0;
+ }
+
+ /** Returns the number of flexible job constraints required to be satisfied to execute */
+ public int getNumRequiredFlexibleConstraints() {
+ return mNumRequiredFlexibleConstraints;
+ }
+
+ /**
+ * Returns the number of required flexible job constraints that have been dropped with time.
+ * The lower this number is the easier it is for the flexibility constraint to be satisfied.
+ */
+ public int getNumDroppedFlexibleConstraints() {
+ return mNumDroppedFlexibleConstraints;
+ }
+
/**
* Checks both {@link #requiredConstraints} and {@link #mDynamicConstraints} to see if this job
* requires the specified constraint.
@@ -1128,6 +1206,10 @@
return mOriginalLatestRunTimeElapsedMillis;
}
+ public int getFlexibleConstraints() {
+ return mFlexibleConstraints;
+ }
+
public void setOriginalLatestRunTimeElapsed(long latestRunTimeElapsed) {
mOriginalLatestRunTimeElapsedMillis = latestRunTimeElapsed;
}
@@ -1301,6 +1383,11 @@
return false;
}
+ /** @return true if the constraint was changed, false otherwise. */
+ boolean setFlexibilityConstraintSatisfied(final long nowElapsed, boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_FLEXIBLE, nowElapsed, state);
+ }
+
/**
* Sets whether or not this job is approved to be treated as an expedited job based on quota
* policy.
@@ -1490,6 +1577,18 @@
trackingControllers |= which;
}
+ /** Adjusts the number of required flexible constraints by the given number */
+ public void adjustNumRequiredFlexibleConstraints(int adjustment) {
+ mNumRequiredFlexibleConstraints += adjustment;
+ if (mNumRequiredFlexibleConstraints < 0) {
+ mNumRequiredFlexibleConstraints = 0;
+ }
+ mNumDroppedFlexibleConstraints -= adjustment;
+ if (mNumDroppedFlexibleConstraints < 0) {
+ mNumDroppedFlexibleConstraints = 0;
+ }
+ }
+
/**
* Add additional constraints to prevent this job from running when doze or battery saver are
* active.
@@ -1650,12 +1749,14 @@
/** All constraints besides implicit and deadline. */
static final int CONSTRAINTS_OF_INTEREST = CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW
| CONSTRAINT_STORAGE_NOT_LOW | CONSTRAINT_TIMING_DELAY | CONSTRAINT_CONNECTIVITY
- | CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER | CONSTRAINT_PREFETCH;
+ | CONSTRAINT_IDLE | CONSTRAINT_CONTENT_TRIGGER | CONSTRAINT_PREFETCH
+ | CONSTRAINT_FLEXIBLE;
// Soft override covers all non-"functional" constraints
static final int SOFT_OVERRIDE_CONSTRAINTS =
CONSTRAINT_CHARGING | CONSTRAINT_BATTERY_NOT_LOW | CONSTRAINT_STORAGE_NOT_LOW
- | CONSTRAINT_TIMING_DELAY | CONSTRAINT_IDLE | CONSTRAINT_PREFETCH;
+ | CONSTRAINT_TIMING_DELAY | CONSTRAINT_IDLE | CONSTRAINT_PREFETCH
+ | CONSTRAINT_FLEXIBLE;
/** Returns true whenever all dynamically set constraints are satisfied. */
public boolean areDynamicConstraintsSatisfied() {
diff --git a/core/java/android/app/timedetector/TimeDetectorHelper.java b/core/java/android/app/timedetector/TimeDetectorHelper.java
new file mode 100644
index 0000000..8752ee0
--- /dev/null
+++ b/core/java/android/app/timedetector/TimeDetectorHelper.java
@@ -0,0 +1,158 @@
+/*
+ * 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 android.app.timedetector;
+
+import android.annotation.NonNull;
+import android.os.Build;
+
+import java.time.Instant;
+
+/**
+ * A utility class for fundamental time detector-related logic that doesn't need to communicate with
+ * the time detector service, i.e. because it can use SDK APIs or hard-coded facts, and doesn't need
+ * permissions or singleton state. Putting logic here avoids the need to expose binder-based calls
+ * or to duplicate code to share related logic (since android.app.timedetector classes are visible
+ * to all processes).
+ *
+ * @hide
+ */
+// Not final for easy replacement / mocking during tests.
+public class TimeDetectorHelper {
+
+ /**
+ * See {@link #getManualDateSelectionYearMin()}. Chosen to produce Unix epoch times be greater
+ * than {@link #MANUAL_SUGGESTION_LOWER_BOUND}.
+ */
+ private static final int MANUAL_SUGGESTION_YEAR_MIN = 2008;
+
+ /**
+ * The maximum gregorian calendar year to allow for manual date selection on devices unlikely to
+ * have Y2038 issues. This serves as a sensible UI-enforced limit though the system server may
+ * support a larger upper bound. Users besides future archeologists are unlikely to need higher
+ * values, for a few years at least.
+ */
+ private static final int MANUAL_SUGGESTION_YEAR_MAX_WITHOUT_Y2038_ISSUE = 2100;
+
+ /**
+ * The maximum gregorian calendar year to allow for manual date selection on devices that may
+ * have Y2038 issues. This serves as a sensible UI-enforced limit though the system server may
+ * support a larger upper bound. That is, the signed 32-bit milliseconds value is
+ * 03:14:07 UTC on 19 January 2038, but this constant means users can only enter dates up to
+ * 2037-12-31. See {@link #MANUAL_SUGGESTION_YEAR_MAX_WITH_Y2038_ISSUE}.
+ *
+ * <p>Note: This UI limit also doesn't prevent devices reaching the Y2038 roll-over time through
+ * the natural passage of time, it just prevents users potentially causing issues in the years
+ * leading up to it accidentally via the UI.
+ */
+ private static final int MANUAL_SUGGESTION_YEAR_MAX_WITH_Y2038_ISSUE = 2037;
+
+ /**
+ * The upper bound for valid suggestions when the Y2038 issue is a risk. This is the instant
+ * when the Y2038 issue occurs.
+ */
+ private static final Instant SUGGESTION_UPPER_BOUND_WITH_Y2038_ISSUE =
+ Instant.ofEpochMilli(1000L * Integer.MAX_VALUE);
+
+ /**
+ * The upper bound for valid suggestions when the Y2038 issue is not a risk. This values means
+ * there is no practical upper bound.
+ *
+ * <p>Make sure this value remains in the value representable as a signed int64 Unix epoch
+ * millis value as in various places {@link Instant#toEpochMilli()} is called, and that throws
+ * an exception if the value is too large.
+ */
+ private static final Instant SUGGESTION_UPPER_BOUND_WIITHOUT_Y2038_ISSUE =
+ Instant.ofEpochMilli(Long.MAX_VALUE);
+
+ /** See {@link #getManualSuggestionLowerBound()}. */
+ private static final Instant MANUAL_SUGGESTION_LOWER_BOUND =
+ Instant.ofEpochMilli(1194220800000L); // Nov 5, 2007, 0:00 UTC
+
+ /**
+ * The lowest value in Unix epoch milliseconds that is considered a valid automatic suggestion.
+ * See also {@link #MANUAL_SUGGESTION_LOWER_BOUND}.
+ *
+ * <p>Note that this is a default value. The lower value enforced can be overridden to be
+ * lower in the system server with flags for testing.
+ */
+ private static final Instant AUTO_SUGGESTION_LOWER_BOUND_DEFAULT = Instant.ofEpochMilli(
+ Long.max(android.os.Environment.getRootDirectory().lastModified(), Build.TIME));
+
+ /** The singleton instance of this class. */
+ public static final TimeDetectorHelper INSTANCE = new TimeDetectorHelper();
+
+ /** Constructor present for subclassing in tests. Use {@link #INSTANCE} in production code. */
+ protected TimeDetectorHelper() {}
+
+ /**
+ * Returns the minimum gregorian calendar year to offer for manual date selection. This serves
+ * as a sensible UI-enforced lower limit, the system server may support a smaller lower bound.
+ */
+ public int getManualDateSelectionYearMin() {
+ return MANUAL_SUGGESTION_YEAR_MIN;
+ }
+
+ /**
+ * Returns the maximum gregorian calendar year to offer for manual date selection. This serves
+ * as a sensible UI-enforced lower limit, the system server may support a larger upper bound.
+ */
+ public int getManualDateSelectionYearMax() {
+ return getDeviceHasY2038Issue()
+ ? MANUAL_SUGGESTION_YEAR_MAX_WITH_Y2038_ISSUE
+ : MANUAL_SUGGESTION_YEAR_MAX_WITHOUT_Y2038_ISSUE;
+ }
+
+ /**
+ * Returns the lowest value in Unix epoch milliseconds that is considered a valid manual
+ * suggestion. For historical reasons Android has a different lower limit for manual input than
+ * automatic. This may change in the future to align with automatic suggestions, but has been
+ * kept initially to avoid breaking manual tests that are hard-coded with old dates real users
+ * will never want to use.
+ */
+ @NonNull
+ public Instant getManualSuggestionLowerBound() {
+ return MANUAL_SUGGESTION_LOWER_BOUND;
+ }
+
+ /**
+ * Returns the lowest value in Unix epoch milliseconds that is considered a valid automatic
+ * suggestion. See also {@link #MANUAL_SUGGESTION_LOWER_BOUND}.
+ *
+ * <p>Note that this is a default value. The lower value enforced can be overridden to be
+ * different in the system server with server flags.
+ */
+ @NonNull
+ public Instant getAutoSuggestionLowerBoundDefault() {
+ return AUTO_SUGGESTION_LOWER_BOUND_DEFAULT;
+ }
+
+ /** Returns the upper bound to enforce for all time suggestions (manual and automatic). */
+ @NonNull
+ public Instant getSuggestionUpperBound() {
+ return getDeviceHasY2038Issue()
+ ? SUGGESTION_UPPER_BOUND_WITH_Y2038_ISSUE
+ : SUGGESTION_UPPER_BOUND_WIITHOUT_Y2038_ISSUE;
+ }
+
+ /**
+ * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
+ * defines time_t as a 32-bit signed integer for 32-bit processes).
+ */
+ private boolean getDeviceHasY2038Issue() {
+ return Build.SUPPORTED_32_BIT_ABIS.length > 0;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index c672476..24f02ac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -681,9 +681,12 @@
return;
}
+ if (mState.getState() == STATE_ACTIVE) {
+ mOneHandedUiEventLogger.writeEvent(
+ OneHandedUiEventLogger.EVENT_ONE_HANDED_TRIGGER_ROTATION_OUT);
+ }
+
mDisplayAreaOrganizer.onRotateDisplay(mContext, toRotation, wct);
- mOneHandedUiEventLogger.writeEvent(
- OneHandedUiEventLogger.EVENT_ONE_HANDED_TRIGGER_ROTATION_OUT);
}
/**
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 071667a..c84f5b0 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -172,7 +172,7 @@
try {
mMediaRouterService.startScan(client);
} catch (RemoteException ex) {
- Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -196,7 +196,7 @@
try {
mMediaRouterService.stopScan(client);
} catch (RemoteException ex) {
- Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -361,9 +361,8 @@
return mMediaRouterService.getSystemSessionInfoForPackage(
getOrCreateClient(), packageName);
} catch (RemoteException ex) {
- Log.e(TAG, "Unable to get current system session info", ex);
+ throw ex.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -429,7 +428,7 @@
try {
return mMediaRouterService.getRemoteSessions(client);
} catch (RemoteException ex) {
- Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
return Collections.emptyList();
@@ -521,7 +520,7 @@
int requestId = mNextRequestId.getAndIncrement();
mMediaRouterService.setRouteVolumeWithManager(client, requestId, route, volume);
} catch (RemoteException ex) {
- Log.e(TAG, "Unable to set route volume.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -551,7 +550,7 @@
mMediaRouterService.setSessionVolumeWithManager(
client, requestId, sessionInfo.getId(), volume);
} catch (RemoteException ex) {
- Log.e(TAG, "Unable to set session volume.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -816,7 +815,7 @@
mMediaRouterService.selectRouteWithManager(
client, requestId, sessionInfo.getId(), route);
} catch (RemoteException ex) {
- Log.e(TAG, "selectRoute: Failed to send a request.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -858,7 +857,7 @@
mMediaRouterService.deselectRouteWithManager(
client, requestId, sessionInfo.getId(), route);
} catch (RemoteException ex) {
- Log.e(TAG, "deselectRoute: Failed to send a request.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -883,7 +882,7 @@
mMediaRouterService.releaseSessionWithManager(
client, requestId, sessionInfo.getId());
} catch (RemoteException ex) {
- Log.e(TAG, "releaseSession: Failed to send a request", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -903,7 +902,7 @@
mMediaRouterService.transferToRouteWithManager(
client, requestId, session.getId(), route);
} catch (RemoteException ex) {
- Log.e(TAG, "transferToRoute: Failed to send a request.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -923,7 +922,7 @@
mMediaRouterService.requestCreateSessionWithManager(
client, requestId, oldSession, route);
} catch (RemoteException ex) {
- Log.e(TAG, "requestCreateSession: Failed to send a request", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
@@ -979,10 +978,9 @@
mClient = client;
return client;
} catch (RemoteException ex) {
- Log.e(TAG, "Unable to register media router manager.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
- return null;
}
/**
diff --git a/packages/SettingsLib/LayoutPreference/res/layout/settings_entity_header.xml b/packages/SettingsLib/LayoutPreference/res/layout/settings_entity_header.xml
index 50f69d1..c629d96 100644
--- a/packages/SettingsLib/LayoutPreference/res/layout/settings_entity_header.xml
+++ b/packages/SettingsLib/LayoutPreference/res/layout/settings_entity_header.xml
@@ -71,6 +71,8 @@
<TextView
android:id="@+id/entity_header_second_summary"
style="@style/TextAppearance.EntityHeaderSummary"
+ android:singleLine="false"
+ android:maxLines="4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index dbdbdf6..2f36ab9 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -515,11 +515,20 @@
dialogContentWithBackground.setTransitionVisibility(View.INVISIBLE)
// Make sure the dialog is visible instantly and does not do any window animation.
- window.attributes.windowAnimations = R.style.Animation_LaunchAnimation
+ val attributes = window.attributes
+ attributes.windowAnimations = R.style.Animation_LaunchAnimation
// Ensure that the animation is not clipped by the display cut-out when animating this
// dialog into an app.
- window.attributes.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+ attributes.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+
+ // Ensure that the animation is not clipped by the navigation/task bars when animating this
+ // dialog into an app.
+ val wasFittingNavigationBars =
+ attributes.fitInsetsTypes and WindowInsets.Type.navigationBars() != 0
+ attributes.fitInsetsTypes =
+ attributes.fitInsetsTypes and WindowInsets.Type.navigationBars().inv()
+
window.attributes = window.attributes
// We apply the insets ourselves to make sure that the paddings are set on the correct
@@ -527,7 +536,13 @@
window.setDecorFitsSystemWindows(false)
val viewWithInsets = (dialogContentWithBackground.parent as ViewGroup)
viewWithInsets.setOnApplyWindowInsetsListener { view, windowInsets ->
- val insets = windowInsets.getInsets(WindowInsets.Type.displayCutout())
+ val type = if (wasFittingNavigationBars) {
+ WindowInsets.Type.displayCutout() or WindowInsets.Type.navigationBars()
+ } else {
+ WindowInsets.Type.displayCutout()
+ }
+
+ val insets = windowInsets.getInsets(type)
view.setPadding(insets.left, insets.top, insets.right, insets.bottom)
WindowInsets.CONSUMED
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 15c1761..a553e19 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -145,6 +145,9 @@
public static final ResourceBooleanFlag STATUS_BAR_USER_SWITCHER =
new ResourceBooleanFlag(602, R.bool.flag_user_switcher_chip);
+ public static final BooleanFlag STATUS_BAR_LETTERBOX_APPEARANCE =
+ new BooleanFlag(603, false);
+
/***************************************/
// 700 - dialer/calls
public static final BooleanFlag ONGOING_CALL_STATUS_BAR_CHIP =
diff --git a/services/contentcapture/Android.bp b/services/contentcapture/Android.bp
index 434f239..5392c2c 100644
--- a/services/contentcapture/Android.bp
+++ b/services/contentcapture/Android.bp
@@ -17,6 +17,9 @@
java_library_static {
name: "services.contentcapture",
defaults: ["platform_service_defaults"],
- srcs: [":services.contentcapture-sources"],
+ srcs: [
+ ":services.contentcapture-sources",
+ "java/**/*.logtags",
+ ],
libs: ["services.core"],
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 7a95a8f..1ca68d7 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -60,6 +60,7 @@
import android.service.voice.VoiceInteractionManagerInternal;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -88,6 +89,11 @@
private static final String TAG = ContentCapturePerUserService.class.getSimpleName();
+ private static final int EVENT_LOG_CONNECT_STATE_DIED = 0;
+ static final int EVENT_LOG_CONNECT_STATE_CONNECTED = 1;
+ static final int EVENT_LOG_CONNECT_STATE_DISCONNECTED = 2;
+
+
@GuardedBy("mLock")
private final SparseArray<ContentCaptureServerSession> mSessions = new SparseArray<>();
@@ -190,9 +196,13 @@
Slog.w(TAG, "remote service died: " + service);
synchronized (mLock) {
mZombie = true;
+ ComponentName serviceComponent = getServiceComponentName();
writeServiceEvent(
FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_REMOTE_SERVICE_DIED,
- getServiceComponentName());
+ serviceComponent);
+ EventLog.writeEvent(EventLogTags.CC_CONNECT_STATE_CHANGED, mUserId,
+ serviceComponent != null ? serviceComponent.flattenToShortString() : "",
+ EVENT_LOG_CONNECT_STATE_DIED);
}
}
@@ -614,11 +624,16 @@
? "null_activities" : activities.size() + " activities") + ")"
+ " for user " + mUserId);
}
+ int packageCount = packages != null ? packages.size() : 0;
+ int activityCount = activities != null ? activities.size() : 0;
ArraySet<String> oldList =
mMaster.mGlobalContentCaptureOptions.getWhitelistedPackages(mUserId);
+ EventLog.writeEvent(EventLogTags.CC_CURRENT_ALLOWLIST, mUserId, oldList.size());
mMaster.mGlobalContentCaptureOptions.setWhitelist(mUserId, packages, activities);
+ EventLog.writeEvent(EventLogTags.CC_SET_ALLOWLIST, mUserId,
+ packageCount, activityCount);
writeSetWhitelistEvent(getServiceComponentName(), packages, activities);
updateContentCaptureOptions(oldList);
@@ -699,12 +714,14 @@
private void updateContentCaptureOptions(@Nullable ArraySet<String> oldList) {
ArraySet<String> adding = mMaster.mGlobalContentCaptureOptions
.getWhitelistedPackages(mUserId);
+ EventLog.writeEvent(EventLogTags.CC_CURRENT_ALLOWLIST, mUserId, adding.size());
if (oldList != null && adding != null) {
adding.removeAll(oldList);
}
int N = adding != null ? adding.size() : 0;
+ EventLog.writeEvent(EventLogTags.CC_UPDATE_OPTIONS, mUserId, N);
for (int i = 0; i < N; i++) {
String packageName = adding.valueAt(i);
ContentCaptureOptions options = mMaster.mGlobalContentCaptureOptions
diff --git a/services/contentcapture/java/com/android/server/contentcapture/EventLogTags.logtags b/services/contentcapture/java/com/android/server/contentcapture/EventLogTags.logtags
new file mode 100644
index 0000000..6722b9e
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentcapture/EventLogTags.logtags
@@ -0,0 +1,8 @@
+# See system/logging/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.server.contentcapture
+
+53200 cc_connect_state_changed (User|1|5),(component|3),(type|1)
+53201 cc_set_allowlist (User|1|5),(package_count|1),(activity_count|1)
+53202 cc_current_allowlist (User|1|5),(count|1)
+53203 cc_update_options (User|1|5),(count|1)
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 1efe55a..e22a9d0 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -31,6 +31,7 @@
import android.service.contentcapture.IContentCaptureServiceCallback;
import android.service.contentcapture.IDataShareCallback;
import android.service.contentcapture.SnapshotData;
+import android.util.EventLog;
import android.util.Slog;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.DataRemovalRequest;
@@ -47,6 +48,7 @@
private final IBinder mServerCallback;
private final int mIdleUnbindTimeoutMs;
private final ContentCapturePerUserService mPerUserService;
+ private final int mUserId;
RemoteContentCaptureService(Context context, String serviceInterface,
ComponentName serviceComponentName, IContentCaptureServiceCallback callback, int userId,
@@ -61,6 +63,7 @@
mPerUserService = perUserService;
mServerCallback = callback.asBinder();
mIdleUnbindTimeoutMs = idleUnbindTimeoutMs;
+ mUserId = userId;
// Bind right away, which will trigger a onConnected() on service's
ensureBoundLocked();
@@ -88,6 +91,9 @@
writeServiceEvent(
FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_CONNECTED,
mComponentName);
+ EventLog.writeEvent(EventLogTags.CC_CONNECT_STATE_CHANGED, mUserId,
+ mComponentName != null ? mComponentName.flattenToShortString() : "",
+ ContentCapturePerUserService.EVENT_LOG_CONNECT_STATE_CONNECTED);
} finally {
// Update the system-service state, in case the service reconnected after
// dying
@@ -98,6 +104,9 @@
writeServiceEvent(
FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_DISCONNECTED,
mComponentName);
+ EventLog.writeEvent(EventLogTags.CC_CONNECT_STATE_CHANGED, mUserId,
+ mComponentName != null ? mComponentName.flattenToShortString() : "",
+ ContentCapturePerUserService.EVENT_LOG_CONNECT_STATE_DISCONNECTED);
}
} catch (Exception e) {
Slog.w(mTag, "Exception calling onConnectedStateChanged(" + connected + "): " + e);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 46b0ded..556fa14 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -10377,6 +10377,11 @@
@Override
public void setAccessibilityServiceUids(IntArray uids) {
+ // TODO(b/233287010): Fix voice interaction and a11y concurrency in audio policy service
+ if (isPlatformAutomotive()) {
+ return;
+ }
+
synchronized (mAccessibilityServiceUidsLock) {
if (uids.size() == 0) {
mAccessibilityServiceUids = null;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 8d0114d..794c06f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1,16 +1,17 @@
/*
+ * 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
+ * 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
+ * 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.
+ * 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.inputmethod;
@@ -367,29 +368,29 @@
Future<?> mImeDrawsImeNavBarResLazyInitFuture;
static class SessionState {
- final ClientState client;
- final IInputMethodInvoker method;
+ final ClientState mClient;
+ final IInputMethodInvoker mMethod;
- IInputMethodSession session;
- InputChannel channel;
+ IInputMethodSession mSession;
+ InputChannel mChannel;
@Override
public String toString() {
- return "SessionState{uid " + client.uid + " pid " + client.pid
+ return "SessionState{uid " + mClient.mUid + " pid " + mClient.mPid
+ " method " + Integer.toHexString(
- IInputMethodInvoker.getBinderIdentityHashCode(method))
+ IInputMethodInvoker.getBinderIdentityHashCode(mMethod))
+ " session " + Integer.toHexString(
- System.identityHashCode(session))
- + " channel " + channel
+ System.identityHashCode(mSession))
+ + " channel " + mChannel
+ "}";
}
- SessionState(ClientState _client, IInputMethodInvoker _method,
- IInputMethodSession _session, InputChannel _channel) {
- client = _client;
- method = _method;
- session = _session;
- channel = _channel;
+ SessionState(ClientState client, IInputMethodInvoker method,
+ IInputMethodSession session, InputChannel channel) {
+ mClient = client;
+ mMethod = method;
+ mSession = session;
+ mChannel = channel;
}
}
@@ -405,7 +406,7 @@
@Override
public String toString() {
- return "AccessibilitySessionState{uid " + mClient.uid + " pid " + mClient.pid
+ return "AccessibilitySessionState{uid " + mClient.mUid + " pid " + mClient.mPid
+ " id " + Integer.toHexString(mId)
+ " session " + Integer.toHexString(
System.identityHashCode(mSession))
@@ -436,37 +437,37 @@
}
static final class ClientState {
- final IInputMethodClientInvoker client;
- final IRemoteInputConnection fallbackInputConnection;
- final int uid;
- final int pid;
- final int selfReportedDisplayId;
- final InputBinding binding;
- final ClientDeathRecipient clientDeathRecipient;
+ final IInputMethodClientInvoker mClient;
+ final IRemoteInputConnection mFallbackInputConnection;
+ final int mUid;
+ final int mPid;
+ final int mSelfReportedDisplayId;
+ final InputBinding mBinding;
+ final ClientDeathRecipient mClientDeathRecipient;
- boolean sessionRequested;
+ boolean mSessionRequested;
boolean mSessionRequestedForAccessibility;
- SessionState curSession;
+ SessionState mCurSession;
SparseArray<AccessibilitySessionState> mAccessibilitySessions = new SparseArray<>();
@Override
public String toString() {
return "ClientState{" + Integer.toHexString(
- System.identityHashCode(this)) + " uid=" + uid
- + " pid=" + pid + " displayId=" + selfReportedDisplayId + "}";
+ System.identityHashCode(this)) + " mUid=" + mUid
+ + " mPid=" + mPid + " mSelfReportedDisplayId=" + mSelfReportedDisplayId + "}";
}
- ClientState(IInputMethodClientInvoker _client,
- IRemoteInputConnection _fallbackInputConnection,
- int _uid, int _pid, int _selfReportedDisplayId,
- ClientDeathRecipient _clientDeathRecipient) {
- client = _client;
- fallbackInputConnection = _fallbackInputConnection;
- uid = _uid;
- pid = _pid;
- selfReportedDisplayId = _selfReportedDisplayId;
- binding = new InputBinding(null, fallbackInputConnection.asBinder(), uid, pid);
- clientDeathRecipient = _clientDeathRecipient;
+ ClientState(IInputMethodClientInvoker client,
+ IRemoteInputConnection fallbackInputConnection,
+ int uid, int pid, int selfReportedDisplayId,
+ ClientDeathRecipient clientDeathRecipient) {
+ mClient = client;
+ mFallbackInputConnection = fallbackInputConnection;
+ mUid = uid;
+ mPid = pid;
+ mSelfReportedDisplayId = selfReportedDisplayId;
+ mBinding = new InputBinding(null, mFallbackInputConnection.asBinder(), mUid, mPid);
+ mClientDeathRecipient = clientDeathRecipient;
}
}
@@ -764,7 +765,7 @@
*/
boolean mBoundToAccessibility;
- /**
+ /**
* Currently enabled session.
*/
@GuardedBy("ImfLock.class")
@@ -1009,7 +1010,7 @@
* <p>TODO: Consider to follow what other system services have been doing to manage
* constants (e.g. {@link android.provider.Settings.Global#ACTIVITY_MANAGER_CONSTANTS}).</p>
*/
- private final static int ENTRY_SIZE_FOR_HIGH_RAM_DEVICE = 32;
+ private static final int ENTRY_SIZE_FOR_HIGH_RAM_DEVICE = 32;
/**
* Entry size for non low-RAM devices.
@@ -1017,7 +1018,7 @@
* <p>TODO: Consider to follow what other system services have been doing to manage
* constants (e.g. {@link android.provider.Settings.Global#ACTIVITY_MANAGER_CONSTANTS}).</p>
*/
- private final static int ENTRY_SIZE_FOR_LOW_RAM_DEVICE = 5;
+ private static final int ENTRY_SIZE_FOR_LOW_RAM_DEVICE = 5;
private static int getEntrySize() {
if (ActivityManager.isLowRamDeviceStatic()) {
@@ -1140,7 +1141,7 @@
pw.print(prefix);
pw.println(" softInputMode=" + InputMethodDebug.softInputModeToString(
- entry.mTargetWindowSoftInputMode));
+ entry.mTargetWindowSoftInputMode));
pw.print(prefix);
pw.println(" inputType=0x" + Integer.toHexString(entry.mEditorInfo.inputType)
@@ -1336,7 +1337,7 @@
* rescanning.</p>
*/
@GuardedBy("ImfLock.class")
- final private ArraySet<String> mKnownImePackageNames = new ArraySet<>();
+ private final ArraySet<String> mKnownImePackageNames = new ArraySet<>();
/**
* Packages that are appeared, disappeared, or modified for whatever reason.
@@ -1364,7 +1365,7 @@
}
@GuardedBy("ImfLock.class")
- final void addKnownImePackageNameLocked(@NonNull String packageName) {
+ void addKnownImePackageNameLocked(@NonNull String packageName) {
mKnownImePackageNames.add(packageName);
}
@@ -1387,9 +1388,9 @@
return false;
}
String curInputMethodId = mSettings.getSelectedInputMethod();
- final int N = mMethodList.size();
+ final int numImes = mMethodList.size();
if (curInputMethodId != null) {
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < numImes; i++) {
InputMethodInfo imi = mMethodList.get(i);
if (imi.getId().equals(curInputMethodId)) {
for (String pkg : packages) {
@@ -1491,8 +1492,8 @@
// Otherwise, check if mKnownImePackageNames and mChangedPackages have any intersection.
// TODO: Consider to create a utility method to do the following test. List.retainAll()
// is an option, but it may still do some extra operations that we do not need here.
- final int N = mChangedPackages.size();
- for (int i = 0; i < N; ++i) {
+ final int numPackages = mChangedPackages.size();
+ for (int i = 0; i < numPackages; ++i) {
final String packageName = mChangedPackages.get(i);
if (mKnownImePackageNames.contains(packageName)) {
return true;
@@ -1512,9 +1513,9 @@
InputMethodInfo curIm = null;
String curInputMethodId = mSettings.getSelectedInputMethod();
- final int N = mMethodList.size();
+ final int numImes = mMethodList.size();
if (curInputMethodId != null) {
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < numImes; i++) {
InputMethodInfo imi = mMethodList.get(i);
final String imiId = imi.getId();
if (imiId.equals(curInputMethodId)) {
@@ -1620,6 +1621,10 @@
@GuardedBy("ImfLock.class")
private UserSwitchHandlerTask mUserSwitchHandlerTask;
+ /**
+ * {@link SystemService} used to publish and manage the lifecycle of
+ * {@link InputMethodManagerService}.
+ */
public static final class Lifecycle extends SystemService {
private final InputMethodManagerService mService;
@@ -1853,8 +1858,10 @@
@GuardedBy("ImfLock.class")
private void switchUserOnHandlerLocked(@UserIdInt int newUserId,
IInputMethodClientInvoker clientToBeReset) {
- if (DEBUG) Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId
- + " currentUserId=" + mSettings.getCurrentUserId());
+ if (DEBUG) {
+ Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId
+ + " currentUserId=" + mSettings.getCurrentUserId());
+ }
maybeInitImeNavbarConfigLocked(newUserId);
@@ -1871,8 +1878,10 @@
AdditionalSubtypeUtils.load(mAdditionalSubtypeMap, newUserId);
final String defaultImiId = mSettings.getSelectedInputMethod();
- if (DEBUG) Slog.d(TAG, "Switching user stage 2/3. newUserId=" + newUserId
- + " defaultImiId=" + defaultImiId);
+ if (DEBUG) {
+ Slog.d(TAG, "Switching user stage 2/3. newUserId=" + newUserId
+ + " defaultImiId=" + defaultImiId);
+ }
// For secondary users, the list of enabled IMEs may not have been updated since the
// callbacks to PackageMonitor are ignored for the secondary user. Here, defaultImiId may
@@ -1899,8 +1908,10 @@
mSettings.getEnabledInputMethodListLocked());
}
- if (DEBUG) Slog.d(TAG, "Switching user stage 3/3. newUserId=" + newUserId
- + " selectedIme=" + mSettings.getSelectedInputMethod());
+ if (DEBUG) {
+ Slog.d(TAG, "Switching user stage 3/3. newUserId=" + newUserId
+ + " selectedIme=" + mSettings.getSelectedInputMethod());
+ }
mLastSwitchUserId = newUserId;
@@ -1910,7 +1921,7 @@
// The client is already gone.
return;
}
- cs.client.scheduleStartInputIfNecessary(mInFullscreenMode);
+ cs.mClient.scheduleStartInputIfNecessary(mInFullscreenMode);
}
}
@@ -1934,6 +1945,9 @@
}
}
+ /**
+ * TODO(b/32343335): The entire systemRunning() method needs to be revisited.
+ */
public void systemRunning(StatusBarManagerService statusBar) {
synchronized (ImfLock.class) {
if (DEBUG) {
@@ -2033,7 +2047,7 @@
// by a token.
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
- == PackageManager.PERMISSION_GRANTED) {
+ == PackageManager.PERMISSION_GRANTED) {
if (DEBUG) {
Slog.d(TAG, "--- Access granted because the calling process has "
+ "the INTERACT_ACROSS_USERS_FULL permission");
@@ -2270,8 +2284,8 @@
final int numClients = mClients.size();
for (int i = 0; i < numClients; ++i) {
final ClientState state = mClients.valueAt(i);
- if (state.uid == callerUid && state.pid == callerPid
- && state.selfReportedDisplayId == selfReportedDisplayId) {
+ if (state.mUid == callerUid && state.mPid == callerPid
+ && state.mSelfReportedDisplayId == selfReportedDisplayId) {
throw new SecurityException("uid=" + callerUid + "/pid=" + callerPid
+ "/displayId=" + selfReportedDisplayId + " is already registered.");
}
@@ -2303,7 +2317,7 @@
synchronized (ImfLock.class) {
ClientState cs = mClients.remove(client.asBinder());
if (cs != null) {
- client.asBinder().unlinkToDeath(cs.clientDeathRecipient, 0);
+ client.asBinder().unlinkToDeath(cs.mClientDeathRecipient, 0);
clearClientSessionLocked(cs);
clearClientSessionForAccessibilityLocked(cs);
@@ -2342,8 +2356,10 @@
@GuardedBy("ImfLock.class")
void unbindCurrentClientLocked(@UnbindReason int unbindClientReason) {
if (mCurClient != null) {
- if (DEBUG) Slog.v(TAG, "unbindCurrentInputLocked: client="
- + mCurClient.client.asBinder());
+ if (DEBUG) {
+ Slog.v(TAG, "unbindCurrentInputLocked: client="
+ + mCurClient.mClient.asBinder());
+ }
if (mBoundToMethod) {
mBoundToMethod = false;
IInputMethodInvoker curMethod = getCurMethodLocked();
@@ -2356,10 +2372,10 @@
// Since we set active false to current client and set mCurClient to null, let's unbind
// all accessibility too. That means, when input method get disconnected (including
// switching ime), we also unbind accessibility
- mCurClient.client.setActive(false /* active */, false /* fullscreen */,
+ mCurClient.mClient.setActive(false /* active */, false /* fullscreen */,
false /* reportToImeController */);
- mCurClient.client.onUnbindMethod(getSequenceNumberLocked(), unbindClientReason);
- mCurClient.sessionRequested = false;
+ mCurClient.mClient.onUnbindMethod(getSequenceNumberLocked(), unbindClientReason);
+ mCurClient.mSessionRequested = false;
mCurClient.mSessionRequestedForAccessibility = false;
mCurClient = null;
mCurVirtualDisplayToScreenMatrix = null;
@@ -2401,7 +2417,7 @@
@NonNull
InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) {
if (!mBoundToMethod) {
- getCurMethodLocked().bindInput(mCurClient.binding);
+ getCurMethodLocked().bindInput(mCurClient.mBinding);
mBoundToMethod = true;
}
@@ -2410,7 +2426,7 @@
final StartInputInfo info = new StartInputInfo(mSettings.getCurrentUserId(),
getCurTokenLocked(),
mCurTokenDisplayId, getCurIdLocked(), startInputReason, restarting,
- UserHandle.getUserId(mCurClient.uid), mCurClient.selfReportedDisplayId,
+ UserHandle.getUserId(mCurClient.mUid), mCurClient.mSelfReportedDisplayId,
mCurFocusedWindow, mCurEditorInfo, mCurFocusedWindowSoftInputMode,
getSequenceNumberLocked());
mImeTargetWindowMap.put(startInputToken, mCurFocusedWindow);
@@ -2421,17 +2437,17 @@
// same-user scenarios.
// That said ignoring cross-user scenario will never affect IMEs that do not have
// INTERACT_ACROSS_USERS(_FULL) permissions, which is actually almost always the case.
- if (mSettings.getCurrentUserId() == UserHandle.getUserId(mCurClient.uid)) {
+ if (mSettings.getCurrentUserId() == UserHandle.getUserId(mCurClient.mUid)) {
mPackageManagerInternal.grantImplicitAccess(mSettings.getCurrentUserId(),
- null /* intent */, UserHandle.getAppId(getCurMethodUidLocked()), mCurClient.uid,
- true /* direct */);
+ null /* intent */, UserHandle.getAppId(getCurMethodUidLocked()),
+ mCurClient.mUid, true /* direct */);
}
@InputMethodNavButtonFlags
final int navButtonFlags = getInputMethodNavButtonFlagsLocked();
- final SessionState session = mCurClient.curSession;
+ final SessionState session = mCurClient.mCurSession;
setEnabledSessionLocked(session);
- session.method.startInput(startInputToken, mCurInputConnection, mCurEditorInfo, restarting,
+ session.mMethod.startInput(startInputToken, mCurInputConnection, mCurEditorInfo, restarting,
navButtonFlags, mCurImeDispatcher);
if (mShowRequested) {
if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
@@ -2446,8 +2462,8 @@
final SparseArray<IAccessibilityInputMethodSession> accessibilityInputMethodSessions =
createAccessibilityInputMethodSessions(mCurClient.mAccessibilitySessions);
return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,
- session.session, accessibilityInputMethodSessions,
- (session.channel != null ? session.channel.dup() : null),
+ session.mSession, accessibilityInputMethodSessions,
+ (session.mChannel != null ? session.mChannel.dup() : null),
curId, getSequenceNumberLocked(), mCurVirtualDisplayToScreenMatrix,
suppressesSpellChecker);
}
@@ -2470,10 +2486,10 @@
} else {
matrix.postConcat(info.mMatrix);
}
- if (info.mParentClient.selfReportedDisplayId == imeDisplayId) {
+ if (info.mParentClient.mSelfReportedDisplayId == imeDisplayId) {
return matrix;
}
- displayId = info.mParentClient.selfReportedDisplayId;
+ displayId = info.mParentClient.mSelfReportedDisplayId;
}
}
@@ -2541,16 +2557,16 @@
null, null, null, selectedMethodId, getSequenceNumberLocked(), null, false);
}
- if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.uid,
+ if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.mUid,
editorInfo.packageName)) {
Slog.e(TAG, "Rejecting this client as it reported an invalid package name."
- + " uid=" + cs.uid + " package=" + editorInfo.packageName);
+ + " uid=" + cs.mUid + " package=" + editorInfo.packageName);
return InputBindResult.INVALID_PACKAGE_NAME;
}
// Compute the final shown display ID with validated cs.selfReportedDisplayId for this
// session & other conditions.
- mDisplayIdToShowIme = computeImeDisplayIdForTarget(cs.selfReportedDisplayId,
+ mDisplayIdToShowIme = computeImeDisplayIdForTarget(cs.mSelfReportedDisplayId,
mImeDisplayValidator);
if (mDisplayIdToShowIme == INVALID_DISPLAY) {
@@ -2572,7 +2588,7 @@
mCurRemoteAccessibilityInputConnection = remoteAccessibilityInputConnection;
mCurImeDispatcher = imeDispatcher;
mCurVirtualDisplayToScreenMatrix =
- getVirtualDisplayToScreenMatrixLocked(cs.selfReportedDisplayId,
+ getVirtualDisplayToScreenMatrixLocked(cs.mSelfReportedDisplayId,
mDisplayIdToShowIme);
mCurEditorInfo = editorInfo;
@@ -2591,7 +2607,7 @@
// We expect the caller has already verified that the client is allowed to access this
// display ID.
if (isSelectedMethodBoundLocked()) {
- if (cs.curSession != null) {
+ if (cs.mCurSession != null) {
// Fast case: if we are already connected to the input method,
// then just return it.
// This doesn't mean a11y sessions are there. When a11y service is
@@ -2667,7 +2683,7 @@
unbindCurrentClientLocked(UnbindReason.SWITCH_CLIENT);
// If the screen is on, inform the new client it is active
if (mIsInteractive) {
- cs.client.setActive(true /* active */, false /* fullscreen */,
+ cs.mClient.setActive(true /* active */, false /* fullscreen */,
false /* reportToImeController */);
}
}
@@ -2779,13 +2795,13 @@
&& curMethod.asBinder() == method.asBinder()) {
if (mCurClient != null) {
clearClientSessionLocked(mCurClient);
- mCurClient.curSession = new SessionState(mCurClient,
+ mCurClient.mCurSession = new SessionState(mCurClient,
method, session, channel);
InputBindResult res = attachNewInputLocked(
StartInputReason.SESSION_CREATED_BY_IME, true);
attachNewAccessibilityLocked(StartInputReason.SESSION_CREATED_BY_IME, true);
if (res.method != null) {
- mCurClient.client.onBindMethod(res);
+ mCurClient.mClient.onBindMethod(res);
}
return;
}
@@ -2828,7 +2844,7 @@
@GuardedBy("ImfLock.class")
void requestClientSessionLocked(ClientState cs) {
- if (!cs.sessionRequested) {
+ if (!cs.mSessionRequested) {
if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
final InputChannel serverChannel;
final InputChannel clientChannel;
@@ -2838,7 +2854,7 @@
clientChannel = channels[1];
}
- cs.sessionRequested = true;
+ cs.mSessionRequested = true;
final IInputMethodInvoker curMethod = getCurMethodLocked();
final IInputMethodSessionCallback.Stub callback =
@@ -2881,9 +2897,9 @@
@GuardedBy("ImfLock.class")
void clearClientSessionLocked(ClientState cs) {
- finishSessionLocked(cs.curSession);
- cs.curSession = null;
- cs.sessionRequested = false;
+ finishSessionLocked(cs.mCurSession);
+ cs.mCurSession = null;
+ cs.mSessionRequested = false;
}
@GuardedBy("ImfLock.class")
@@ -2907,18 +2923,18 @@
@GuardedBy("ImfLock.class")
private void finishSessionLocked(SessionState sessionState) {
if (sessionState != null) {
- if (sessionState.session != null) {
+ if (sessionState.mSession != null) {
try {
- sessionState.session.finishSession();
+ sessionState.mSession.finishSession();
} catch (RemoteException e) {
Slog.w(TAG, "Session failed to close due to remote exception", e);
updateSystemUiLocked(0 /* vis */, mBackDisposition);
}
- sessionState.session = null;
+ sessionState.mSession = null;
}
- if (sessionState.channel != null) {
- sessionState.channel.dispose();
- sessionState.channel = null;
+ if (sessionState.mChannel != null) {
+ sessionState.mChannel.dispose();
+ sessionState.mChannel = null;
}
}
}
@@ -3017,7 +3033,7 @@
InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE);
return (canImeDrawsImeNavBar ? InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR : 0)
| (shouldShowImeSwitcherWhenImeIsShown
- ? InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN : 0);
+ ? InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN : 0);
}
@GuardedBy("ImfLock.class")
@@ -3040,17 +3056,17 @@
return false;
}
- List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListWithFilterLocked(
+ List<InputMethodInfo> imes = mSettings.getEnabledInputMethodListWithFilterLocked(
InputMethodInfo::shouldShowInInputMethodPicker);
- final int N = imis.size();
- if (N > 2) return true;
- if (N < 1) return false;
+ final int numImes = imes.size();
+ if (numImes > 2) return true;
+ if (numImes < 1) return false;
int nonAuxCount = 0;
int auxCount = 0;
InputMethodSubtype nonAuxSubtype = null;
InputMethodSubtype auxSubtype = null;
- for(int i = 0; i < N; ++i) {
- final InputMethodInfo imi = imis.get(i);
+ for (int i = 0; i < numImes; ++i) {
+ final InputMethodInfo imi = imes.get(i);
final List<InputMethodSubtype> subtypes =
mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
final int subtypeCount = subtypes.size();
@@ -3074,8 +3090,8 @@
} else if (nonAuxCount == 1 && auxCount == 1) {
if (nonAuxSubtype != null && auxSubtype != null
&& (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
- || auxSubtype.overridesImplicitlyEnabledSubtype()
- || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
+ || auxSubtype.overridesImplicitlyEnabledSubtype()
+ || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
&& nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
return false;
}
@@ -3231,7 +3247,7 @@
void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) {
if (enabledMayChange) {
List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
- for (int i=0; i<enabled.size(); i++) {
+ for (int i = 0; i < enabled.size(); i++) {
// We allow the user to select "disabled until used" apps, so if they
// are enabling one of those here we now need to make it enabled.
InputMethodInfo imm = enabled.get(i);
@@ -3437,10 +3453,10 @@
return false;
}
- if ((flags&InputMethodManager.SHOW_FORCED) != 0) {
+ if ((flags & InputMethodManager.SHOW_FORCED) != 0) {
mShowExplicitlyRequested = true;
mShowForced = true;
- } else if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
+ } else if ((flags & InputMethodManager.SHOW_IMPLICIT) == 0) {
mShowExplicitlyRequested = true;
}
@@ -3496,12 +3512,12 @@
@GuardedBy("ImfLock.class")
boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver,
@SoftInputShowHideReason int reason) {
- if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
+ if ((flags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mShowExplicitlyRequested || mShowForced)) {
if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
return false;
}
- if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
+ if (mShowForced && (flags & InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
return false;
}
@@ -3548,7 +3564,7 @@
private boolean isImeClientFocused(IBinder windowToken, ClientState cs) {
final int imeClientFocus = mWindowManagerInternal.hasInputMethodClientFocus(
- windowToken, cs.uid, cs.pid, cs.selfReportedDisplayId);
+ windowToken, cs.mUid, cs.mPid, cs.mSelfReportedDisplayId);
return imeClientFocus == WindowManagerInternal.ImeClientFocusResult.HAS_IME_FOCUS;
}
@@ -3663,7 +3679,7 @@
}
final int imeClientFocus = mWindowManagerInternal.hasInputMethodClientFocus(
- windowToken, cs.uid, cs.pid, cs.selfReportedDisplayId);
+ windowToken, cs.mUid, cs.mPid, cs.mSelfReportedDisplayId);
switch (imeClientFocus) {
case WindowManagerInternal.ImeClientFocusResult.DISPLAY_ID_MISMATCH:
Slog.e(TAG, "startInputOrWindowGainedFocusInternal: display ID mismatch.");
@@ -3675,8 +3691,8 @@
// next client receiving focus that has any interest in input will
// be calling through here after that change happens.
if (DEBUG) {
- Slog.w(TAG, "Focus gain on non-focused client " + cs.client
- + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
+ Slog.w(TAG, "Focus gain on non-focused client " + cs.mClient
+ + " (uid=" + cs.mUid + " pid=" + cs.mPid + ")");
}
return InputBindResult.NOT_IME_TARGET_WINDOW;
case WindowManagerInternal.ImeClientFocusResult.INVALID_DISPLAY_ID:
@@ -3687,19 +3703,19 @@
// There is already an on-going pending user switch task.
final int nextUserId = mUserSwitchHandlerTask.mToUserId;
if (userId == nextUserId) {
- scheduleSwitchUserTaskLocked(userId, cs.client);
+ scheduleSwitchUserTaskLocked(userId, cs.mClient);
return InputBindResult.USER_SWITCHING;
}
for (int profileId : mUserManager.getProfileIdsWithDisabled(nextUserId)) {
if (profileId == userId) {
- scheduleSwitchUserTaskLocked(userId, cs.client);
+ scheduleSwitchUserTaskLocked(userId, cs.mClient);
return InputBindResult.USER_SWITCHING;
}
}
return InputBindResult.INVALID_USER;
}
- final boolean shouldClearFlag = mImePlatformCompatUtils.shouldClearShowForcedFlag(cs.uid);
+ final boolean shouldClearFlag = mImePlatformCompatUtils.shouldClearShowForcedFlag(cs.mUid);
// In case mShowForced flag affects the next client to keep IME visible, when the current
// client is leaving due to the next focused client, we clear mShowForced flag when the
// next client's targetSdkVersion is T or higher.
@@ -3719,7 +3735,7 @@
}
if (userId != mSettings.getCurrentUserId()) {
- scheduleSwitchUserTaskLocked(userId, cs.client);
+ scheduleSwitchUserTaskLocked(userId, cs.mClient);
return InputBindResult.USER_SWITCHING;
}
@@ -3760,7 +3776,7 @@
final boolean doAutoShow =
(softInputMode & LayoutParams.SOFT_INPUT_MASK_ADJUST)
== LayoutParams.SOFT_INPUT_ADJUST_RESIZE
- || mRes.getConfiguration().isLayoutSizeAtLeast(
+ || mRes.getConfiguration().isLayoutSizeAtLeast(
Configuration.SCREENLAYOUT_SIZE_LARGE);
// We want to start input before showing the IME, but after closing
@@ -3803,7 +3819,7 @@
// window token removed.
// Note that we can trust client's display ID as long as it matches
// to the display ID obtained from the window.
- if (cs.selfReportedDisplayId != mCurTokenDisplayId) {
+ if (cs.mSelfReportedDisplayId != mCurTokenDisplayId) {
mBindingController.unbindCurrentMethod();
}
}
@@ -3918,7 +3934,7 @@
private boolean canInteractWithImeLocked(
int uid, IInputMethodClient client, String methodName) {
if (mCurClient == null || client == null
- || mCurClient.client.asBinder() != client.asBinder()) {
+ || mCurClient.mClient.asBinder() != client.asBinder()) {
// We need to check if this is the current client with
// focus in the window manager, to allow this call to
// be made before input is started in it.
@@ -3951,7 +3967,7 @@
private boolean canShowInputMethodPickerLocked(IInputMethodClient client) {
final int uid = Binder.getCallingUid();
if (mCurFocusedWindowClient != null && client != null
- && mCurFocusedWindowClient.client.asBinder() == client.asBinder()) {
+ && mCurFocusedWindowClient.mClient.asBinder() == client.asBinder()) {
return true;
}
if (mSettings.getCurrentUserId() != UserHandle.getUserId(uid)) {
@@ -3979,7 +3995,7 @@
// Always call subtype picker, because subtype picker is a superset of input method
// picker.
final int displayId =
- (mCurClient != null) ? mCurClient.selfReportedDisplayId : DEFAULT_DISPLAY;
+ (mCurClient != null) ? mCurClient.mSelfReportedDisplayId : DEFAULT_DISPLAY;
mHandler.obtainMessage(MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode, displayId)
.sendToTarget();
}
@@ -4078,11 +4094,11 @@
// the most applicable enabled keyboard subtype of the system imes.
final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
if (enabled != null) {
- final int N = enabled.size();
+ final int enabledCount = enabled.size();
final String locale = mCurrentSubtype == null
? mRes.getConfiguration().locale.toString()
: mCurrentSubtype.getLocale();
- for (int i = 0; i < N; ++i) {
+ for (int i = 0; i < enabledCount; ++i) {
final InputMethodInfo imi = enabled.get(i);
if (imi.getSubtypeCount() > 0 && imi.isSystem()) {
InputMethodSubtype keyboardSubtype =
@@ -4093,7 +4109,7 @@
targetLastImiId = imi.getId();
subtypeId = SubtypeUtils.getSubtypeIdFromHashCode(imi,
keyboardSubtype.hashCode());
- if(keyboardSubtype.getLocale().equals(locale)) {
+ if (keyboardSubtype.getLocale().equals(locale)) {
break;
}
}
@@ -4230,8 +4246,9 @@
* {@link InputMethodManager#getInputMethodWindowVisibleHeight()} and a dependency in
* {@link InputMethodService#onCreate()}.
*
- * <p>TODO(Bug 113914148): Check if we can remove this.</p>
* @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight(int)}
+ *
+ * @deprecated TODO(b/113914148): Check if we can remove this
*/
@Override
@Deprecated
@@ -4305,7 +4322,7 @@
+ " is already registered by " + info.mParentClient);
}
if (info == null) {
- if (!mWindowManagerInternal.isUidAllowedOnDisplay(childDisplayId, cs.uid)) {
+ if (!mWindowManagerInternal.isUidAllowedOnDisplay(childDisplayId, cs.mUid)) {
throw new SecurityException(cs + " cannot access to display #"
+ childDisplayId);
}
@@ -4314,12 +4331,12 @@
}
info.mMatrix.setValues(matrixValues);
- if (mCurClient == null || mCurClient.curSession == null) {
+ if (mCurClient == null || mCurClient.mCurSession == null) {
return;
}
Matrix matrix = null;
- int displayId = mCurClient.selfReportedDisplayId;
+ int displayId = mCurClient.mSelfReportedDisplayId;
boolean needToNotify = false;
while (true) {
needToNotify |= (displayId == childDisplayId);
@@ -4332,16 +4349,16 @@
} else {
matrix.postConcat(next.mMatrix);
}
- if (next.mParentClient.selfReportedDisplayId == mCurTokenDisplayId) {
+ if (next.mParentClient.mSelfReportedDisplayId == mCurTokenDisplayId) {
if (needToNotify) {
final float[] values = new float[9];
matrix.getValues(values);
- mCurClient.client.updateVirtualDisplayToScreenMatrix(
+ mCurClient.mClient.updateVirtualDisplayToScreenMatrix(
getSequenceNumberLocked(), values);
}
break;
}
- displayId = info.mParentClient.selfReportedDisplayId;
+ displayId = info.mParentClient.mSelfReportedDisplayId;
}
}
} catch (Throwable t) {
@@ -4493,7 +4510,7 @@
/**
* Starting point for dumping the IME tracing information in proto format.
*
- * @param clientProtoDump dump information from the IME client side
+ * @param protoDump dump information from the IME client side
*/
@BinderThread
@Override
@@ -4558,7 +4575,7 @@
}
for (ClientState state : clients.values()) {
if (state != null) {
- state.client.setImeTraceEnabled(true /* enabled */);
+ state.mClient.setImeTraceEnabled(true /* enabled */);
}
}
}
@@ -4573,7 +4590,7 @@
}
for (ClientState state : clients.values()) {
if (state != null) {
- state.client.setImeTraceEnabled(false /* enabled */);
+ state.mClient.setImeTraceEnabled(false /* enabled */);
}
}
}
@@ -4652,7 +4669,7 @@
// actual IME target.
mWindowManagerInternal.hideIme(
mHideRequestWindowMap.get(windowToken),
- mCurClient.selfReportedDisplayId);
+ mCurClient.mSelfReportedDisplayId);
}
} else {
// Send to window manager to show IME after IME layout finishes.
@@ -4683,7 +4700,7 @@
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(
"Using null token requires permission "
- + android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ + android.Manifest.permission.WRITE_SECURE_SETTINGS);
}
} else if (getCurTokenLocked() != token) {
Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
@@ -4751,14 +4768,14 @@
@GuardedBy("ImfLock.class")
void setEnabledSessionLocked(SessionState session) {
if (mEnabledSession != session) {
- if (mEnabledSession != null && mEnabledSession.session != null) {
+ if (mEnabledSession != null && mEnabledSession.mSession != null) {
if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession);
- mEnabledSession.method.setSessionEnabled(mEnabledSession.session, false);
+ mEnabledSession.mMethod.setSessionEnabled(mEnabledSession.mSession, false);
}
mEnabledSession = session;
- if (mEnabledSession != null && mEnabledSession.session != null) {
+ if (mEnabledSession != null && mEnabledSession.mSession != null) {
if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
- mEnabledSession.method.setSessionEnabled(mEnabledSession.session, true);
+ mEnabledSession.mMethod.setSessionEnabled(mEnabledSession.mSession, true);
}
}
}
@@ -4837,9 +4854,9 @@
case MSG_REMOVE_IME_SURFACE: {
synchronized (ImfLock.class) {
try {
- if (mEnabledSession != null && mEnabledSession.session != null
+ if (mEnabledSession != null && mEnabledSession.mSession != null
&& !mShowRequested) {
- mEnabledSession.session.removeImeSurface();
+ mEnabledSession.mSession.removeImeSurface();
}
} catch (RemoteException e) {
}
@@ -4851,8 +4868,8 @@
synchronized (ImfLock.class) {
try {
if (windowToken == mCurFocusedWindow
- && mEnabledSession != null && mEnabledSession.session != null) {
- mEnabledSession.session.removeImeSurface();
+ && mEnabledSession != null && mEnabledSession.mSession != null) {
+ mEnabledSession.mSession.removeImeSurface();
}
} catch (RemoteException e) {
}
@@ -4962,8 +4979,8 @@
updateSystemUiLocked(interactive ? mImeWindowVis : 0, mBackDisposition);
// Inform the current client of the change in active status
- if (mCurClient != null && mCurClient.client != null) {
- mCurClient.client.setActive(mIsInteractive, mInFullscreenMode,
+ if (mCurClient != null && mCurClient.mClient != null) {
+ mCurClient.mClient.setActive(mIsInteractive, mInFullscreenMode,
mImePlatformCompatUtils.shouldFinishInputWithReportToIme(
getCurMethodUidLocked()));
}
@@ -5073,8 +5090,8 @@
mContext.getPackageManager().queryIntentServicesAsUser(
new Intent(InputMethod.SERVICE_INTERFACE),
PackageManager.MATCH_DISABLED_COMPONENTS, mSettings.getCurrentUserId());
- final int N = allInputMethodServices.size();
- for (int i = 0; i < N; ++i) {
+ final int numImes = allInputMethodServices.size();
+ for (int i = 0; i < numImes; ++i) {
final ServiceInfo si = allInputMethodServices.get(i).serviceInfo;
if (android.Manifest.permission.BIND_INPUT_METHOD.equals(si.permission)) {
mMyPackageMonitor.addKnownImePackageNameLocked(si.packageName);
@@ -5088,8 +5105,8 @@
boolean enabledImeFound = false;
boolean enabledNonAuxImeFound = false;
final List<InputMethodInfo> enabledImes = mSettings.getEnabledInputMethodListLocked();
- final int N = enabledImes.size();
- for (int i = 0; i < N; ++i) {
+ final int numImes = enabledImes.size();
+ for (int i = 0; i < numImes; ++i) {
final InputMethodInfo imi = enabledImes.get(i);
if (mMethodList.contains(imi)) {
enabledImeFound = true;
@@ -5117,8 +5134,8 @@
final ArrayList<InputMethodInfo> defaultEnabledIme =
InputMethodInfoUtils.getDefaultEnabledImes(mContext, mMethodList,
reenableMinimumNonAuxSystemImes);
- final int N = defaultEnabledIme.size();
- for (int i = 0; i < N; ++i) {
+ final int numImes = defaultEnabledIme.size();
+ for (int i = 0; i < numImes; ++i) {
final InputMethodInfo imi = defaultEnabledIme.get(i);
if (DEBUG) {
Slog.d(TAG, "--- enable ime = " + imi);
@@ -5360,7 +5377,7 @@
if (userId == mSettings.getCurrentUserId()) {
if (!mMethodMap.containsKey(imeId)
|| !mSettings.getEnabledInputMethodListLocked()
- .contains(mMethodMap.get(imeId))) {
+ .contains(mMethodMap.get(imeId))) {
return false; // IME is not found or not enabled.
}
setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID);
@@ -5371,8 +5388,7 @@
mContext.getResources(), mContext.getContentResolver(), methodMap,
userId, false);
if (!methodMap.containsKey(imeId)
- || !settings.getEnabledInputMethodListLocked()
- .contains(methodMap.get(imeId))) {
+ || !settings.getEnabledInputMethodListLocked().contains(methodMap.get(imeId))) {
return false; // IME is not found or not enabled.
}
settings.putSelectedInputMethod(imeId);
@@ -5528,18 +5544,18 @@
attachNewAccessibilityLocked(StartInputReason.SESSION_CREATED_BY_ACCESSIBILITY,
true);
- final SessionState sessionState = mCurClient.curSession;
+ final SessionState sessionState = mCurClient.mCurSession;
final IInputMethodSession imeSession = sessionState == null
- ? null : sessionState.session;
+ ? null : sessionState.mSession;
final SparseArray<IAccessibilityInputMethodSession>
accessibilityInputMethodSessions =
- createAccessibilityInputMethodSessions(
- mCurClient.mAccessibilitySessions);
+ createAccessibilityInputMethodSessions(
+ mCurClient.mAccessibilitySessions);
final InputBindResult res = new InputBindResult(
InputBindResult.ResultCode.SUCCESS_WITH_ACCESSIBILITY_SESSION,
imeSession, accessibilityInputMethodSessions, null, getCurIdLocked(),
getSequenceNumberLocked(), mCurVirtualDisplayToScreenMatrix, false);
- mCurClient.client.onBindAccessibilityService(res, accessibilityConnectionId);
+ mCurClient.mClient.onBindAccessibilityService(res, accessibilityConnectionId);
}
}
}
@@ -5550,11 +5566,11 @@
if (mCurClient != null) {
if (DEBUG) {
Slog.v(TAG, "unbindAccessibilityFromCurrentClientLocked: client="
- + mCurClient.client.asBinder());
+ + mCurClient.mClient.asBinder());
}
// A11yManagerService unbinds the disabled accessibility service. We don't need
// to do it here.
- mCurClient.client.onUnbindAccessibilityService(getSequenceNumberLocked(),
+ mCurClient.mClient.onUnbindAccessibilityService(getSequenceNumberLocked(),
accessibilityConnectionId);
}
// We only have sessions when we bound to an input method. Remove this session
@@ -5620,7 +5636,7 @@
// This user ID can never bee spoofed.
final int imeUserId = UserHandle.getUserId(uid);
// This user ID can never bee spoofed.
- final int appUserId = UserHandle.getUserId(mCurClient.uid);
+ final int appUserId = UserHandle.getUserId(mCurClient.mUid);
// This user ID may be invalid if "contentUri" embedded an invalid user ID.
final int contentUriOwnerUserId = ContentProvider.getUserIdFromUri(contentUri,
imeUserId);
@@ -5642,9 +5658,9 @@
if (!calledWithValidTokenLocked(token)) {
return;
}
- if (mCurClient != null && mCurClient.client != null) {
+ if (mCurClient != null && mCurClient.mClient != null) {
mInFullscreenMode = fullscreen;
- mCurClient.client.reportFullscreenMode(fullscreen);
+ mCurClient.mClient.reportFullscreenMode(fullscreen);
}
}
}
@@ -5722,9 +5738,9 @@
synchronized (ImfLock.class) {
p.println("Current Input Method Manager state:");
- int N = mMethodList.size();
+ int numImes = mMethodList.size();
p.println(" Input Methods: mMethodMapUpdateCount=" + mMethodMapUpdateCount);
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < numImes; i++) {
InputMethodInfo info = mMethodList.get(i);
p.println(" InputMethod #" + i + ":");
info.dump(p, " ");
@@ -5734,20 +5750,20 @@
for (int i = 0; i < numClients; ++i) {
final ClientState ci = mClients.valueAt(i);
p.println(" Client " + ci + ":");
- p.println(" client=" + ci.client);
- p.println(" fallbackInputConnection=" + ci.fallbackInputConnection);
- p.println(" sessionRequested=" + ci.sessionRequested);
+ p.println(" client=" + ci.mClient);
+ p.println(" fallbackInputConnection=" + ci.mFallbackInputConnection);
+ p.println(" sessionRequested=" + ci.mSessionRequested);
p.println(" sessionRequestedForAccessibility="
+ ci.mSessionRequestedForAccessibility);
- p.println(" curSession=" + ci.curSession);
+ p.println(" curSession=" + ci.mCurSession);
}
p.println(" mCurMethodId=" + getSelectedMethodIdLocked());
client = mCurClient;
p.println(" mCurClient=" + client + " mCurSeq=" + getSequenceNumberLocked());
p.println(" mCurPerceptible=" + mCurPerceptible);
p.println(" mCurFocusedWindow=" + mCurFocusedWindow
- + " softInputMode=" +
- InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode)
+ + " softInputMode="
+ + InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode)
+ " client=" + mCurFocusedWindowClient);
focusedWindowClient = mCurFocusedWindowClient;
p.println(" mCurId=" + getCurIdLocked() + " mHaveConnection=" + hasConnectionLocked()
@@ -5791,7 +5807,7 @@
if (client != null) {
pw.flush();
try {
- TransferPipe.dumpAsync(client.client.asBinder(), fd, args);
+ TransferPipe.dumpAsync(client.mClient.asBinder(), fd, args);
} catch (IOException | RemoteException e) {
p.println("Failed to dump input method client: " + e);
}
@@ -5807,7 +5823,7 @@
p.println(" ");
pw.flush();
try {
- TransferPipe.dumpAsync(focusedWindowClient.client.asBinder(), fd, args);
+ TransferPipe.dumpAsync(focusedWindowClient.mClient.asBinder(), fd, args);
} catch (IOException | RemoteException e) {
p.println("Failed to dump input method client in focused window: " + e);
}
@@ -6359,7 +6375,7 @@
}
for (ClientState state : clients.values()) {
if (state != null) {
- state.client.setImeTraceEnabled(isImeTraceEnabled);
+ state.mClient.setImeTraceEnabled(isImeTraceEnabled);
}
}
return ShellCommandResult.SUCCESS;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 1369f27..172cf29 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2460,11 +2460,11 @@
SnoozeHelper snoozeHelper = new SnoozeHelper(getContext(), (userId, r, muteOnReturn) -> {
try {
if (DBG) {
- Slog.d(TAG, "Reposting " + r.getKey());
+ Slog.d(TAG, "Reposting " + r.getKey() + " " + muteOnReturn);
}
enqueueNotificationInternal(r.getSbn().getPackageName(), r.getSbn().getOpPkg(),
r.getSbn().getUid(), r.getSbn().getInitialPid(), r.getSbn().getTag(),
- r.getSbn().getId(), r.getSbn().getNotification(), userId, true);
+ r.getSbn().getId(), r.getSbn().getNotification(), userId, muteOnReturn);
} catch (Exception e) {
Slog.e(TAG, "Cannot un-snooze notification", e);
}
diff --git a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
index 683eaeb..372bcc6 100644
--- a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
@@ -46,9 +46,10 @@
private final boolean mAutoDetectionSupported;
private final int mSystemClockUpdateThresholdMillis;
- private final Instant mAutoTimeLowerBound;
+ private final Instant mAutoSuggestionLowerBound;
+ private final Instant mManualSuggestionLowerBound;
+ private final Instant mSuggestionUpperBound;
private final @Origin int[] mOriginPriorities;
- private final boolean mDeviceHasY2038Issue;
private final boolean mAutoDetectionEnabledSetting;
private final @UserIdInt int mUserId;
private final boolean mUserConfigAllowed;
@@ -56,9 +57,10 @@
private ConfigurationInternal(Builder builder) {
mAutoDetectionSupported = builder.mAutoDetectionSupported;
mSystemClockUpdateThresholdMillis = builder.mSystemClockUpdateThresholdMillis;
- mAutoTimeLowerBound = Objects.requireNonNull(builder.mAutoTimeLowerBound);
+ mAutoSuggestionLowerBound = Objects.requireNonNull(builder.mAutoSuggestionLowerBound);
+ mManualSuggestionLowerBound = Objects.requireNonNull(builder.mManualSuggestionLowerBound);
+ mSuggestionUpperBound = Objects.requireNonNull(builder.mSuggestionUpperBound);
mOriginPriorities = Objects.requireNonNull(builder.mOriginPriorities);
- mDeviceHasY2038Issue = builder.mDeviceHasY2038Issue;
mAutoDetectionEnabledSetting = builder.mAutoDetectionEnabledSetting;
mUserId = builder.mUserId;
@@ -80,14 +82,31 @@
}
/**
- * Returns the lower bound for valid automatic times. It is guaranteed to be in the past,
- * i.e. it is unrelated to the current system clock time.
+ * Returns the lower bound for valid automatic time suggestions. It is guaranteed to be in the
+ * past, i.e. it is unrelated to the current system clock time.
* It holds no other meaning; it could be related to when the device system image was built,
* or could be updated by a mainline module.
*/
@NonNull
- public Instant getAutoTimeLowerBound() {
- return mAutoTimeLowerBound;
+ public Instant getAutoSuggestionLowerBound() {
+ return mAutoSuggestionLowerBound;
+ }
+
+ /**
+ * Returns the lower bound for valid manual time suggestions. It is guaranteed to be in the
+ * past, i.e. it is unrelated to the current system clock time.
+ */
+ @NonNull
+ public Instant getManualSuggestionLowerBound() {
+ return mManualSuggestionLowerBound;
+ }
+
+ /**
+ * Returns the upper bound for valid time suggestions (manual and automatic).
+ */
+ @NonNull
+ public Instant getSuggestionUpperBound() {
+ return mSuggestionUpperBound;
}
/**
@@ -98,14 +117,6 @@
return mOriginPriorities;
}
- /**
- * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
- * defines time_t as a 32-bit signed integer for 32-bit processes).
- */
- public boolean getDeviceHasY2038Issue() {
- return mDeviceHasY2038Issue;
- }
-
/** Returns the value of the auto time detection enabled setting. */
public boolean getAutoDetectionEnabledSetting() {
return mAutoDetectionEnabledSetting;
@@ -207,16 +218,17 @@
&& mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting
&& mUserId == that.mUserId && mUserConfigAllowed == that.mUserConfigAllowed
&& mSystemClockUpdateThresholdMillis == that.mSystemClockUpdateThresholdMillis
- && mAutoTimeLowerBound.equals(that.mAutoTimeLowerBound)
- && mDeviceHasY2038Issue == that.mDeviceHasY2038Issue
+ && mAutoSuggestionLowerBound.equals(that.mAutoSuggestionLowerBound)
+ && mManualSuggestionLowerBound.equals(that.mManualSuggestionLowerBound)
+ && mSuggestionUpperBound.equals(that.mSuggestionUpperBound)
&& Arrays.equals(mOriginPriorities, that.mOriginPriorities);
}
@Override
public int hashCode() {
int result = Objects.hash(mAutoDetectionSupported, mAutoDetectionEnabledSetting, mUserId,
- mUserConfigAllowed, mSystemClockUpdateThresholdMillis, mAutoTimeLowerBound,
- mDeviceHasY2038Issue);
+ mUserConfigAllowed, mSystemClockUpdateThresholdMillis, mAutoSuggestionLowerBound,
+ mManualSuggestionLowerBound, mSuggestionUpperBound);
result = 31 * result + Arrays.hashCode(mOriginPriorities);
return result;
}
@@ -230,10 +242,13 @@
return "ConfigurationInternal{"
+ "mAutoDetectionSupported=" + mAutoDetectionSupported
+ ", mSystemClockUpdateThresholdMillis=" + mSystemClockUpdateThresholdMillis
- + ", mAutoTimeLowerBound=" + mAutoTimeLowerBound
- + "(" + mAutoTimeLowerBound.toEpochMilli() + ")"
+ + ", mAutoSuggestionLowerBound=" + mAutoSuggestionLowerBound
+ + "(" + mAutoSuggestionLowerBound.toEpochMilli() + ")"
+ + ", mManualSuggestionLowerBound=" + mManualSuggestionLowerBound
+ + "(" + mManualSuggestionLowerBound.toEpochMilli() + ")"
+ + ", mSuggestionUpperBound=" + mSuggestionUpperBound
+ + "(" + mSuggestionUpperBound.toEpochMilli() + ")"
+ ", mOriginPriorities=" + originPrioritiesString
- + ", mDeviceHasY2038Issue=" + mDeviceHasY2038Issue
+ ", mAutoDetectionEnabled=" + mAutoDetectionEnabledSetting
+ ", mUserId=" + mUserId
+ ", mUserConfigAllowed=" + mUserConfigAllowed
@@ -243,9 +258,10 @@
static final class Builder {
private boolean mAutoDetectionSupported;
private int mSystemClockUpdateThresholdMillis;
- @NonNull private Instant mAutoTimeLowerBound;
+ @NonNull private Instant mAutoSuggestionLowerBound;
+ @NonNull private Instant mManualSuggestionLowerBound;
+ @NonNull private Instant mSuggestionUpperBound;
@NonNull private @Origin int[] mOriginPriorities;
- private boolean mDeviceHasY2038Issue;
private boolean mAutoDetectionEnabledSetting;
private final @UserIdInt int mUserId;
@@ -263,9 +279,10 @@
this.mUserConfigAllowed = toCopy.mUserConfigAllowed;
this.mAutoDetectionSupported = toCopy.mAutoDetectionSupported;
this.mSystemClockUpdateThresholdMillis = toCopy.mSystemClockUpdateThresholdMillis;
- this.mAutoTimeLowerBound = toCopy.mAutoTimeLowerBound;
+ this.mAutoSuggestionLowerBound = toCopy.mAutoSuggestionLowerBound;
+ this.mManualSuggestionLowerBound = toCopy.mManualSuggestionLowerBound;
+ this.mSuggestionUpperBound = toCopy.mSuggestionUpperBound;
this.mOriginPriorities = toCopy.mOriginPriorities;
- this.mDeviceHasY2038Issue = toCopy.mDeviceHasY2038Issue;
this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
}
@@ -296,10 +313,26 @@
}
/**
- * Sets the lower bound for valid automatic times.
+ * Sets the lower bound for valid automatic time suggestions.
*/
- public Builder setAutoTimeLowerBound(@NonNull Instant autoTimeLowerBound) {
- mAutoTimeLowerBound = Objects.requireNonNull(autoTimeLowerBound);
+ public Builder setAutoSuggestionLowerBound(@NonNull Instant autoSuggestionLowerBound) {
+ mAutoSuggestionLowerBound = Objects.requireNonNull(autoSuggestionLowerBound);
+ return this;
+ }
+
+ /**
+ * Sets the lower bound for valid manual time suggestions.
+ */
+ public Builder setManualSuggestionLowerBound(@NonNull Instant manualSuggestionLowerBound) {
+ mManualSuggestionLowerBound = Objects.requireNonNull(manualSuggestionLowerBound);
+ return this;
+ }
+
+ /**
+ * Sets the upper bound for valid time suggestions (manual and automatic).
+ */
+ public Builder setSuggestionUpperBound(@NonNull Instant suggestionUpperBound) {
+ mSuggestionUpperBound = Objects.requireNonNull(suggestionUpperBound);
return this;
}
@@ -320,15 +353,6 @@
return this;
}
- /**
- * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
- * defines time_t as a 32-bit signed integer for 32-bit processes).
- */
- Builder setDeviceHasY2038Issue(boolean deviceHasY2038Issue) {
- mDeviceHasY2038Issue = deviceHasY2038Issue;
- return this;
- }
-
/** Returns a new {@link ConfigurationInternal}. */
@NonNull
ConfigurationInternal build() {
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
index e4f3a80..888304a 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
@@ -31,6 +31,7 @@
import android.app.time.TimeCapabilities;
import android.app.time.TimeCapabilitiesAndConfig;
import android.app.time.TimeConfiguration;
+import android.app.timedetector.TimeDetectorHelper;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -38,7 +39,6 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
-import android.os.Build;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -74,13 +74,6 @@
private static final @Origin int[]
DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES = { ORIGIN_TELEPHONY, ORIGIN_NETWORK };
- /**
- * Time in the past. If an automatic time suggestion is before this point, it is sure to be
- * incorrect.
- */
- private static final Instant TIME_LOWER_BOUND_DEFAULT = Instant.ofEpochMilli(
- Long.max(android.os.Environment.getRootDirectory().lastModified(), Build.TIME));
-
/** Device config keys that affect the {@link TimeDetectorService}. */
private static final Set<String> SERVER_FLAGS_KEYS_TO_WATCH = Set.of(
KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE,
@@ -237,14 +230,16 @@
@Override
@NonNull
public synchronized ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
+ TimeDetectorHelper timeDetectorHelper = TimeDetectorHelper.INSTANCE;
return new ConfigurationInternal.Builder(userId)
.setUserConfigAllowed(isUserConfigAllowed(userId))
.setAutoDetectionSupported(isAutoDetectionSupported())
.setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting())
.setSystemClockUpdateThresholdMillis(getSystemClockUpdateThresholdMillis())
- .setAutoTimeLowerBound(getAutoTimeLowerBound())
+ .setAutoSuggestionLowerBound(getAutoSuggestionLowerBound())
+ .setManualSuggestionLowerBound(timeDetectorHelper.getManualSuggestionLowerBound())
+ .setSuggestionUpperBound(timeDetectorHelper.getSuggestionUpperBound())
.setOriginPriorities(getOriginPriorities())
- .setDeviceHasY2038Issue(getDeviceHasY2038Issue())
.build();
}
@@ -291,9 +286,9 @@
}
@NonNull
- private Instant getAutoTimeLowerBound() {
+ private Instant getAutoSuggestionLowerBound() {
return mServerFlags.getOptionalInstant(KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE)
- .orElse(TIME_LOWER_BOUND_DEFAULT);
+ .orElse(TimeDetectorHelper.INSTANCE.getAutoSuggestionLowerBoundDefault());
}
@NonNull
@@ -310,10 +305,6 @@
return DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES;
}
- private boolean getDeviceHasY2038Issue() {
- return Build.SUPPORTED_32_BIT_ABIS.length > 0;
- }
-
/**
* A base supplier of an array of time origin integers in priority order.
* It handles memoization of the result to avoid repeated string parsing when nothing has
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 017306a..547cf9d 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -84,9 +84,6 @@
*/
private static final int KEEP_SUGGESTION_HISTORY_SIZE = 10;
- /** The value in Unix epoch milliseconds of the Y2038 issue. */
- private static final long Y2038_LIMIT_IN_MILLIS = 1000L * Integer.MAX_VALUE;
-
/**
* A log that records the decisions / decision metadata that affected the device's system clock
* time. This is logged in bug reports to assist with debugging issues with detection.
@@ -248,7 +245,7 @@
final TimestampedValue<Long> newUnixEpochTime = suggestion.getUnixEpochTime();
- if (!validateSuggestionTime(newUnixEpochTime, suggestion)) {
+ if (!validateManualSuggestionTime(newUnixEpochTime, suggestion)) {
return false;
}
@@ -424,7 +421,7 @@
}
@GuardedBy("this")
- private boolean validateSuggestionTime(
+ private boolean validateSuggestionCommon(
@NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
if (newUnixEpochTime.getValue() == null) {
Slog.w(LOG_TAG, "Suggested time value is null. suggestion=" + suggestion);
@@ -441,8 +438,8 @@
return false;
}
- if (newUnixEpochTime.getValue() > Y2038_LIMIT_IN_MILLIS
- && mCurrentConfigurationInternal.getDeviceHasY2038Issue()) {
+ if (newUnixEpochTime.getValue()
+ > mCurrentConfigurationInternal.getSuggestionUpperBound().toEpochMilli()) {
// This check won't prevent a device's system clock exceeding Integer.MAX_VALUE Unix
// seconds through the normal passage of time, but it will stop it jumping above 2038
// because of a "bad" suggestion. b/204193177
@@ -453,20 +450,40 @@
return true;
}
+ /**
+ * Returns {@code true} if an automatic time suggestion time is valid.
+ * See also {@link #validateManualSuggestionTime(TimestampedValue, Object)}.
+ */
@GuardedBy("this")
private boolean validateAutoSuggestionTime(
@NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
- return validateSuggestionTime(newUnixEpochTime, suggestion)
- && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion);
+ Instant lowerBound = mCurrentConfigurationInternal.getAutoSuggestionLowerBound();
+ return validateSuggestionCommon(newUnixEpochTime, suggestion)
+ && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion,
+ lowerBound);
+ }
+
+ /**
+ * Returns {@code true} if a manual time suggestion time is valid.
+ * See also {@link #validateAutoSuggestionTime(TimestampedValue, Object)}.
+ */
+ @GuardedBy("this")
+ private boolean validateManualSuggestionTime(
+ @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
+ Instant lowerBound = mCurrentConfigurationInternal.getManualSuggestionLowerBound();
+
+ // Suggestion is definitely wrong if it comes before lower time bound.
+ return validateSuggestionCommon(newUnixEpochTime, suggestion)
+ && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion, lowerBound);
}
@GuardedBy("this")
private boolean validateSuggestionAgainstLowerBound(
- @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
- Instant lowerBound = mCurrentConfigurationInternal.getAutoTimeLowerBound();
+ @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion,
+ @NonNull Instant lowerBound) {
// Suggestion is definitely wrong if it comes before lower time bound.
- if (lowerBound.isAfter(Instant.ofEpochMilli(newUnixEpochTime.getValue()))) {
+ if (lowerBound.toEpochMilli() > newUnixEpochTime.getValue()) {
Slog.w(LOG_TAG, "Suggestion points to time before lower bound, skipping it. "
+ "suggestion=" + suggestion + ", lower bound=" + lowerBound);
return false;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 59dbf22..f5c5a13 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -724,13 +724,15 @@
// used here because it may be cleared in setTargetRootTaskIfNeeded.
final ActivityOptions originalOptions = mRequest.activityOptions != null
? mRequest.activityOptions.getOriginalOptions() : null;
+ // Only track the launch time of activity that will be resumed.
+ final ActivityRecord launchingRecord = mDoResume ? mLastStartActivityRecord : null;
// If the new record is the one that started, a new activity has created.
- final boolean newActivityCreated = mStartActivity == mLastStartActivityRecord;
+ final boolean newActivityCreated = mStartActivity == launchingRecord;
// Notify ActivityMetricsLogger that the activity has launched.
// ActivityMetricsLogger will then wait for the windows to be drawn and populate
// WaitResult.
mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
- newActivityCreated, mLastStartActivityRecord, originalOptions);
+ newActivityCreated, launchingRecord, originalOptions);
if (mRequest.waitResult != null) {
mRequest.waitResult.result = res;
res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
@@ -1214,7 +1216,7 @@
}
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
- request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,
+ request.voiceInteractor, startFlags, checkedOptions,
inTask, inTaskFragment, restrictedBgActivity, intentGrants);
if (request.outActivity != null) {
@@ -1640,7 +1642,7 @@
*/
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- int startFlags, boolean doResume, ActivityOptions options, Task inTask,
+ int startFlags, ActivityOptions options, Task inTask,
TaskFragment inTaskFragment, boolean restrictedBgActivity,
NeededUriGrants intentGrants) {
int result = START_CANCELED;
@@ -1664,7 +1666,7 @@
try {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
- startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,
+ startFlags, options, inTask, inTaskFragment, restrictedBgActivity,
intentGrants);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
@@ -1808,10 +1810,10 @@
@VisibleForTesting
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- int startFlags, boolean doResume, ActivityOptions options, Task inTask,
+ int startFlags, ActivityOptions options, Task inTask,
TaskFragment inTaskFragment, boolean restrictedBgActivity,
NeededUriGrants intentGrants) {
- setInitialState(r, options, inTask, inTaskFragment, doResume, startFlags, sourceRecord,
+ setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,
voiceSession, voiceInteractor, restrictedBgActivity);
computeLaunchingTaskFlags();
@@ -2429,7 +2431,7 @@
}
private void setInitialState(ActivityRecord r, ActivityOptions options, Task inTask,
- TaskFragment inTaskFragment, boolean doResume, int startFlags,
+ TaskFragment inTaskFragment, int startFlags,
ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession,
IVoiceInteractor voiceInteractor, boolean restrictedBgActivity) {
reset(false /* clearRequest */);
@@ -2494,10 +2496,11 @@
// If the caller has asked not to resume at this point, we make note
// of this in the record so that we can skip it when trying to find
// the top running activity.
- mDoResume = doResume;
- if (!doResume || !r.showToCurrentUser() || mLaunchTaskBehind) {
+ if (!r.showToCurrentUser() || mLaunchTaskBehind) {
r.delayedResume = true;
mDoResume = false;
+ } else {
+ mDoResume = true;
}
if (mOptions != null) {
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 804ccc5..3d40f64 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -18,7 +18,6 @@
name: "services.net",
defaults: ["platform_service_defaults"],
srcs: [
- ":net-module-utils-srcs",
":services.net-sources",
],
static_libs: [
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
new file mode 100644
index 0000000..c7ccef2
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
@@ -0,0 +1,242 @@
+/*
+ * 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.server.job.controllers;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.AlarmManager;
+import android.app.job.JobInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManagerInternal;
+import android.os.Looper;
+import android.util.ArraySet;
+
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobStore;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+
+public class FlexibilityControllerTest {
+ private static final String SOURCE_PACKAGE = "com.android.frameworks.mockingservicestests";
+ private static final int SOURCE_USER_ID = 0;
+
+ private MockitoSession mMockingSession;
+ private FlexibilityController mFlexibilityController;
+ @Mock
+ private AlarmManager mAlarmManager;
+ @Mock
+ private Context mContext;
+ @Mock
+ private JobSchedulerService mJobSchedulerService;
+ private JobStore mJobStore;
+
+ @Before
+ public void setup() {
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .strictness(Strictness.LENIENT)
+ .mockStatic(LocalServices.class)
+ .startMocking();
+ // Called in StateController constructor.
+ when(mJobSchedulerService.getTestableContext()).thenReturn(mContext);
+ when(mJobSchedulerService.getLock()).thenReturn(mJobSchedulerService);
+ when(mJobSchedulerService.getConstants()).thenReturn(
+ mock(JobSchedulerService.Constants.class));
+ // Called in FlexibilityController constructor.
+ when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
+ when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
+ //used to get jobs by UID
+ mJobStore = JobStore.initAndGetForTesting(mContext, mContext.getFilesDir());
+ when(mJobSchedulerService.getJobStore()).thenReturn(mJobStore);
+ // Used in JobStatus.
+ doReturn(mock(PackageManagerInternal.class))
+ .when(() -> LocalServices.getService(PackageManagerInternal.class));
+ // Freeze the clocks at a moment in time
+ JobSchedulerService.sSystemClock =
+ Clock.fixed(Instant.ofEpochMilli(100L), ZoneOffset.UTC);
+ JobSchedulerService.sElapsedRealtimeClock =
+ Clock.fixed(Instant.ofEpochMilli(100L), ZoneOffset.UTC);
+ // Initialize real objects.
+ mFlexibilityController = new FlexibilityController(mJobSchedulerService);
+ }
+
+ @After
+ public void teardown() {
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+ }
+
+ private static JobInfo.Builder createJob(int id) {
+ return new JobInfo.Builder(id, new ComponentName("foo", "bar"));
+ }
+
+ private JobStatus createJobStatus(String testTag, JobInfo.Builder job) {
+ JobInfo jobInfo = job.build();
+ return JobStatus.createFromJobInfo(
+ jobInfo, 1000, SOURCE_PACKAGE, SOURCE_USER_ID, testTag);
+ }
+
+ @Test
+ public void testGetNextConstraintDropTimeElapsed() {
+ long nextTimeToDropNumConstraints;
+
+ // no delay, deadline
+ JobInfo.Builder jb = createJob(0).setOverrideDeadline(1000);
+ JobStatus js = createJobStatus("time", jb);
+ js.enqueueTime = 100L;
+
+ assertEquals(0, js.getEarliestRunTime());
+ assertEquals(1100L, js.getLatestRunTimeElapsed());
+ assertEquals(100L, js.enqueueTime);
+
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(600L, nextTimeToDropNumConstraints);
+ js.adjustNumRequiredFlexibleConstraints(-1);
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(700L, nextTimeToDropNumConstraints);
+ js.adjustNumRequiredFlexibleConstraints(-1);
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(800L, nextTimeToDropNumConstraints);
+
+ // delay, no deadline
+ jb = createJob(0).setMinimumLatency(800000L);
+ js = createJobStatus("time", jb);
+ js.enqueueTime = 100L;
+
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(130400100, nextTimeToDropNumConstraints);
+ js.adjustNumRequiredFlexibleConstraints(-1);
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(156320100L, nextTimeToDropNumConstraints);
+ js.adjustNumRequiredFlexibleConstraints(-1);
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(182240100L, nextTimeToDropNumConstraints);
+
+ // no delay, no deadline
+ jb = createJob(0);
+ js = createJobStatus("time", jb);
+ js.enqueueTime = 100L;
+
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(129600100, nextTimeToDropNumConstraints);
+ js.adjustNumRequiredFlexibleConstraints(-1);
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(155520100L, nextTimeToDropNumConstraints);
+ js.adjustNumRequiredFlexibleConstraints(-1);
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(181440100L, nextTimeToDropNumConstraints);
+
+ // delay, deadline
+ jb = createJob(0).setOverrideDeadline(1100).setMinimumLatency(100);
+ js = createJobStatus("time", jb);
+ js.enqueueTime = 100L;
+
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(700L, nextTimeToDropNumConstraints);
+ js.adjustNumRequiredFlexibleConstraints(-1);
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(800L, nextTimeToDropNumConstraints);
+ js.adjustNumRequiredFlexibleConstraints(-1);
+ nextTimeToDropNumConstraints = mFlexibilityController.getNextConstraintDropTimeElapsed(js);
+ assertEquals(900L, nextTimeToDropNumConstraints);
+ }
+
+ @Test
+ public void testWontStopJobFromRunning() {
+ JobStatus js = createJobStatus("testWontStopJobFromRunning", createJob(101));
+ // Stop satisfied constraints from causing a false positive.
+ js.adjustNumRequiredFlexibleConstraints(100);
+ synchronized (mFlexibilityController.mLock) {
+ when(mJobSchedulerService.isCurrentlyRunningLocked(js)).thenReturn(true);
+ assertTrue(mFlexibilityController.isFlexibilitySatisfiedLocked(js));
+ }
+ }
+
+ @Test
+ public void testFlexibilityTracker() {
+ FlexibilityController.FlexibilityTracker flexTracker =
+ mFlexibilityController.new
+ FlexibilityTracker(FlexibilityController.FLEXIBLE_CONSTRAINTS);
+
+ JobStatus[] jobs = new JobStatus[4];
+ JobInfo.Builder jb;
+ for (int i = 0; i < jobs.length; i++) {
+ jb = createJob(i);
+ if (i > 0) {
+ jb.setRequiresDeviceIdle(true);
+ }
+ if (i > 1) {
+ jb.setRequiresBatteryNotLow(true);
+ }
+ if (i > 2) {
+ jb.setRequiresCharging(true);
+ }
+ jobs[i] = createJobStatus("", jb);
+ flexTracker.add(jobs[i]);
+
+ }
+
+ ArrayList<ArraySet<JobStatus>> trackedJobs = flexTracker.getArrayList();
+ assertEquals(1, trackedJobs.get(0).size());
+ assertEquals(1, trackedJobs.get(1).size());
+ assertEquals(1, trackedJobs.get(2).size());
+ assertEquals(0, trackedJobs.get(3).size());
+
+ flexTracker.adjustJobsRequiredConstraints(jobs[0], -1);
+ assertEquals(1, trackedJobs.get(0).size());
+ assertEquals(2, trackedJobs.get(1).size());
+ assertEquals(0, trackedJobs.get(2).size());
+ assertEquals(0, trackedJobs.get(3).size());
+
+ flexTracker.adjustJobsRequiredConstraints(jobs[0], -1);
+ assertEquals(2, trackedJobs.get(0).size());
+ assertEquals(1, trackedJobs.get(1).size());
+ assertEquals(0, trackedJobs.get(2).size());
+ assertEquals(0, trackedJobs.get(3).size());
+
+ flexTracker.adjustJobsRequiredConstraints(jobs[0], -1);
+ assertEquals(1, trackedJobs.get(0).size());
+ assertEquals(1, trackedJobs.get(1).size());
+ assertEquals(0, trackedJobs.get(2).size());
+ assertEquals(0, trackedJobs.get(3).size());
+
+ flexTracker.remove(jobs[1]);
+ assertEquals(1, trackedJobs.get(0).size());
+ assertEquals(0, trackedJobs.get(1).size());
+ assertEquals(0, trackedJobs.get(2).size());
+ assertEquals(0, trackedJobs.get(3).size());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
index c3d40da..208f99a 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
@@ -45,7 +45,9 @@
private static final int ARBITRARY_USER_ID = 99999;
private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
- private static final Instant ARBITRARY_AUTO_TIME_LOWER_BOUND = Instant.ofEpochMilli(0);
+ private static final Instant ARBITRARY_SUGGESTION_LOWER_BOUND = Instant.ofEpochMilli(0);
+ private static final Instant ARBITRARY_SUGGESTION_UPPER_BOUND =
+ Instant.ofEpochMilli(Long.MAX_VALUE);
private static final @Origin int[] ARBITRARY_ORIGIN_PRIORITIES = { ORIGIN_NETWORK };
/**
@@ -59,9 +61,10 @@
.setUserConfigAllowed(true)
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(true)
.build();
{
@@ -110,9 +113,10 @@
.setUserConfigAllowed(false)
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(true)
.build();
{
@@ -159,9 +163,10 @@
.setUserConfigAllowed(true)
.setAutoDetectionSupported(false)
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(true)
.build();
{
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index b9c74ba..67c8c4f 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -69,7 +69,9 @@
private static final int ARBITRARY_USER_ID = 9999;
private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
- private static final Instant ARBITRARY_AUTO_TIME_LOWER_BOUND = Instant.ofEpochMilli(0);
+ private static final Instant ARBITRARY_SUGGESTION_LOWER_BOUND = Instant.ofEpochMilli(0);
+ private static final Instant ARBITRARY_SUGGESTION_UPPER_BOUND =
+ Instant.ofEpochMilli(Long.MAX_VALUE);
private static final int[] ARBITRARY_ORIGIN_PRIORITIES = { ORIGIN_NETWORK };
private Context mMockContext;
@@ -444,9 +446,10 @@
.setUserConfigAllowed(true)
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(autoDetectionEnabled)
.build();
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index aeb5c65..1aea672 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -53,7 +53,16 @@
private static final @UserIdInt int ARBITRARY_USER_ID = 9876;
private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
- private static final Instant TIME_LOWER_BOUND = createUnixEpochTime(2009, 1, 1, 12, 0, 0);
+ private static final Instant DEFAULT_SUGGESTION_LOWER_BOUND =
+ createUnixEpochTime(2005, 1, 1, 1, 0, 0);
+ /** A value after {@link #DEFAULT_SUGGESTION_LOWER_BOUND} */
+ private static final Instant TEST_SUGGESTION_LOWER_BOUND =
+ createUnixEpochTime(2006, 1, 1, 1, 0, 0);
+ private static final Instant DEFAULT_SUGGESTION_UPPER_BOUND =
+ createUnixEpochTime(2099, 12, 1, 1, 0, 0);
+ /** A value before {@link #DEFAULT_SUGGESTION_UPPER_BOUND} */
+ private static final Instant TEST_SUGGESTION_UPPER_BOUND =
+ createUnixEpochTime(2037, 12, 1, 1, 0, 0);
private static final TimestampedValue<Instant> ARBITRARY_CLOCK_INITIALIZATION_INFO =
new TimestampedValue<>(
@@ -77,9 +86,10 @@
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(
ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(false)
.build();
@@ -89,9 +99,10 @@
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(
ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
- .setAutoTimeLowerBound(TIME_LOWER_BOUND)
+ .setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+ .setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+ .setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
.setOriginPriorities(ORIGIN_PRIORITIES)
- .setDeviceHasY2038Issue(true)
.setAutoDetectionEnabledSetting(true)
.build();
@@ -344,22 +355,6 @@
}
@Test
- public void telephonyTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
-
- int slotIndex = ARBITRARY_SLOT_INDEX;
- Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
-
- TelephonyTimeSuggestion timeSuggestion =
- script.generateTelephonyTimeSuggestion(
- slotIndex, suggestedTime);
-
- script.simulateTelephonyTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestTelephonySuggestion(slotIndex, null);
- }
-
- @Test
public void testSuggestTelephonyTime_timeDetectionToggled() {
final int clockIncrementMillis = 100;
final int systemClockUpdateThresholdMillis = 2000;
@@ -453,6 +448,70 @@
}
@Test
+ public void testSuggestTelephonyTime_rejectedBelowLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setOriginPriorities(ORIGIN_TELEPHONY)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
+ TelephonyTimeSuggestion timeSuggestion =
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowLowerBound);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestTelephonyTime_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_TELEPHONY)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ TelephonyTimeSuggestion timeSuggestion =
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveLowerBound);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestTelephonyTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_TELEPHONY)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ TelephonyTimeSuggestion timeSuggestion =
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveUpperBound);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestTelephonyTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_TELEPHONY)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ TelephonyTimeSuggestion timeSuggestion =
+ script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowUpperBound);
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
+ }
+
+ @Test
public void testSuggestManualTime_autoTimeDisabled() {
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
@@ -530,7 +589,7 @@
}
@Test
- public void manualTimeSuggestion_isIgnored_whenAutoTimeEnabled() {
+ public void testSuggestManualTime_isIgnored_whenAutoTimeEnabled() {
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
ManualTimeSuggestion timeSuggestion =
@@ -543,16 +602,63 @@
}
@Test
- public void manualTimeSuggestion_ignoresTimeLowerBound() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
- Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+ public void testSuggestManualTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
- ManualTimeSuggestion timeSuggestion =
- script.generateManualTimeSuggestion(suggestedTime);
-
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveUpperBound);
script.simulateManualTimeSuggestion(
- ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
- .verifySystemClockWasSetAndResetCallTracking(suggestedTime.toEpochMilli());
+ ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestManualTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowUpperBound);
+ script.simulateManualTimeSuggestion(
+ ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestManualTime_rejectedBelowLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
+ ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowLowerBound);
+ script.simulateManualTimeSuggestion(
+ ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestManualTimes_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveLowerBound);
+ script.simulateManualTimeSuggestion(
+ ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
}
@Test
@@ -591,20 +697,67 @@
}
@Test
- public void networkTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+ public void testSuggestNetworkTime_rejectedBelowLowerBound() {
ConfigurationInternal configInternal =
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_NETWORK)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
Script script = new Script().simulateConfigurationInternalChange(configInternal);
- Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
NetworkTimeSuggestion timeSuggestion =
- script.generateNetworkTimeSuggestion(suggestedTime);
-
+ script.generateNetworkTimeSuggestion(belowLowerBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestNetworkSuggestion(null);
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestNetworkTime_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_NETWORK)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ NetworkTimeSuggestion timeSuggestion =
+ script.generateNetworkTimeSuggestion(aboveLowerBound);
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestNetworkTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_NETWORK)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ NetworkTimeSuggestion timeSuggestion =
+ script.generateNetworkTimeSuggestion(aboveUpperBound);
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestNetworkTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_NETWORK)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ NetworkTimeSuggestion timeSuggestion =
+ script.generateNetworkTimeSuggestion(belowUpperBound);
+ script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@Test
@@ -643,6 +796,70 @@
}
@Test
+ public void testSuggestGnssTime_rejectedBelowLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_GNSS)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
+ GnssTimeSuggestion timeSuggestion =
+ script.generateGnssTimeSuggestion(belowLowerBound);
+ script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestGnssTime_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_GNSS)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ GnssTimeSuggestion timeSuggestion =
+ script.generateGnssTimeSuggestion(aboveLowerBound);
+ script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestGnssTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_GNSS)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ GnssTimeSuggestion timeSuggestion =
+ script.generateGnssTimeSuggestion(aboveUpperBound);
+ script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestGnssTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_GNSS)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ GnssTimeSuggestion timeSuggestion =
+ script.generateGnssTimeSuggestion(belowUpperBound);
+ script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
+ }
+
+ @Test
public void testSuggestExternalTime_autoTimeEnabled() {
ConfigurationInternal configInternal =
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
@@ -678,20 +895,67 @@
}
@Test
- public void externalTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+ public void testSuggestExternalTime_rejectedBelowLowerBound() {
ConfigurationInternal configInternal =
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_EXTERNAL)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
Script script = new Script().simulateConfigurationInternalChange(configInternal);
- Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+ Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
ExternalTimeSuggestion timeSuggestion =
- script.generateExternalTimeSuggestion(suggestedTime);
-
+ script.generateExternalTimeSuggestion(belowLowerBound);
script.simulateExternalTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestExternalSuggestion(null);
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestExternalTime_notRejectedAboveLowerBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_EXTERNAL)
+ .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+ ExternalTimeSuggestion timeSuggestion =
+ script.generateExternalTimeSuggestion(aboveLowerBound);
+ script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+ }
+
+ @Test
+ public void testSuggestExternalTime_rejectedAboveUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_EXTERNAL)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+ ExternalTimeSuggestion timeSuggestion =
+ script.generateExternalTimeSuggestion(aboveUpperBound);
+ script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void testSuggestExternalTime_notRejectedBelowUpperBound() {
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+ .setOriginPriorities(ORIGIN_EXTERNAL)
+ .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+ .build();
+ Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+ Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+ ExternalTimeSuggestion timeSuggestion =
+ script.generateExternalTimeSuggestion(belowUpperBound);
+ script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@Test
@@ -1198,56 +1462,6 @@
.verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
}
- @Test
- public void manualY2038SuggestionsAreRejectedOnAffectedDevices() {
- ConfigurationInternal configInternal =
- new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
- .setOriginPriorities(ORIGIN_TELEPHONY)
- .setDeviceHasY2038Issue(true)
- .build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
-
- Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
- ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(y2038IssueTime);
- script.simulateManualTimeSuggestion(
- ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
- .verifySystemClockWasNotSetAndResetCallTracking();
- }
-
- @Test
- public void telephonyY2038SuggestionsAreRejectedOnAffectedDevices() {
- ConfigurationInternal configInternal =
- new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
- .setOriginPriorities(ORIGIN_TELEPHONY)
- .setDeviceHasY2038Issue(true)
- .build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
-
- final int slotIndex = 0;
- Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
- TelephonyTimeSuggestion timeSuggestion =
- script.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
- script.simulateTelephonyTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking();
- }
-
- @Test
- public void telephonyY2038SuggestionsAreNotRejectedOnUnaffectedDevices() {
- ConfigurationInternal configInternal =
- new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
- .setOriginPriorities(ORIGIN_TELEPHONY)
- .setDeviceHasY2038Issue(false)
- .build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
-
- final int slotIndex = 0;
- Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
- TelephonyTimeSuggestion timeSuggestion =
- script.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
- script.simulateTelephonyTimeSuggestion(timeSuggestion)
- .verifySystemClockWasSetAndResetCallTracking(y2038IssueTime.toEpochMilli());
- }
-
/**
* A fake implementation of {@link TimeDetectorStrategyImpl.Environment}. Besides tracking
* changes and behaving like the real thing should, it also asserts preconditions.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index fe3c26a..cd087e6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -1406,7 +1406,7 @@
ActivityRecord source, ActivityOptions options, Task inTask,
TaskFragment inTaskFragment) {
starter.startActivityInner(target, source, null /* voiceSession */,
- null /* voiceInteractor */, 0 /* startFlags */, true /* doResume */,
+ null /* voiceInteractor */, 0 /* startFlags */,
options, inTask, inTaskFragment, false /* restrictedBgActivity */,
null /* intentGrants */);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
index 47c2176..21197ba 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
@@ -184,7 +184,6 @@
/* voiceSession */null,
/* voiceInteractor */ null,
/* startFlags */ 0,
- /* doResume */true,
/* options */null,
/* inTask */null,
/* inTaskFragment */ null,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
index 0f809ee..470fa58 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
@@ -193,18 +193,22 @@
}
/** {@inheritDoc} */
+ @Test
@Ignore("Visibility changes depending on orientation and navigation mode")
override fun navBarLayerIsVisibleAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Visibility changes depending on orientation and navigation mode")
override fun navBarLayerPositionAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Visibility changes depending on orientation and navigation mode")
override fun statusBarLayerPositionAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Visibility changes depending on orientation and navigation mode")
override fun statusBarLayerIsVisibleAtStartAndEnd() { }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
index 242a884..220e4ca 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
@@ -91,6 +91,7 @@
override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
/** {@inheritDoc} */
+ @Test
@Ignore("Display is off at the start")
override fun navBarLayerPositionAtStartAndEnd() { }
@@ -105,6 +106,7 @@
}
/** {@inheritDoc} */
+ @Test
@Ignore("Display is off at the start")
override fun statusBarLayerPositionAtStartAndEnd() { }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
index 3619505..9ed1bde 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
@@ -117,6 +117,7 @@
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun navBarLayerPositionAtStartAndEnd() { }
@@ -131,6 +132,7 @@
}
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun statusBarLayerPositionAtStartAndEnd() { }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
index 5a4b369..1d8b0a6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
@@ -102,18 +102,22 @@
override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun navBarLayerPositionAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun statusBarLayerPositionAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun taskBarLayerIsVisibleAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun taskBarWindowIsAlwaysVisible() { }
@@ -135,6 +139,7 @@
fun statusBarLayerPositionAtEnd() = testSpec.statusBarLayerPositionAtEnd()
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun statusBarLayerIsVisibleAtStartAndEnd() { }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index c03cb56..1ad5426 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -132,22 +132,27 @@
}
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun taskBarLayerIsVisibleAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun navBarLayerIsVisibleAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun taskBarWindowIsAlwaysVisible() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun navBarWindowIsAlwaysVisible() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
override fun statusBarWindowIsAlwaysVisible() { }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index b2a2381..1e3caa4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -164,14 +164,17 @@
}
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. App is full screen")
override fun statusBarLayerPositionAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. App is full screen")
override fun statusBarLayerIsVisibleAtStartAndEnd() { }
/** {@inheritDoc} */
+ @Test
@Ignore("Not applicable to this CUJ. App is full screen")
override fun statusBarWindowIsAlwaysVisible() { }