Merge "AudioService: fix disconnect/connect of A2DP device"
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index e44e902..38bb75f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -25,7 +25,6 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.IUidObserver;
import android.app.job.IJobScheduler;
@@ -95,7 +94,6 @@
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
-import com.android.server.job.JobSchedulerServiceDumpProto.RegisteredJob;
import com.android.server.job.controllers.BackgroundJobsController;
import com.android.server.job.controllers.BatteryController;
import com.android.server.job.controllers.ConnectivityController;
@@ -117,7 +115,6 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -240,18 +237,7 @@
final SparseIntArray mBackingUpUids = new SparseIntArray();
/**
- * Count standby heartbeats, and keep track of which beat each bucket's jobs will
- * next become runnable. Index into this array is by normalized bucket:
- * { ACTIVE, WORKING, FREQUENT, RARE, NEVER }. The ACTIVE and NEVER bucket
- * milestones are not updated: ACTIVE apps get jobs whenever they ask for them,
- * and NEVER apps don't get them at all.
- */
- final long[] mNextBucketHeartbeat = { 0, 0, 0, 0, Long.MAX_VALUE };
- long mHeartbeat = 0;
- long mLastHeartbeatTime = sElapsedRealtimeClock.millis();
-
- /**
- * Named indices into the STANDBY_BEATS array, for clarity in referring to
+ * Named indices into standby bucket arrays, for clarity in referring to
* specific buckets' bookkeeping.
*/
public static final int ACTIVE_INDEX = 0;
@@ -260,21 +246,6 @@
public static final int RARE_INDEX = 3;
public static final int NEVER_INDEX = 4;
- /**
- * Bookkeeping about when jobs last run. We keep our own record in heartbeat time,
- * rather than rely on Usage Stats' timestamps, because heartbeat time can be
- * manipulated for testing purposes and we need job runnability to track that rather
- * than real time.
- *
- * Outer SparseArray slices by user handle; inner map of package name to heartbeat
- * is a HashMap<> rather than ArrayMap<> because we expect O(hundreds) of keys
- * and it will be accessed in a known-hot code path.
- */
- final SparseArray<HashMap<String, Long>> mLastJobHeartbeats = new SparseArray<>();
-
- static final String HEARTBEAT_TAG = "*job.heartbeat*";
- final HeartbeatAlarmListener mHeartbeatAlarm = new HeartbeatAlarmListener();
-
// -- Pre-allocated temporaries only for use in assignJobsToContextsLocked --
private class ConstantsObserver extends ContentObserver {
@@ -311,11 +282,6 @@
Slog.e(TAG, "Bad jobscheduler settings", e);
}
}
-
- if (mConstants.USE_HEARTBEATS) {
- // Reset the heartbeat alarm based on the new heartbeat duration
- setNextHeartbeatAlarm();
- }
}
}
@@ -465,13 +431,15 @@
private static final String KEY_MAX_WORK_RESCHEDULE_COUNT = "max_work_reschedule_count";
private static final String KEY_MIN_LINEAR_BACKOFF_TIME = "min_linear_backoff_time";
private static final String KEY_MIN_EXP_BACKOFF_TIME = "min_exp_backoff_time";
- private static final String KEY_STANDBY_HEARTBEAT_TIME = "standby_heartbeat_time";
- private static final String KEY_STANDBY_WORKING_BEATS = "standby_working_beats";
- private static final String KEY_STANDBY_FREQUENT_BEATS = "standby_frequent_beats";
- private static final String KEY_STANDBY_RARE_BEATS = "standby_rare_beats";
+ private static final String DEPRECATED_KEY_STANDBY_HEARTBEAT_TIME =
+ "standby_heartbeat_time";
+ private static final String DEPRECATED_KEY_STANDBY_WORKING_BEATS = "standby_working_beats";
+ private static final String DEPRECATED_KEY_STANDBY_FREQUENT_BEATS =
+ "standby_frequent_beats";
+ private static final String DEPRECATED_KEY_STANDBY_RARE_BEATS = "standby_rare_beats";
private static final String KEY_CONN_CONGESTION_DELAY_FRAC = "conn_congestion_delay_frac";
private static final String KEY_CONN_PREFETCH_RELAX_FRAC = "conn_prefetch_relax_frac";
- private static final String KEY_USE_HEARTBEATS = "use_heartbeats";
+ private static final String DEPRECATED_KEY_USE_HEARTBEATS = "use_heartbeats";
private static final int DEFAULT_MIN_IDLE_COUNT = 1;
private static final int DEFAULT_MIN_CHARGING_COUNT = 1;
@@ -488,13 +456,8 @@
private static final int DEFAULT_MAX_WORK_RESCHEDULE_COUNT = Integer.MAX_VALUE;
private static final long DEFAULT_MIN_LINEAR_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS;
private static final long DEFAULT_MIN_EXP_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS;
- private static final long DEFAULT_STANDBY_HEARTBEAT_TIME = 11 * 60 * 1000L;
- private static final int DEFAULT_STANDBY_WORKING_BEATS = 11; // ~ 2 hours, with 11min beats
- private static final int DEFAULT_STANDBY_FREQUENT_BEATS = 43; // ~ 8 hours
- private static final int DEFAULT_STANDBY_RARE_BEATS = 130; // ~ 24 hours
private static final float DEFAULT_CONN_CONGESTION_DELAY_FRAC = 0.5f;
private static final float DEFAULT_CONN_PREFETCH_RELAX_FRAC = 0.5f;
- private static final boolean DEFAULT_USE_HEARTBEATS = false;
/**
* Minimum # of idle jobs that must be ready in order to force the JMS to schedule things
@@ -617,26 +580,7 @@
* The minimum backoff time to allow for exponential backoff.
*/
long MIN_EXP_BACKOFF_TIME = DEFAULT_MIN_EXP_BACKOFF_TIME;
- /**
- * How often we recalculate runnability based on apps' standby bucket assignment.
- * This should be prime relative to common time interval lengths such as a quarter-
- * hour or day, so that the heartbeat drifts relative to wall-clock milestones.
- */
- long STANDBY_HEARTBEAT_TIME = DEFAULT_STANDBY_HEARTBEAT_TIME;
- /**
- * Mapping: standby bucket -> number of heartbeats between each sweep of that
- * bucket's jobs.
- *
- * Bucket assignments as recorded in the JobStatus objects are normalized to be
- * indices into this array, rather than the raw constants used
- * by AppIdleHistory.
- */
- final int[] STANDBY_BEATS = {
- 0,
- DEFAULT_STANDBY_WORKING_BEATS,
- DEFAULT_STANDBY_FREQUENT_BEATS,
- DEFAULT_STANDBY_RARE_BEATS
- };
+
/**
* The fraction of a job's running window that must pass before we
* consider running it when the network is congested.
@@ -647,11 +591,6 @@
* we consider matching it against a metered network.
*/
public float CONN_PREFETCH_RELAX_FRAC = DEFAULT_CONN_PREFETCH_RELAX_FRAC;
- /**
- * Whether to use heartbeats or rolling window for quota management. True will use
- * heartbeats, false will use a rolling window.
- */
- public boolean USE_HEARTBEATS = DEFAULT_USE_HEARTBEATS;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -709,19 +648,10 @@
DEFAULT_MIN_LINEAR_BACKOFF_TIME);
MIN_EXP_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_EXP_BACKOFF_TIME,
DEFAULT_MIN_EXP_BACKOFF_TIME);
- STANDBY_HEARTBEAT_TIME = mParser.getDurationMillis(KEY_STANDBY_HEARTBEAT_TIME,
- DEFAULT_STANDBY_HEARTBEAT_TIME);
- STANDBY_BEATS[WORKING_INDEX] = mParser.getInt(KEY_STANDBY_WORKING_BEATS,
- DEFAULT_STANDBY_WORKING_BEATS);
- STANDBY_BEATS[FREQUENT_INDEX] = mParser.getInt(KEY_STANDBY_FREQUENT_BEATS,
- DEFAULT_STANDBY_FREQUENT_BEATS);
- STANDBY_BEATS[RARE_INDEX] = mParser.getInt(KEY_STANDBY_RARE_BEATS,
- DEFAULT_STANDBY_RARE_BEATS);
CONN_CONGESTION_DELAY_FRAC = mParser.getFloat(KEY_CONN_CONGESTION_DELAY_FRAC,
DEFAULT_CONN_CONGESTION_DELAY_FRAC);
CONN_PREFETCH_RELAX_FRAC = mParser.getFloat(KEY_CONN_PREFETCH_RELAX_FRAC,
DEFAULT_CONN_PREFETCH_RELAX_FRAC);
- USE_HEARTBEATS = mParser.getBoolean(KEY_USE_HEARTBEATS, DEFAULT_USE_HEARTBEATS);
}
void dump(IndentingPrintWriter pw) {
@@ -757,17 +687,8 @@
pw.printPair(KEY_MAX_WORK_RESCHEDULE_COUNT, MAX_WORK_RESCHEDULE_COUNT).println();
pw.printPair(KEY_MIN_LINEAR_BACKOFF_TIME, MIN_LINEAR_BACKOFF_TIME).println();
pw.printPair(KEY_MIN_EXP_BACKOFF_TIME, MIN_EXP_BACKOFF_TIME).println();
- pw.printPair(KEY_STANDBY_HEARTBEAT_TIME, STANDBY_HEARTBEAT_TIME).println();
- pw.print("standby_beats={");
- pw.print(STANDBY_BEATS[0]);
- for (int i = 1; i < STANDBY_BEATS.length; i++) {
- pw.print(", ");
- pw.print(STANDBY_BEATS[i]);
- }
- pw.println('}');
pw.printPair(KEY_CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC).println();
pw.printPair(KEY_CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC).println();
- pw.printPair(KEY_USE_HEARTBEATS, USE_HEARTBEATS).println();
pw.decreaseIndent();
}
@@ -797,13 +718,8 @@
proto.write(ConstantsProto.MAX_WORK_RESCHEDULE_COUNT, MAX_WORK_RESCHEDULE_COUNT);
proto.write(ConstantsProto.MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME);
proto.write(ConstantsProto.MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME);
- proto.write(ConstantsProto.STANDBY_HEARTBEAT_TIME_MS, STANDBY_HEARTBEAT_TIME);
- for (int period : STANDBY_BEATS) {
- proto.write(ConstantsProto.STANDBY_BEATS, period);
- }
proto.write(ConstantsProto.CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC);
proto.write(ConstantsProto.CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC);
- proto.write(ConstantsProto.USE_HEARTBEATS, USE_HEARTBEATS);
}
}
@@ -1441,9 +1357,6 @@
mAppStateTracker = Preconditions.checkNotNull(
LocalServices.getService(AppStateTracker.class));
- if (mConstants.USE_HEARTBEATS) {
- setNextHeartbeatAlarm();
- }
// Register br for package removals and user removals.
final IntentFilter filter = new IntentFilter();
@@ -1647,7 +1560,7 @@
}
delayMillis =
Math.min(delayMillis, JobInfo.MAX_BACKOFF_DELAY_MILLIS);
- JobStatus newJob = new JobStatus(failureToReschedule, getCurrentHeartbeat(),
+ JobStatus newJob = new JobStatus(failureToReschedule,
elapsedNowMillis + delayMillis,
JobStatus.NO_LATEST_RUNTIME, backoffAttempts,
failureToReschedule.getLastSuccessfulRunTime(), sSystemClock.millis());
@@ -1682,8 +1595,7 @@
* {@link com.android.server.job.JobServiceContext#EXECUTING_TIMESLICE_MILLIS}, but will lead
* to underscheduling at least, rather than if we had taken the last execution time to be the
* start of the execution.
- * <p>Unlike a reschedule prior to execution, in this case we advance the next-heartbeat
- * tracking as though the job were newly-scheduled.
+ *
* @return A new job representing the execution criteria for this instantiation of the
* recurring job.
*/
@@ -1736,7 +1648,7 @@
if (newLatestRuntimeElapsed < elapsedNow) {
Slog.wtf(TAG, "Rescheduling calculated latest runtime in the past: "
+ newLatestRuntimeElapsed);
- return new JobStatus(periodicToReschedule, getCurrentHeartbeat(),
+ return new JobStatus(periodicToReschedule,
elapsedNow + period - flex, elapsedNow + period,
0 /* backoffAttempt */,
sSystemClock.millis() /* lastSuccessfulRunTime */,
@@ -1751,64 +1663,13 @@
newEarliestRunTimeElapsed / 1000 + ", " + newLatestRuntimeElapsed / 1000
+ "]s");
}
- return new JobStatus(periodicToReschedule, getCurrentHeartbeat(),
+ return new JobStatus(periodicToReschedule,
newEarliestRunTimeElapsed, newLatestRuntimeElapsed,
0 /* backoffAttempt */,
sSystemClock.millis() /* lastSuccessfulRunTime */,
periodicToReschedule.getLastFailedRunTime());
}
- /*
- * We default to "long enough ago that every bucket's jobs are immediately runnable" to
- * avoid starvation of apps in uncommon-use buckets that might arise from repeated
- * reboot behavior.
- */
- long heartbeatWhenJobsLastRun(String packageName, final @UserIdInt int userId) {
- // The furthest back in pre-boot time that we need to bother with
- long heartbeat = -mConstants.STANDBY_BEATS[RARE_INDEX];
- boolean cacheHit = false;
- synchronized (mLock) {
- HashMap<String, Long> jobPackages = mLastJobHeartbeats.get(userId);
- if (jobPackages != null) {
- long cachedValue = jobPackages.getOrDefault(packageName, Long.MAX_VALUE);
- if (cachedValue < Long.MAX_VALUE) {
- cacheHit = true;
- heartbeat = cachedValue;
- }
- }
- if (!cacheHit) {
- // We haven't seen it yet; ask usage stats about it
- final long timeSinceJob = mUsageStats.getTimeSinceLastJobRun(packageName, userId);
- if (timeSinceJob < Long.MAX_VALUE) {
- // Usage stats knows about it from before, so calculate back from that
- // and go from there.
- heartbeat = mHeartbeat - (timeSinceJob / mConstants.STANDBY_HEARTBEAT_TIME);
- }
- // If usage stats returned its "not found" MAX_VALUE, we still have the
- // negative default 'heartbeat' value we established above
- setLastJobHeartbeatLocked(packageName, userId, heartbeat);
- }
- }
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Last job heartbeat " + heartbeat + " for "
- + packageName + "/" + userId);
- }
- return heartbeat;
- }
-
- long heartbeatWhenJobsLastRun(JobStatus job) {
- return heartbeatWhenJobsLastRun(job.getSourcePackageName(), job.getSourceUserId());
- }
-
- void setLastJobHeartbeatLocked(String packageName, int userId, long heartbeat) {
- HashMap<String, Long> jobPackages = mLastJobHeartbeats.get(userId);
- if (jobPackages == null) {
- jobPackages = new HashMap<>();
- mLastJobHeartbeats.put(userId, jobPackages);
- }
- jobPackages.put(packageName, heartbeat);
- }
-
// JobCompletedListener implementations.
/**
@@ -2176,82 +2037,6 @@
mMaybeQueueFunctor.postProcess();
}
- /**
- * Heartbeat tracking. The heartbeat alarm is intentionally non-wakeup.
- */
- class HeartbeatAlarmListener implements AlarmManager.OnAlarmListener {
-
- @Override
- public void onAlarm() {
- synchronized (mLock) {
- final long sinceLast = sElapsedRealtimeClock.millis() - mLastHeartbeatTime;
- final long beatsElapsed = sinceLast / mConstants.STANDBY_HEARTBEAT_TIME;
- if (beatsElapsed > 0) {
- mLastHeartbeatTime += beatsElapsed * mConstants.STANDBY_HEARTBEAT_TIME;
- advanceHeartbeatLocked(beatsElapsed);
- }
- }
- setNextHeartbeatAlarm();
- }
- }
-
- // Intentionally does not touch the alarm timing
- void advanceHeartbeatLocked(long beatsElapsed) {
- if (!mConstants.USE_HEARTBEATS) {
- return;
- }
- mHeartbeat += beatsElapsed;
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Advancing standby heartbeat by " + beatsElapsed
- + " to " + mHeartbeat);
- }
- // Don't update ACTIVE or NEVER bucket milestones. Note that mHeartbeat
- // will be equal to mNextBucketHeartbeat[bucket] for one beat, during which
- // new jobs scheduled by apps in that bucket will be permitted to run
- // immediately.
- boolean didAdvanceBucket = false;
- for (int i = 1; i < mNextBucketHeartbeat.length - 1; i++) {
- // Did we reach or cross a bucket boundary?
- if (mHeartbeat >= mNextBucketHeartbeat[i]) {
- didAdvanceBucket = true;
- }
- while (mHeartbeat > mNextBucketHeartbeat[i]) {
- mNextBucketHeartbeat[i] += mConstants.STANDBY_BEATS[i];
- }
- if (DEBUG_STANDBY) {
- Slog.v(TAG, " Bucket " + i + " next heartbeat "
- + mNextBucketHeartbeat[i]);
- }
- }
-
- if (didAdvanceBucket) {
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Hit bucket boundary; reevaluating job runnability");
- }
- mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
- }
- }
-
- void setNextHeartbeatAlarm() {
- final long heartbeatLength;
- synchronized (mLock) {
- if (!mConstants.USE_HEARTBEATS) {
- return;
- }
- heartbeatLength = mConstants.STANDBY_HEARTBEAT_TIME;
- }
- final long now = sElapsedRealtimeClock.millis();
- final long nextBeatOrdinal = (now + heartbeatLength) / heartbeatLength;
- final long nextHeartbeat = nextBeatOrdinal * heartbeatLength;
- if (DEBUG_STANDBY) {
- Slog.i(TAG, "Setting heartbeat alarm for " + nextHeartbeat
- + " = " + TimeUtils.formatDuration(nextHeartbeat - now));
- }
- AlarmManager am = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
- am.setExact(AlarmManager.ELAPSED_REALTIME, nextHeartbeat,
- HEARTBEAT_TAG, mHeartbeatAlarm, mHandler);
- }
-
/** Returns true if both the calling and source users for the job are started. */
private boolean areUsersStartedLocked(final JobStatus job) {
boolean sourceStarted = ArrayUtils.contains(mStartedUsers, job.getSourceUserId());
@@ -2323,54 +2108,6 @@
return false;
}
- if (mConstants.USE_HEARTBEATS) {
- // If the app is in a non-active standby bucket, make sure we've waited
- // an appropriate amount of time since the last invocation. During device-
- // wide parole, standby bucketing is ignored.
- //
- // Jobs in 'active' apps are not subject to standby, nor are jobs that are
- // specifically marked as exempt.
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
- + " parole=" + mInParole + " active=" + job.uidActive
- + " exempt=" + job.getJob().isExemptedFromAppStandby());
- }
- if (!mInParole
- && !job.uidActive
- && !job.getJob().isExemptedFromAppStandby()) {
- final int bucket = job.getStandbyBucket();
- if (DEBUG_STANDBY) {
- Slog.v(TAG, " bucket=" + bucket + " heartbeat=" + mHeartbeat
- + " next=" + mNextBucketHeartbeat[bucket]);
- }
- if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
- // Only skip this job if the app is still waiting for the end of its nominal
- // bucket interval. Once it's waited that long, we let it go ahead and clear.
- // The final (NEVER) bucket is special; we never age those apps' jobs into
- // runnability.
- final long appLastRan = heartbeatWhenJobsLastRun(job);
- if (bucket >= mConstants.STANDBY_BEATS.length
- || (mHeartbeat > appLastRan
- && mHeartbeat < appLastRan + mConstants.STANDBY_BEATS[bucket])) {
- if (job.getWhenStandbyDeferred() == 0) {
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
- + (appLastRan + mConstants.STANDBY_BEATS[bucket])
- + " for " + job);
- }
- job.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
- }
- return false;
- } else {
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Bucket deferred job aged into runnability at "
- + mHeartbeat + " : " + job);
- }
- }
- }
- }
- }
-
// The expensive check: validate that the defined package+service is
// still present & viable.
return isComponentUsable(job);
@@ -2439,9 +2176,6 @@
// Job pending/active doesn't affect the readiness of a job.
- // Skipping the heartbeat check as this will only come into play when using the rolling
- // window quota management system.
-
// The expensive check: validate that the defined package+service is
// still present & viable.
return isComponentUsable(job);
@@ -2450,9 +2184,6 @@
/** Returns the maximum amount of time this job could run for. */
public long getMaxJobExecutionTimeMs(JobStatus job) {
synchronized (mLock) {
- if (mConstants.USE_HEARTBEATS) {
- return JobServiceContext.EXECUTING_TIMESLICE_MILLIS;
- }
return Math.min(mQuotaController.getMaxJobExecutionTimeMsLocked(job),
JobServiceContext.EXECUTING_TIMESLICE_MILLIS);
}
@@ -2498,56 +2229,6 @@
final class LocalService implements JobSchedulerInternal {
/**
- * The current bucket heartbeat ordinal
- */
- public long currentHeartbeat() {
- return getCurrentHeartbeat();
- }
-
- /**
- * Heartbeat ordinal at which the given standby bucket's jobs next become runnable
- */
- public long nextHeartbeatForBucket(int bucket) {
- synchronized (mLock) {
- return mNextBucketHeartbeat[bucket];
- }
- }
-
- /**
- * Heartbeat ordinal for the given app. This is typically the heartbeat at which
- * the app last ran jobs, so that a newly-scheduled job in an app that hasn't run
- * jobs in a long time is immediately runnable even if the app is bucketed into
- * an infrequent time allocation.
- */
- public long baseHeartbeatForApp(String packageName, @UserIdInt int userId,
- final int appStandbyBucket) {
- if (appStandbyBucket == 0 ||
- appStandbyBucket >= mConstants.STANDBY_BEATS.length) {
- // ACTIVE => everything can be run right away
- // NEVER => we won't run them anyway, so let them go in the future
- // as soon as the app enters normal use
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Base heartbeat forced ZERO for new job in "
- + packageName + "/" + userId);
- }
- return 0;
- }
-
- final long baseHeartbeat = heartbeatWhenJobsLastRun(packageName, userId);
- if (DEBUG_STANDBY) {
- Slog.v(TAG, "Base heartbeat " + baseHeartbeat + " for new job in "
- + packageName + "/" + userId);
- }
- return baseHeartbeat;
- }
-
- public void noteJobStart(String packageName, int userId) {
- synchronized (mLock) {
- setLastJobHeartbeatLocked(packageName, userId, mHeartbeat);
- }
- }
-
- /**
* Returns a list of all pending jobs. A running job is not considered pending. Periodic
* jobs are always considered pending.
*/
@@ -3158,12 +2839,6 @@
}
}
- long getCurrentHeartbeat() {
- synchronized (mLock) {
- return mHeartbeat;
- }
- }
-
// Shell command infrastructure
int getJobState(PrintWriter pw, String pkgName, int userId, int jobId) {
try {
@@ -3249,21 +2924,6 @@
return 0;
}
- // Shell command infrastructure
- int executeHeartbeatCommand(PrintWriter pw, int numBeats) {
- if (numBeats < 1) {
- pw.println(getCurrentHeartbeat());
- return 0;
- }
-
- pw.print("Advancing standby heartbeat by ");
- pw.println(numBeats);
- synchronized (mLock) {
- advanceHeartbeatLocked(numBeats);
- }
- return 0;
- }
-
void triggerDockState(boolean idleState) {
final Intent dockIntent;
if (idleState) {
@@ -3319,20 +2979,6 @@
}
pw.println();
- pw.println(" Heartbeat:");
- pw.print(" Current: "); pw.println(mHeartbeat);
- pw.println(" Next");
- pw.print(" ACTIVE: "); pw.println(mNextBucketHeartbeat[0]);
- pw.print(" WORKING: "); pw.println(mNextBucketHeartbeat[1]);
- pw.print(" FREQUENT: "); pw.println(mNextBucketHeartbeat[2]);
- pw.print(" RARE: "); pw.println(mNextBucketHeartbeat[3]);
- pw.print(" Last heartbeat: ");
- TimeUtils.formatDuration(mLastHeartbeatTime, nowElapsed, pw);
- pw.println();
- pw.print(" Next heartbeat: ");
- TimeUtils.formatDuration(mLastHeartbeatTime + mConstants.STANDBY_HEARTBEAT_TIME,
- nowElapsed, pw);
- pw.println();
pw.print(" In parole?: ");
pw.print(mInParole);
pw.println();
@@ -3358,9 +3004,6 @@
}
job.dump(pw, " ", true, nowElapsed);
- pw.print(" Last run heartbeat: ");
- pw.print(heartbeatWhenJobsLastRun(job));
- pw.println();
pw.print(" Ready: ");
pw.print(isReadyToBeExecutedLocked(job));
@@ -3514,15 +3157,6 @@
}
proto.end(settingsToken);
- proto.write(JobSchedulerServiceDumpProto.CURRENT_HEARTBEAT, mHeartbeat);
- proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[0]);
- proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[1]);
- proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[2]);
- proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT, mNextBucketHeartbeat[3]);
- proto.write(JobSchedulerServiceDumpProto.LAST_HEARTBEAT_TIME_MILLIS,
- mLastHeartbeatTime - nowUptime);
- proto.write(JobSchedulerServiceDumpProto.NEXT_HEARTBEAT_TIME_MILLIS,
- mLastHeartbeatTime + mConstants.STANDBY_HEARTBEAT_TIME - nowUptime);
proto.write(JobSchedulerServiceDumpProto.IN_PAROLE, mInParole);
proto.write(JobSchedulerServiceDumpProto.IN_THERMAL, mThermalConstraint);
@@ -3564,7 +3198,6 @@
}
proto.write(JobSchedulerServiceDumpProto.RegisteredJob.IS_COMPONENT_PRESENT,
componentPresent);
- proto.write(RegisteredJob.LAST_RUN_HEARTBEAT, heartbeatWhenJobsLastRun(job));
proto.end(rjToken);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index e361441..01d158ba 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -340,15 +340,8 @@
private int doHeartbeat(PrintWriter pw) throws Exception {
checkPermission("manipulate scheduler heartbeat");
- final String arg = getNextArg();
- final int numBeats = (arg != null) ? Integer.parseInt(arg) : 0;
-
- final long ident = Binder.clearCallingIdentity();
- try {
- return mInternal.executeHeartbeatCommand(pw, numBeats);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ pw.println("Heartbeat command is no longer supported");
+ return -1;
}
private int triggerDockState(PrintWriter pw) throws Exception {
@@ -401,8 +394,7 @@
pw.println(" -u or --user: specify which user's job is to be run; the default is");
pw.println(" the primary or system user");
pw.println(" heartbeat [num]");
- pw.println(" With no argument, prints the current standby heartbeat. With a positive");
- pw.println(" argument, advances the standby heartbeat by that number.");
+ pw.println(" No longer used.");
pw.println(" monitor-battery [on|off]");
pw.println(" Control monitoring of all battery changes. Off by default. Turning");
pw.println(" on makes get-battery-seq useful.");
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 7da128f..4d9f133 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -285,9 +285,6 @@
UsageStatsManagerInternal usageStats =
LocalServices.getService(UsageStatsManagerInternal.class);
usageStats.setLastJobRunTime(jobPackage, jobUserId, mExecutionStartTimeElapsed);
- JobSchedulerInternal jobScheduler =
- LocalServices.getService(JobSchedulerInternal.class);
- jobScheduler.noteJobStart(jobPackage, jobUserId);
mAvailable = false;
mStoppedReason = null;
mStoppedTime = 0;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index d69faf3..4321fc7 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -189,7 +189,7 @@
if (utcTimes != null) {
Pair<Long, Long> elapsedRuntimes =
convertRtcBoundsToElapsed(utcTimes, elapsedNow);
- JobStatus newJob = new JobStatus(job, job.getBaseHeartbeat(),
+ JobStatus newJob = new JobStatus(job,
elapsedRuntimes.first, elapsedRuntimes.second,
0, job.getLastSuccessfulRunTime(), job.getLastFailedRunTime());
newJob.prepareLocked(am);
@@ -944,10 +944,9 @@
JobSchedulerInternal service = LocalServices.getService(JobSchedulerInternal.class);
final int appBucket = JobSchedulerService.standbyBucketForPackage(sourcePackageName,
sourceUserId, elapsedNow);
- long currentHeartbeat = service != null ? service.currentHeartbeat() : 0;
JobStatus js = new JobStatus(
jobBuilder.build(), uid, sourcePackageName, sourceUserId,
- appBucket, currentHeartbeat, sourceTag,
+ appBucket, sourceTag,
elapsedRuntimes.first, elapsedRuntimes.second,
lastSuccessfulRunTime, lastFailedRunTime,
(rtcIsGood) ? null : rtcRuntimes, internalFlags);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index f8cf6ae..a67aadf 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -47,7 +47,6 @@
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobSchedulerService.Constants;
-import com.android.server.job.JobServiceContext;
import com.android.server.job.StateControllerProto;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -88,8 +87,6 @@
@GuardedBy("mLock")
private final ArraySet<Network> mAvailableNetworks = new ArraySet<>();
- private boolean mUseQuotaLimit;
-
private static final int MSG_DATA_SAVER_TOGGLED = 0;
private static final int MSG_UID_RULES_CHANGES = 1;
private static final int MSG_REEVALUATE_JOBS = 2;
@@ -110,8 +107,6 @@
mConnManager.registerNetworkCallback(request, mNetworkCallback);
mNetPolicyManager.registerListener(mNetPolicyListener);
-
- mUseQuotaLimit = !mConstants.USE_HEARTBEATS;
}
@GuardedBy("mLock")
@@ -142,24 +137,6 @@
}
}
- @GuardedBy("mLock")
- @Override
- public void onConstantsUpdatedLocked() {
- if (mConstants.USE_HEARTBEATS) {
- // App idle exceptions are only requested for the rolling quota system.
- if (DEBUG) Slog.i(TAG, "Revoking all standby exceptions");
- for (int i = 0; i < mRequestedWhitelistJobs.size(); ++i) {
- int uid = mRequestedWhitelistJobs.keyAt(i);
- mNetPolicyManagerInternal.setAppIdleWhitelist(uid, false);
- }
- mRequestedWhitelistJobs.clear();
- }
- if (mUseQuotaLimit == mConstants.USE_HEARTBEATS) {
- mUseQuotaLimit = !mConstants.USE_HEARTBEATS;
- mHandler.obtainMessage(MSG_REEVALUATE_JOBS).sendToTarget();
- }
- }
-
/**
* Returns true if the job's requested network is available. This DOES NOT necesarilly mean
* that the UID has been granted access to the network.
@@ -237,11 +214,6 @@
@GuardedBy("mLock")
@Override
public void evaluateStateLocked(JobStatus jobStatus) {
- if (mConstants.USE_HEARTBEATS) {
- // This should only be used for the rolling quota system.
- return;
- }
-
if (!jobStatus.hasConnectivityConstraint()) {
return;
}
@@ -263,9 +235,6 @@
@GuardedBy("mLock")
@Override
public void reevaluateStateLocked(final int uid) {
- if (mConstants.USE_HEARTBEATS) {
- return;
- }
// Check if we still need a connectivity exception in case the JobService was disabled.
ArraySet<JobStatus> jobs = mTrackedJobs.get(uid);
if (jobs == null) {
@@ -329,9 +298,7 @@
*/
private boolean isInsane(JobStatus jobStatus, Network network,
NetworkCapabilities capabilities, Constants constants) {
- final long maxJobExecutionTimeMs = mUseQuotaLimit
- ? mService.getMaxJobExecutionTimeMs(jobStatus)
- : JobServiceContext.EXECUTING_TIMESLICE_MILLIS;
+ final long maxJobExecutionTimeMs = mService.getMaxJobExecutionTimeMs(jobStatus);
final long downloadBytes = jobStatus.getEstimatedNetworkDownloadBytes();
if (downloadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
@@ -617,7 +584,6 @@
@Override
public void dumpControllerStateLocked(IndentingPrintWriter pw,
Predicate<JobStatus> predicate) {
- pw.print("mUseQuotaLimit="); pw.println(mUseQuotaLimit);
if (mRequestedWhitelistJobs.size() > 0) {
pw.print("Requested standby exceptions:");
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 6f2b334..ae4abd6 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
@@ -169,12 +169,6 @@
private final int numFailures;
/**
- * Current standby heartbeat when this job was scheduled or last ran. Used to
- * pin the runnability check regardless of the job's app moving between buckets.
- */
- private final long baseHeartbeat;
-
- /**
* Which app standby bucket this job's app is in. Updated when the app is moved to a
* different bucket.
*/
@@ -350,8 +344,6 @@
* @param standbyBucket The standby bucket that the source package is currently assigned to,
* cached here for speed of handling during runnability evaluations (and updated when bucket
* assignments are changed)
- * @param heartbeat Timestamp of when the job was created, in the standby-related
- * timebase.
* @param tag A string associated with the job for debugging/logging purposes.
* @param numFailures Count of how many times this job has requested a reschedule because
* its work was not yet finished.
@@ -364,13 +356,12 @@
* @param internalFlags Non-API property flags about this job
*/
private JobStatus(JobInfo job, int callingUid, String sourcePackageName,
- int sourceUserId, int standbyBucket, long heartbeat, String tag, int numFailures,
+ int sourceUserId, int standbyBucket, String tag, int numFailures,
long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
long lastSuccessfulRunTime, long lastFailedRunTime, int internalFlags) {
this.job = job;
this.callingUid = callingUid;
this.standbyBucket = standbyBucket;
- this.baseHeartbeat = heartbeat;
int tempSourceUid = -1;
if (sourceUserId != -1 && sourcePackageName != null) {
@@ -440,7 +431,7 @@
public JobStatus(JobStatus jobStatus) {
this(jobStatus.getJob(), jobStatus.getUid(),
jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(),
- jobStatus.getStandbyBucket(), jobStatus.getBaseHeartbeat(),
+ jobStatus.getStandbyBucket(),
jobStatus.getSourceTag(), jobStatus.getNumFailures(),
jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed(),
jobStatus.getLastSuccessfulRunTime(), jobStatus.getLastFailedRunTime(),
@@ -462,13 +453,13 @@
* standby bucket is whatever the OS thinks it should be at this moment.
*/
public JobStatus(JobInfo job, int callingUid, String sourcePkgName, int sourceUserId,
- int standbyBucket, long baseHeartbeat, String sourceTag,
+ int standbyBucket, String sourceTag,
long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
long lastSuccessfulRunTime, long lastFailedRunTime,
Pair<Long, Long> persistedExecutionTimesUTC,
int innerFlags) {
this(job, callingUid, sourcePkgName, sourceUserId,
- standbyBucket, baseHeartbeat,
+ standbyBucket,
sourceTag, 0,
earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
lastSuccessfulRunTime, lastFailedRunTime, innerFlags);
@@ -486,13 +477,13 @@
}
/** Create a new job to be rescheduled with the provided parameters. */
- public JobStatus(JobStatus rescheduling, long newBaseHeartbeat,
+ public JobStatus(JobStatus rescheduling,
long newEarliestRuntimeElapsedMillis,
long newLatestRuntimeElapsedMillis, int backoffAttempt,
long lastSuccessfulRunTime, long lastFailedRunTime) {
this(rescheduling.job, rescheduling.getUid(),
rescheduling.getSourcePackageName(), rescheduling.getSourceUserId(),
- rescheduling.getStandbyBucket(), newBaseHeartbeat,
+ rescheduling.getStandbyBucket(),
rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis,
newLatestRuntimeElapsedMillis,
lastSuccessfulRunTime, lastFailedRunTime, rescheduling.getInternalFlags());
@@ -529,11 +520,8 @@
int standbyBucket = JobSchedulerService.standbyBucketForPackage(jobPackage,
sourceUserId, elapsedNow);
JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
- long currentHeartbeat = js != null
- ? js.baseHeartbeatForApp(jobPackage, sourceUserId, standbyBucket)
- : 0;
return new JobStatus(job, callingUid, sourcePkg, sourceUserId,
- standbyBucket, currentHeartbeat, tag, 0,
+ standbyBucket, tag, 0,
earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */,
/*innerFlags=*/ 0);
@@ -714,10 +702,6 @@
return standbyBucket;
}
- public long getBaseHeartbeat() {
- return baseHeartbeat;
- }
-
public void setStandbyBucket(int newBucket) {
standbyBucket = newBucket;
}
@@ -1631,10 +1615,6 @@
}
pw.print(prefix); pw.print("Standby bucket: ");
pw.println(getBucketName());
- if (standbyBucket > 0) {
- pw.print(prefix); pw.print("Base heartbeat: ");
- pw.println(baseHeartbeat);
- }
if (whenStandbyDeferred != 0) {
pw.print(prefix); pw.print(" Deferred since: ");
TimeUtils.formatDuration(whenStandbyDeferred, elapsedRealtimeMillis, pw);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index b8cfac4..043cda4 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -416,13 +416,6 @@
private volatile boolean mInParole;
- /**
- * If the QuotaController should throttle apps based on their standby bucket and job activity.
- * If false, all jobs will have their CONSTRAINT_WITHIN_QUOTA bit set to true immediately and
- * indefinitely.
- */
- private boolean mShouldThrottle;
-
/** How much time each app will have to run jobs within their standby bucket window. */
private long mAllowedTimePerPeriodMs = QcConstants.DEFAULT_ALLOWED_TIME_PER_PERIOD_MS;
@@ -594,8 +587,6 @@
} catch (RemoteException e) {
// ignored; both services live in system_server
}
-
- mShouldThrottle = !mConstants.USE_HEARTBEATS;
}
@Override
@@ -607,8 +598,6 @@
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
final int userId = jobStatus.getSourceUserId();
final String pkgName = jobStatus.getSourcePackageName();
- // Still need to track jobs even if mShouldThrottle is false in case it's set to true at
- // some point.
ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
if (jobs == null) {
jobs = new ArraySet<>();
@@ -616,16 +605,10 @@
}
jobs.add(jobStatus);
jobStatus.setTrackingController(JobStatus.TRACKING_QUOTA);
- if (mShouldThrottle) {
- final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
- setConstraintSatisfied(jobStatus, isWithinQuota);
- if (!isWithinQuota) {
- maybeScheduleStartAlarmLocked(userId, pkgName,
- getEffectiveStandbyBucket(jobStatus));
- }
- } else {
- // QuotaController isn't throttling, so always set to true.
- jobStatus.setQuotaConstraintSatisfied(true);
+ final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
+ setConstraintSatisfied(jobStatus, isWithinQuota);
+ if (!isWithinQuota) {
+ maybeScheduleStartAlarmLocked(userId, pkgName, getEffectiveStandbyBucket(jobStatus));
}
}
@@ -674,20 +657,6 @@
}
@Override
- public void onConstantsUpdatedLocked() {
- if (mShouldThrottle == mConstants.USE_HEARTBEATS) {
- mShouldThrottle = !mConstants.USE_HEARTBEATS;
-
- // Update job bookkeeping out of band.
- BackgroundThread.getHandler().post(() -> {
- synchronized (mLock) {
- maybeUpdateAllConstraintsLocked();
- }
- });
- }
- }
-
- @Override
public void onAppRemovedLocked(String packageName, int uid) {
if (packageName == null) {
Slog.wtf(TAG, "Told app removed but given null package name.");
@@ -780,8 +749,6 @@
boolean isWithinQuotaLocked(final int userId, @NonNull final String packageName,
final int standbyBucket) {
if (standbyBucket == NEVER_INDEX) return false;
- // This check is needed in case the flag is toggled after a job has been registered.
- if (!mShouldThrottle) return true;
// Quota constraint is not enforced while charging or when parole is on.
if (mChargeTracker.isCharging() || mInParole) {
@@ -1820,8 +1787,7 @@
if (timer != null && timer.isActive()) {
timer.rescheduleCutoff();
}
- if (!mShouldThrottle || maybeUpdateConstraintForPkgLocked(userId,
- packageName)) {
+ if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
mStateChangedListener.onControllerStateChanged();
}
}
@@ -2396,7 +2362,7 @@
changed = true;
}
- if (changed && mShouldThrottle) {
+ if (changed) {
// Update job bookkeeping out of band.
BackgroundThread.getHandler().post(() -> {
synchronized (mLock) {
@@ -2561,7 +2527,6 @@
@Override
public void dumpControllerStateLocked(final IndentingPrintWriter pw,
final Predicate<JobStatus> predicate) {
- pw.println("Is throttling: " + mShouldThrottle);
pw.println("Is charging: " + mChargeTracker.isCharging());
pw.println("In parole: " + mInParole);
pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis());
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index f6c72ea..bfbf667 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -56,6 +56,7 @@
import "frameworks/base/core/proto/android/telephony/enums.proto";
import "frameworks/base/core/proto/android/view/enums.proto";
import "frameworks/base/core/proto/android/wifi/enums.proto";
+import "frameworks/base/core/proto/android/stats/textclassifier/textclassifier_enums.proto";
/**
* The master atom class. This message defines all of the available
@@ -319,6 +320,15 @@
217 [(log_from_module) = "permissioncontroller"];
PermissionAppsFragmentViewed permission_apps_fragment_viewed =
218 [(log_from_module) = "permissioncontroller"];
+ TextSelectionEvent text_selection_event =
+ 219 [(log_from_module) = "textclassifier"];
+ TextLinkifyEvent text_linkify_event =
+ 220 [(log_from_module) = "textclassifier"];
+ ConversationActionsEvent conversation_actions_event =
+ 221 [(log_from_module) = "textclassifier"];
+ LanguageDetectionEvent language_detection_event =
+ 222 [(log_from_module) = "textclassifier"];
+
}
// Pulled events will start at field 10000.
@@ -6790,3 +6800,136 @@
}
optional Category category = 6;
}
+
+/**
+ * Logs when there is a smart selection related event.
+ * See frameworks/base/core/java/android/view/textclassifier/TextClassifierEvent.java
+ * Logged from: TextClassifierEventLogger.java
+ */
+message TextSelectionEvent {
+ // A session ID.
+ optional string session_id = 1;
+
+ // Event type of this event.
+ optional android.stats.textclassifier.EventType event_type = 2;
+
+ // Name of the model that is involved in this event.
+ optional string model_name = 3;
+
+ // Type of widget that was involved in triggering this event.
+ optional android.stats.textclassifier.WidgetType widget_type = 4;
+
+ // Index of this event in a session.
+ optional int32 event_index = 5;
+
+ // Entity type that is involved.
+ optional string entity_type = 6;
+
+ // Relative word index of the start of the selection.
+ optional int32 relative_word_start_index = 7;
+
+ // Relative word (exclusive) index of the end of the selection.
+ optional int32 relative_word_end_index = 8;
+
+ // Relative word index of the start of the smart selection.
+ optional int32 relative_suggested_word_start_index = 9;
+
+ // Relative word (exclusive) index of the end of the smart selection.
+ optional int32 relative_suggested_word_end_index = 10;
+}
+
+/**
+ * Logs when there is a smart linkify related event.
+ * See frameworks/base/core/java/android/view/textclassifier/TextClassifierEvent.java
+ * Logged from: TextClassifierEventLogger.java
+ */
+message TextLinkifyEvent {
+ // A session ID.
+ optional string session_id = 1;
+
+ // Event type of this event.
+ optional android.stats.textclassifier.EventType event_type = 2;
+
+ // Name of the model that is involved in this event.
+ optional string model_name = 3;
+
+ // Type of widget that was involved in triggering this event.
+ optional android.stats.textclassifier.WidgetType widget_type = 4;
+
+ // Index of this event in a session.
+ optional int32 event_index = 5;
+
+ // Entity type that is involved.
+ optional string entity_type = 6;
+
+ // Number of links detected.
+ optional int32 num_links = 7;
+
+ // The total length of all links.
+ optional int32 linked_text_length = 8;
+
+ // Length of input text.
+ optional int32 text_length = 9;
+
+ // Time spent on generating links in ms.
+ optional int64 latency_millis = 10;
+}
+
+/**
+ * Logs when there is a conversation actions related event.
+ * See frameworks/base/core/java/android/view/textclassifier/TextClassifierEvent.java
+ * Logged from: TextClassifierEventLogger.java
+ */
+message ConversationActionsEvent {
+ // A session ID.
+ optional string session_id = 1;
+
+ // Event type of this event.
+ optional android.stats.textclassifier.EventType event_type = 2;
+
+ // Name of the model that is involved in this event.
+ optional string model_name = 3;
+
+ // Type of widget that was involved in triggering this event.
+ optional android.stats.textclassifier.WidgetType widget_type = 4;
+
+ // The first entity type that is involved.
+ optional string first_entity_type = 5;
+
+ // The second entity type that is involved.
+ optional string second_entity_type = 6;
+
+ // The third entity type that is involved.
+ optional string third_entity_type = 7;
+
+ // The score of the first entity type.
+ optional float score = 8;
+}
+
+/**
+ * Logs when there is a language detection related event.
+ * See frameworks/base/core/java/android/view/textclassifier/TextClassifierEvent.java
+ * Logged from: TextClassifierEventLogger.java
+ */
+message LanguageDetectionEvent {
+ // A session ID.
+ optional string session_id = 1;
+
+ // Event type of this event.
+ optional android.stats.textclassifier.EventType event_type = 2;
+
+ // Name of the model that is involved in this event.
+ optional string model_name = 3;
+
+ // Type of widget that was involved in triggering this event.
+ optional android.stats.textclassifier.WidgetType widget_type = 4;
+
+ // Detected language.
+ optional string language_tag = 5;
+
+ // Score of the detected language.
+ optional float score = 6;
+
+ // Position of this action.
+ optional int32 action_index = 7;
+}
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index c30a6f4..eb53b7c 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -121,8 +121,6 @@
Landroid/bluetooth/IBluetoothPbap$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothPbap;
Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;-><init>()V
Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V
-Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V
-Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V
Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -194,7 +192,6 @@
Landroid/content/UndoManager;-><init>()V
Landroid/database/IContentObserver$Stub;-><init>()V
Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/database/IContentObserver;
-Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V
Landroid/database/sqlite/SQLiteConnectionPool;->$assertionsDisabled:Z
Landroid/database/sqlite/SQLiteDatabase;->$assertionsDisabled:Z
Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager;
@@ -723,9 +720,6 @@
Lcom/android/internal/location/GpsNetInitiatedHandler;->mIsHexInput:Z
Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
Lcom/android/internal/location/ILocationProvider$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProvider;
-Lcom/android/internal/location/ILocationProvider;->sendExtraCommand(Ljava/lang/String;Landroid/os/Bundle;)V
-Lcom/android/internal/location/ILocationProvider;->setLocationProviderManager(Lcom/android/internal/location/ILocationProviderManager;)V
-Lcom/android/internal/location/ILocationProvider;->setRequest(Lcom/android/internal/location/ProviderRequest;Landroid/os/WorkSource;)V
Lcom/android/internal/location/ILocationProviderManager$Stub;-><init>()V
Lcom/android/internal/location/ILocationProviderManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProviderManager;
Lcom/android/internal/logging/MetricsLogger;-><init>()V
@@ -736,7 +730,6 @@
Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService;
Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback;
-Lcom/android/internal/preference/YesNoPreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
Lcom/android/internal/R$anim;->fade_in:I
Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I
Lcom/android/internal/R$array;->config_autoBrightnessLevels:I
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
index 5f73e55..c9dc019 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
@@ -18,6 +18,8 @@
/** @hide */
interface ICompanionDeviceDiscoveryServiceCallback {
+ @UnsupportedAppUsage
oneway void onDeviceSelected(String packageName, int userId, String deviceAddress);
+ @UnsupportedAppUsage
oneway void onDeviceSelectionCancel();
}
diff --git a/core/java/android/database/IContentObserver.aidl b/core/java/android/database/IContentObserver.aidl
index 22dc9fe..6235566 100644
--- a/core/java/android/database/IContentObserver.aidl
+++ b/core/java/android/database/IContentObserver.aidl
@@ -29,5 +29,6 @@
* observed. selfUpdate is true if the update was caused by a call to
* commit on the cursor that is being observed.
*/
+ @UnsupportedAppUsage
oneway void onChange(boolean selfUpdate, in Uri uri, int userId);
}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index cc8c182..68857da9 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -2337,6 +2337,12 @@
final CaptureCallbackHolder holder =
CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
+ if (holder == null) {
+ Log.e(TAG, String.format("Receive capture error on unknown request ID %d",
+ requestId));
+ return;
+ }
+
final CaptureRequest request = holder.getRequest(subsequenceId);
Runnable failureDispatch = null;
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index b377e8d..6165146 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -123,6 +123,7 @@
IBinder binder = callback.asBinder();
try {
Callback cb = new Callback(callback, cookie);
+ unregister(callback);
binder.linkToDeath(cb, 0);
mCallbacks.put(binder, cb);
return true;
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index e1a9898..a26243c 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -480,7 +480,7 @@
* matter what user ID the calling process has.
*
* <p>Note: This field will be silently ignored when
- * {@link android.view.inputmethod.InputMethodSystemProperty#MULTI_CLIENT_IME_ENABLED} is
+ * {@link com.android.server.inputmethod.InputMethodSystemProperty#MULTI_CLIENT_IME_ENABLED} is
* {@code true}.</p>
*
* <p>Note also that pseudo handles such as {@link UserHandle#ALL} are not supported.</p>
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index a46580d..18d4d69 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -464,7 +464,9 @@
* Note that the feature will continue to be supported on older versions of
* Android as before.
*
- * This function does not have any effect.
+ * @deprecated In Android O and afterwards, this function does not have
+ * any effect, the form data will be saved to platform's autofill service
+ * if applicable.
*/
@Deprecated
public abstract void setSaveFormData(boolean save);
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 5091eea..ad35633 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -42,6 +42,8 @@
import android.view.animation.LinearInterpolator;
import android.widget.RemoteViews.RemoteView;
+import com.android.internal.R;
+
import java.lang.ref.WeakReference;
@RemoteView
@@ -1241,14 +1243,40 @@
info.setScrollable(getChildCount() > 1);
if (isEnabled()) {
if (getDisplayedChild() < getChildCount() - 1) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
+ if (mStackMode == ITEMS_SLIDE_UP) {
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_DOWN);
+ } else {
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_UP);
+ }
}
if (getDisplayedChild() > 0) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
+ if (mStackMode == ITEMS_SLIDE_UP) {
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_UP);
+ } else {
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_DOWN);
+ }
}
}
}
+ private boolean goForward() {
+ if (getDisplayedChild() < getChildCount() - 1) {
+ showNext();
+ return true;
+ }
+ return false;
+ }
+
+ private boolean goBackward() {
+ if (getDisplayedChild() > 0) {
+ showPrevious();
+ return true;
+ }
+ return false;
+ }
+
/** @hide */
@Override
public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
@@ -1260,17 +1288,25 @@
}
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
- if (getDisplayedChild() < getChildCount() - 1) {
- showNext();
- return true;
- }
- } return false;
+ return goForward();
+ }
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
- if (getDisplayedChild() > 0) {
- showPrevious();
- return true;
+ return goBackward();
+ }
+ case R.id.accessibilityActionPageUp: {
+ if (mStackMode == ITEMS_SLIDE_UP) {
+ return goBackward();
+ } else {
+ return goForward();
}
- } return false;
+ }
+ case R.id.accessibilityActionPageDown: {
+ if (mStackMode == ITEMS_SLIDE_UP) {
+ return goForward();
+ } else {
+ return goBackward();
+ }
+ }
}
return false;
}
diff --git a/core/java/com/android/internal/preference/YesNoPreference.java b/core/java/com/android/internal/preference/YesNoPreference.java
index 7abf416..46d14a1 100644
--- a/core/java/com/android/internal/preference/YesNoPreference.java
+++ b/core/java/com/android/internal/preference/YesNoPreference.java
@@ -16,6 +16,7 @@
package com.android.internal.preference;
+import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
@@ -40,6 +41,7 @@
this(context, attrs, defStyleAttr, 0);
}
+ @UnsupportedAppUsage
public YesNoPreference(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.yesNoPreferenceStyle);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index c715577..cf0394d 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -58,7 +58,7 @@
void topAppWindowChanged(int displayId, boolean menuVisible);
void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher);
+ boolean showImeSwitcher, boolean isMultiClientImeEnabled);
void setWindowState(int display, int window, int state);
void showRecentApps(boolean triggeredFromAltTab);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 598c391..85ae18e 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -49,7 +49,7 @@
@UnsupportedAppUsage
void removeIcon(String slot);
void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher);
+ boolean showImeSwitcher, boolean isMultiClientImeEnabled);
void expandSettingsPanel(String subPanel);
// ---- Methods below are for use by the status bar policy services ----
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index 0d87afa..e7d240a 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -26,8 +26,6 @@
import android.widget.ImageView;
import android.widget.RemoteViews;
-import java.util.ArrayList;
-
/**
* A TextView that can float around an image on the end.
*
@@ -44,7 +42,6 @@
private View mMainColumn;
private View mMediaContent;
private int mImagePushIn;
- private ArrayList<VisibilityChangeListener> mListeners;
public MediaNotificationView(Context context) {
this(context, null);
@@ -171,48 +168,4 @@
mMainColumn = findViewById(com.android.internal.R.id.notification_main_column);
mMediaContent = findViewById(com.android.internal.R.id.notification_media_content);
}
-
- @Override
- public void onVisibilityAggregated(boolean isVisible) {
- super.onVisibilityAggregated(isVisible);
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onAggregatedVisibilityChanged(isVisible);
- }
- }
-
- /**
- * Add a listener to receive updates on the visibility of this view
- *
- * @param listener The listener to add.
- */
- public void addVisibilityListener(VisibilityChangeListener listener) {
- if (mListeners == null) {
- mListeners = new ArrayList<>();
- }
- if (!mListeners.contains(listener)) {
- mListeners.add(listener);
- }
- }
-
- /**
- * Remove the specified listener
- *
- * @param listener The listener to remove.
- */
- public void removeVisibilityListener(VisibilityChangeListener listener) {
- if (mListeners != null) {
- mListeners.remove(listener);
- }
- }
-
- /**
- * Interface for receiving updates when the view's visibility changes
- */
- public interface VisibilityChangeListener {
- /**
- * Method called when the visibility of this view has changed
- * @param isVisible true if the view is now visible
- */
- void onAggregatedVisibilityChanged(boolean isVisible);
- }
}
diff --git a/core/java/com/android/server/job/JobSchedulerInternal.java b/core/java/com/android/server/job/JobSchedulerInternal.java
index 425ec47..dbf3b98 100644
--- a/core/java/com/android/server/job/JobSchedulerInternal.java
+++ b/core/java/com/android/server/job/JobSchedulerInternal.java
@@ -16,7 +16,6 @@
package com.android.server.job;
-import android.annotation.UserIdInt;
import android.app.job.JobInfo;
import java.util.List;
@@ -27,31 +26,6 @@
*/
public interface JobSchedulerInternal {
- // Bookkeeping about app standby bucket scheduling
-
- /**
- * The current bucket heartbeat ordinal
- */
- long currentHeartbeat();
-
- /**
- * Heartbeat ordinal at which the given standby bucket's jobs next become runnable
- */
- long nextHeartbeatForBucket(int bucket);
-
- /**
- * Heartbeat ordinal for the given app. This is typically the heartbeat at which
- * the app last ran jobs, so that a newly-scheduled job in an app that hasn't run
- * jobs in a long time is immediately runnable even if the app is bucketed into
- * an infrequent time allocation.
- */
- public long baseHeartbeatForApp(String packageName, @UserIdInt int userId, int appBucket);
-
- /**
- * Tell the scheduler when a JobServiceContext starts running a job in an app
- */
- void noteJobStart(String packageName, int userId);
-
/**
* Returns a list of pending jobs scheduled by the system service.
*/
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index c534aa4..5d4be55 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -38,10 +38,10 @@
optional ConstantsProto settings = 1;
- optional int32 current_heartbeat = 14;
- repeated int32 next_heartbeat = 15;
- optional int64 last_heartbeat_time_millis = 16;
- optional int64 next_heartbeat_time_millis = 17;
+ reserved 14; // current_heartbeat
+ reserved 15; // next_heartbeat
+ reserved 16; // last_heartbeat_time_millis
+ reserved 17; // next_heartbeat_time_millis
optional bool in_parole = 18;
optional bool in_thermal = 19;
@@ -64,7 +64,7 @@
optional bool is_uid_backing_up = 7;
optional bool is_component_present = 8;
- optional int64 last_run_heartbeat = 9;
+ reserved 9; // last_run_heartbeat
}
repeated RegisteredJob registered_jobs = 3;
@@ -214,13 +214,13 @@
// assignment. This should be prime relative to common time interval lengths
// such as a quarter-hour or day, so that the heartbeat drifts relative to
// wall-clock milestones.
- optional int64 standby_heartbeat_time_ms = 19;
+ reserved 19; // standby_heartbeat_time_ms
// Mapping: standby bucket -> number of heartbeats between each sweep of
// that bucket's jobs.
// Bucket assignments as recorded in the JobStatus objects are normalized to
// be indices into this array, rather than the raw constants used by
// AppIdleHistory.
- repeated int32 standby_beats = 20;
+ reserved 20; // standby_beats
// The fraction of a job's running window that must pass before we
// consider running it when the network is congested.
optional double conn_congestion_delay_frac = 21;
@@ -229,7 +229,7 @@
optional double conn_prefetch_relax_frac = 22;
// Whether to use heartbeats or rolling window for quota management. True
// will use heartbeats, false will use a rolling window.
- optional bool use_heartbeats = 23;
+ reserved 23; // use_heartbeats
message QuotaController {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
diff --git a/core/proto/android/stats/textclassifier/textclassifier_enums.proto b/core/proto/android/stats/textclassifier/textclassifier_enums.proto
new file mode 100644
index 0000000..1885f19
--- /dev/null
+++ b/core/proto/android/stats/textclassifier/textclassifier_enums.proto
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+syntax = "proto2";
+package android.stats.textclassifier;
+option java_multiple_files = true;
+
+enum EventType {
+ TYPE_UNKNOWN = 0;
+ // User started a new selection.
+ SELECTION_STARTED = 1;
+ // User modified an existing selection.
+ SELECTION_MODIFIED = 2;
+ // Smart selection triggered for a single token (word).
+ SMART_SELECTION_SINGLE = 3;
+ // Smart selection triggered spanning multiple tokens (words).
+ SMART_SELECTION_MULTI = 4;
+ // Something else other than user or the default TextClassifier triggered a selection.
+ AUTO_SELECTION = 5;
+ // Smart actions shown to the user.
+ ACTIONS_SHOWN = 6;
+ // User clicked a link.
+ LINK_CLICKED = 7;
+ // User typed over the selection.
+ OVERTYPE = 8;
+ // User clicked on Copy action.
+ COPY_ACTION = 9;
+ // User clicked on Paste action.
+ PASTE_ACTION = 10;
+ // User clicked on Cut action.
+ CUT_ACTION = 11;
+ // User clicked on Share action.
+ SHARE_ACTION = 12;
+ // User clicked on a Smart action.
+ SMART_ACTION = 13;
+ // User dragged+dropped the selection.
+ SELECTION_DRAG = 14;
+ // Selection is destroyed.
+ SELECTION_DESTROYED = 15;
+ // User clicked on a custom action.
+ OTHER_ACTION = 16;
+ // User clicked on Select All action
+ SELECT_ALL = 17;
+ // User reset the smart selection.
+ SELECTION_RESET = 18;
+ // User composed a reply.
+ MANUAL_REPLY = 19;
+ // TextClassifier generated some actions
+ ACTIONS_GENERATED = 20;
+}
+
+enum WidgetType {
+ WIDGET_TYPE_UNKNOWN = 0;
+ // Standard TextView
+ WIDGET_TYPE_TEXTVIEW = 1;
+ // EditText
+ WIDGET_TYPE_EDITTEXT = 2;
+ // Not selectable textview
+ WIDGET_TYPE_UNSELECTABLE_TEXTVIEW = 3;
+ // Standard Webview
+ WIDGET_TYPE_WEBVIEW = 4;
+ // Editable TextView
+ WIDGET_TYPE_EDIT_WEBVIEW = 5;
+ // Custom text widget
+ WIDGET_TYPE_CUSTOM_TEXTVIEW = 6;
+ // Custom editable text widget.
+ WIDGET_TYPE_CUSTOM_EDITTEXT = 7;
+ // Non-selectable text widget.
+ WIDGET_TYPE_CUSTOM_UNSELECTABLE_TEXTVIEW = 8;
+ // Notification
+ WIDGET_TYPE_NOTIFICATION = 9;
+}
diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java
index 0eba2ed..46873b9 100644
--- a/core/tests/coretests/src/android/os/ParcelTest.java
+++ b/core/tests/coretests/src/android/os/ParcelTest.java
@@ -43,8 +43,8 @@
// WorkSource can be updated.
p.writeInterfaceToken(INTERFACE_TOKEN_1);
- assertEquals(true, p.replaceCallingWorkSourceUid(WORK_SOURCE_1));
- assertEquals(WORK_SOURCE_1, p.readCallingWorkSourceUid());
+ assertEquals(true, p.replaceCallingWorkSourceUid(WORK_SOURCE_2));
+ assertEquals(WORK_SOURCE_2, p.readCallingWorkSourceUid());
// WorkSource can be updated to unset value.
assertEquals(true, p.replaceCallingWorkSourceUid(Binder.UNSET_WORKSOURCE));
@@ -56,18 +56,16 @@
@Test
public void testCallingWorkSourceUidAfterEnforce() {
Parcel p = Parcel.obtain();
- // Write headers manually so that we do not invoke #writeInterfaceToken.
- p.writeInt(1); // strict mode header
- p.writeInt(WORK_SOURCE_1); // worksource header.
- p.writeString(INTERFACE_TOKEN_1); // interface token.
+ p.writeInterfaceToken(INTERFACE_TOKEN_1);
+ assertEquals(true, p.replaceCallingWorkSourceUid(WORK_SOURCE_1));
p.setDataPosition(0);
p.enforceInterface(INTERFACE_TOKEN_1);
assertEquals(WORK_SOURCE_1, p.readCallingWorkSourceUid());
// WorkSource can be updated.
- assertEquals(true, p.replaceCallingWorkSourceUid(WORK_SOURCE_1));
- assertEquals(WORK_SOURCE_1, p.readCallingWorkSourceUid());
+ assertEquals(true, p.replaceCallingWorkSourceUid(WORK_SOURCE_2));
+ assertEquals(WORK_SOURCE_2, p.readCallingWorkSourceUid());
p.recycle();
}
diff --git a/graphics/java/android/graphics/RectF.java b/graphics/java/android/graphics/RectF.java
index 3361fa2..1d294d5 100644
--- a/graphics/java/android/graphics/RectF.java
+++ b/graphics/java/android/graphics/RectF.java
@@ -27,7 +27,7 @@
/**
* RectF holds four float coordinates for a rectangle. The rectangle is
- * represented by the coordinates of its 4 edges (left, top, right bottom).
+ * represented by the coordinates of its 4 edges (left, top, right, bottom).
* These fields can be accessed directly. Use width() and height() to retrieve
* the rectangle's width and height. Note: most methods do not check to see that
* the coordinates are sorted correctly (i.e. left <= right and top <= bottom).
diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl
index a571630..8ae972b 100644
--- a/location/java/com/android/internal/location/ILocationProvider.aidl
+++ b/location/java/com/android/internal/location/ILocationProvider.aidl
@@ -29,10 +29,13 @@
*/
interface ILocationProvider {
+ @UnsupportedAppUsage
oneway void setLocationProviderManager(in ILocationProviderManager manager);
+ @UnsupportedAppUsage
oneway void setRequest(in ProviderRequest request, in WorkSource ws);
+ @UnsupportedAppUsage
oneway void sendExtraCommand(String command, in Bundle extras);
// --- deprecated and will be removed the future ---
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 59754e0..81d1ea5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1434,7 +1434,7 @@
void update(@Nullable WifiConfiguration config) {
mConfig = config;
- if (mConfig != null) {
+ if (mConfig != null && !isPasspoint()) {
ssid = removeDoubleQuotes(mConfig.SSID);
}
networkId = config != null ? config.networkId : WifiConfiguration.INVALID_NETWORK_ID;
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index a7b4444..2727880 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -366,8 +366,10 @@
checkProgressUpdated(mInfo, (int) progress);
}
- // TODO(b/127431371): Add error code handling for bugreport API errors.
- // Logging errors and removing progress notification for now.
+ /**
+ * Logs errors and stops the service on which this bugreport was running.
+ * Also stops progress notification (if any).
+ */
@Override
public void onError(@BugreportErrorCode int errorCode) {
trackInfoWithId();
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index df3f36e..3f598ff 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -95,6 +95,7 @@
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.plugins.GlobalActionsPanelPlugin;
import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.phone.UnlockMethodCache;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.EmergencyDialerConstants;
@@ -1523,6 +1524,8 @@
private boolean mShowing;
private float mScrimAlpha;
private ResetOrientationData mResetOrientationData;
+ private boolean mHadTopUi;
+ private final StatusBarWindowController mStatusBarWindowController;
ActionsDialog(Context context, MyAdapter adapter,
GlobalActionsPanelPlugin.PanelViewController plugin) {
@@ -1531,6 +1534,7 @@
mAdapter = adapter;
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
mStatusBarService = Dependency.get(IStatusBarService.class);
+ mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
// Window initialization
Window window = getWindow();
@@ -1706,6 +1710,8 @@
public void show() {
super.show();
mShowing = true;
+ mHadTopUi = mStatusBarWindowController.getForceHasTopUi();
+ mStatusBarWindowController.setForceHasTopUi(true);
mBackgroundDrawable.setAlpha(0);
mGlobalActionsLayout.setTranslationX(mGlobalActionsLayout.getAnimationOffsetX());
mGlobalActionsLayout.setTranslationY(mGlobalActionsLayout.getAnimationOffsetY());
@@ -1738,7 +1744,7 @@
.translationX(mGlobalActionsLayout.getAnimationOffsetX())
.translationY(mGlobalActionsLayout.getAnimationOffsetY())
.setDuration(300)
- .withEndAction(super::dismiss)
+ .withEndAction(this::completeDismiss)
.setInterpolator(new LogAccelerateInterpolator())
.setUpdateListener(animation -> {
int alpha = (int) ((1f - (Float) animation.getAnimatedValue())
@@ -1751,10 +1757,15 @@
}
void dismissImmediately() {
- super.dismiss();
mShowing = false;
dismissPanel();
resetOrientation();
+ completeDismiss();
+ }
+
+ private void completeDismiss() {
+ mStatusBarWindowController.setForceHasTopUi(mHadTopUi);
+ super.dismiss();
}
private void dismissPanel() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 6329af5..fa0fe13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -43,7 +43,6 @@
import android.os.Message;
import android.util.Pair;
import android.util.SparseArray;
-import android.view.inputmethod.InputMethodSystemProperty;
import androidx.annotation.VisibleForTesting;
@@ -481,7 +480,7 @@
@Override
public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher) {
+ boolean showImeSwitcher, boolean isMultiClientImeEnabled) {
synchronized (mLock) {
mHandler.removeMessages(MSG_SHOW_IME_BUTTON);
SomeArgs args = SomeArgs.obtain();
@@ -489,6 +488,7 @@
args.argi2 = vis;
args.argi3 = backDisposition;
args.argi4 = showImeSwitcher ? 1 : 0;
+ args.argi5 = isMultiClientImeEnabled ? 1 : 0;
args.arg1 = token;
Message m = mHandler.obtainMessage(MSG_SHOW_IME_BUTTON, args);
m.sendToTarget();
@@ -801,11 +801,10 @@
}
private void handleShowImeButton(int displayId, IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher) {
+ boolean showImeSwitcher, boolean isMultiClientImeEnabled) {
if (displayId == INVALID_DISPLAY) return;
- if (!InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED
- && mLastUpdatedImeDisplayId != displayId
+ if (!isMultiClientImeEnabled && mLastUpdatedImeDisplayId != displayId
&& mLastUpdatedImeDisplayId != INVALID_DISPLAY) {
// Set previous NavBar's IME window status as invisible when IME
// window switched to another display for single-session IME case.
@@ -891,7 +890,8 @@
args = (SomeArgs) msg.obj;
handleShowImeButton(args.argi1 /* displayId */, (IBinder) args.arg1 /* token */,
args.argi2 /* vis */, args.argi3 /* backDisposition */,
- args.argi4 != 0 /* showImeSwitcher */);
+ args.argi4 != 0 /* showImeSwitcher */,
+ args.argi5 != 0 /* isMultiClientImeEnabled */);
break;
case MSG_SHOW_RECENT_APPS:
for (int i = 0; i < mCallbacks.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 38f9bff..20e8b73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -39,7 +39,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.widget.MediaNotificationView;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.TransformableView;
@@ -68,7 +67,6 @@
private View mSeekBarView;
private Context mContext;
private MetricsLogger mMetricsLogger;
- private boolean mIsViewVisible;
@VisibleForTesting
protected SeekBar.OnSeekBarChangeListener mSeekListener =
@@ -90,33 +88,11 @@
}
};
- MediaNotificationView.VisibilityChangeListener mVisibilityListener =
- new MediaNotificationView.VisibilityChangeListener() {
- @Override
- public void onAggregatedVisibilityChanged(boolean isVisible) {
- mIsViewVisible = isVisible;
- if (isVisible) {
- // Restart timer if we're currently playing and didn't already have one going
- PlaybackState state = mMediaController.getPlaybackState();
- if (state != null && state.getState() == PlaybackState.STATE_PLAYING
- && mSeekBarTimer == null && mSeekBarView != null
- && mSeekBarView.getVisibility() != View.GONE) {
- startTimer();
- }
- } else {
- clearTimer();
- }
- }
- };
-
private MediaController.Callback mMediaCallback = new MediaController.Callback() {
@Override
public void onSessionDestroyed() {
clearTimer();
mMediaController.unregisterCallback(this);
- if (mView instanceof MediaNotificationView) {
- ((MediaNotificationView) mView).removeVisibilityListener(mVisibilityListener);
- }
}
@Override
@@ -150,16 +126,10 @@
mContext = ctx;
mMediaManager = Dependency.get(NotificationMediaManager.class);
mMetricsLogger = Dependency.get(MetricsLogger.class);
-
- if (mView instanceof MediaNotificationView) {
- MediaNotificationView mediaView = (MediaNotificationView) mView;
- mediaView.addVisibilityListener(mVisibilityListener);
- }
}
private void resolveViews() {
mActions = mView.findViewById(com.android.internal.R.id.media_actions);
- mIsViewVisible = mView.isShown();
final MediaSession.Token token = mRow.getEntry().notification.getNotification().extras
.getParcelable(Notification.EXTRA_MEDIA_SESSION);
@@ -238,19 +208,18 @@
private void startTimer() {
clearTimer();
- if (mIsViewVisible) {
- mSeekBarTimer = new Timer(true /* isDaemon */);
- mSeekBarTimer.schedule(new TimerTask() {
- @Override
- public void run() {
- mHandler.post(mOnUpdateTimerTick);
- }
- }, 0, PROGRESS_UPDATE_INTERVAL);
- }
+ mSeekBarTimer = new Timer(true /* isDaemon */);
+ mSeekBarTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ mHandler.post(mOnUpdateTimerTick);
+ }
+ }, 0, PROGRESS_UPDATE_INTERVAL);
}
private void clearTimer() {
if (mSeekBarTimer != null) {
+ // TODO: also trigger this when the notification panel is collapsed
mSeekBarTimer.cancel();
mSeekBarTimer.purge();
mSeekBarTimer = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index 70d3bff..832ea9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -19,7 +19,6 @@
import android.content.Context
import android.content.pm.PackageManager
import android.hardware.biometrics.BiometricSourceType
-import android.hardware.face.FaceManager
import android.provider.Settings
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
@@ -34,6 +33,7 @@
private val unlockMethodCache: UnlockMethodCache
private val statusBarStateController: StatusBarStateController
+ private var hasFaceFeature: Boolean
/**
* The pending unlock type which is set if the bypass was blocked when it happened.
@@ -71,11 +71,8 @@
unlockMethodCache = UnlockMethodCache.getInstance(context)
this.statusBarStateController = statusBarStateController
- if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
- return
- }
- val faceManager = context.getSystemService(FaceManager::class.java)
- if (faceManager?.isHardwareDetected != true) {
+ hasFaceFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)
+ if (!hasFaceFeature) {
return
}
@@ -165,7 +162,7 @@
pw.print(" isPulseExpanding: "); pw.println(isPulseExpanding)
pw.print(" launchingAffordance: "); pw.println(launchingAffordance)
pw.print(" qSExpanded: "); pw.println(qSExpanded)
- pw.print(" bouncerShowing: "); pw.println(bouncerShowing)
+ pw.print(" hasFaceFeature: "); pw.println(hasFaceFeature)
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index c0a1b12..1d4d0bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -103,10 +103,11 @@
final boolean userSwitcherEnabled = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.USER_SWITCHER_ENABLED, 0) != 0;
- if (!UserManager.supportsMultipleUsers()
- || mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)
+ // TODO(b/138661450) Move IPC calls to background
+ if (!userSwitcherEnabled
+ || !UserManager.supportsMultipleUsers()
|| UserManager.isDeviceInDemoMode(mContext)
- || !userSwitcherEnabled) {
+ || mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index d0626ed..9652992 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -3098,10 +3098,8 @@
/**
* Whether the camera application can be launched for the camera launch gesture.
- *
- * @param keyguardIsShowing whether keyguard is being shown
*/
- public boolean canCameraGestureBeLaunched(boolean keyguardIsShowing) {
+ public boolean canCameraGestureBeLaunched() {
if (!mStatusBar.isCameraAllowedByAdmin()) {
return false;
}
@@ -3110,7 +3108,7 @@
String packageToLaunch = (resolveInfo == null || resolveInfo.activityInfo == null)
? null : resolveInfo.activityInfo.packageName;
return packageToLaunch != null &&
- (keyguardIsShowing || !isForegroundApp(packageToLaunch))
+ (mBarState != StatusBarState.SHADE || !isForegroundApp(packageToLaunch))
&& !mAffordanceHelper.isSwipingInProgress();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index f15b601..17a3a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3785,10 +3785,8 @@
mLaunchCameraOnFinishedGoingToSleep = true;
return;
}
- if (!mNotificationPanel.canCameraGestureBeLaunched(
- mStatusBarKeyguardViewManager.isShowing() && mExpandedVisible)) {
- if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now, mExpandedVisible: " +
- mExpandedVisible);
+ if (!mNotificationPanel.canCameraGestureBeLaunched()) {
+ if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now");
return;
}
if (!mDeviceInteractive) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index ebac855..0ef981b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -76,13 +76,13 @@
private final WindowManager mWindowManager;
private final IActivityManager mActivityManager;
private final DozeParameters mDozeParameters;
- private final WindowManager.LayoutParams mLpChanged;
+ private final LayoutParams mLpChanged;
private final boolean mKeyguardScreenRotation;
private final long mLockScreenDisplayTimeout;
private final Display.Mode mKeyguardDisplayMode;
private final KeyguardBypassController mKeyguardBypassController;
private ViewGroup mStatusBarView;
- private WindowManager.LayoutParams mLp;
+ private LayoutParams mLp;
private boolean mHasTopUi;
private boolean mHasTopUiChanged;
private int mBarHeight;
@@ -117,7 +117,7 @@
mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
mDozeParameters = dozeParameters;
mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
- mLpChanged = new WindowManager.LayoutParams();
+ mLpChanged = new LayoutParams();
mKeyguardBypassController = keyguardBypassController;
mLockScreenDisplayTimeout = context.getResources()
.getInteger(R.integer.config_lockScreenDisplayTimeout);
@@ -171,19 +171,19 @@
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
- mLp = new WindowManager.LayoutParams(
+ mLp = new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
barHeight,
- WindowManager.LayoutParams.TYPE_STATUS_BAR,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ LayoutParams.TYPE_STATUS_BAR,
+ LayoutParams.FLAG_NOT_FOCUSABLE
+ | LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+ | LayoutParams.FLAG_SPLIT_TOUCH
+ | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
PixelFormat.TRANSLUCENT);
mLp.token = new Binder();
mLp.gravity = Gravity.TOP;
- mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+ mLp.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
mLp.setTitle("StatusBar");
mLp.packageName = mContext.getPackageName();
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -216,9 +216,9 @@
private void applyKeyguardFlags(State state) {
if (state.keyguardShowing) {
- mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+ mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_KEYGUARD;
} else {
- mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+ mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_KEYGUARD;
}
final boolean scrimsOccludingWallpaper =
@@ -226,9 +226,9 @@
final boolean keyguardOrAod = state.keyguardShowing
|| (state.dozing && mDozeParameters.getAlwaysOn());
if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) {
- mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+ mLpChanged.flags |= LayoutParams.FLAG_SHOW_WALLPAPER;
} else {
- mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+ mLpChanged.flags &= ~LayoutParams.FLAG_SHOW_WALLPAPER;
}
if (state.dozing) {
@@ -267,17 +267,17 @@
if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput)
|| ENABLE_REMOTE_INPUT && state.remoteInputActive
|| state.bubbleExpanded) {
- mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
- mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLpChanged.flags |= LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else {
- mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ mLpChanged.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
- mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+ mLpChanged.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
}
private void applyForceShowNavigationFlag(State state) {
@@ -335,19 +335,19 @@
&& state.statusBarState == StatusBarState.KEYGUARD
&& !state.qsExpanded && !state.forceUserActivity) {
mLpChanged.inputFeatures |=
- WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+ LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
} else {
mLpChanged.inputFeatures &=
- ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+ ~LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
}
}
private void applyStatusBarColorSpaceAgnosticFlag(State state) {
if (!isExpanded(state)) {
- mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
+ mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
} else {
mLpChanged.privateFlags &=
- ~WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
+ ~LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
}
}
@@ -396,16 +396,16 @@
mLpChanged.privateFlags |= WindowManager
.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
} else {
- mLpChanged.privateFlags &= ~WindowManager
- .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
+ mLpChanged.privateFlags
+ &= ~LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
}
}
private void applyModalFlag(State state) {
if (state.headsUpShowing) {
- mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCH_MODAL;
} else {
- mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCH_MODAL;
}
}
@@ -413,12 +413,12 @@
if (state.forceDozeBrightness) {
mLpChanged.screenBrightness = mScreenBrightnessDoze;
} else {
- mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
+ mLpChanged.screenBrightness = LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
}
}
private void applyHasTopUi(State state) {
- mHasTopUiChanged = isExpanded(state);
+ mHasTopUiChanged = state.forceHasTopUi || isExpanded(state);
}
private void applyNotTouchable(State state) {
@@ -642,6 +642,15 @@
apply(mCurrentState);
}
+ public boolean getForceHasTopUi() {
+ return mCurrentState.forceHasTopUi;
+ }
+
+ public void setForceHasTopUi(boolean forceHasTopUi) {
+ mCurrentState.forceHasTopUi = forceHasTopUi;
+ apply(mCurrentState);
+ }
+
private static class State {
boolean keyguardShowing;
boolean keyguardOccluded;
@@ -663,6 +672,7 @@
boolean notTouchable;
boolean bubblesShowing;
boolean bubbleExpanded;
+ boolean forceHasTopUi;
/**
* The {@link StatusBar} state from the status bar.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 84a7d4f..1e1f2156 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -129,7 +129,7 @@
@Test
public void testShowImeButton() {
- mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, 1, 2, true);
+ mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, 1, 2, true, false);
waitForIdleSync();
verify(mCallbacks).setImeWindowStatus(
eq(DEFAULT_DISPLAY), eq(null), eq(1), eq(2), eq(true));
@@ -137,7 +137,7 @@
@Test
public void testShowImeButtonForSecondaryDisplay() {
- mCommandQueue.setImeWindowStatus(SECONDARY_DISPLAY, null, 1, 2, true);
+ mCommandQueue.setImeWindowStatus(SECONDARY_DISPLAY, null, 1, 2, true, false);
waitForIdleSync();
verify(mCallbacks).setImeWindowStatus(
eq(SECONDARY_DISPLAY), eq(null), eq(1), eq(2), eq(true));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 3da9a4b..db8af39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -183,7 +183,7 @@
// Set IME window status for default NavBar.
mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
- BACK_DISPOSITION_DEFAULT, true);
+ BACK_DISPOSITION_DEFAULT, true, false);
Handler.getMain().runWithScissors(() -> { }, 500);
// Verify IME window state will be updated in default NavBar & external NavBar state reset.
@@ -194,7 +194,7 @@
// Set IME window status for external NavBar.
mCommandQueue.setImeWindowStatus(EXTERNAL_DISPLAY_ID, null,
- IME_VISIBLE, BACK_DISPOSITION_DEFAULT, true);
+ IME_VISIBLE, BACK_DISPOSITION_DEFAULT, true, false);
Handler.getMain().runWithScissors(() -> { }, 500);
// Verify IME window state will be updated in external NavBar & default NavBar state reset.
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index d923bed..6b88f5a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -398,7 +398,8 @@
if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
return null;
}
- AccessibilityWindowInfo window = mA11yWindowManager.findA11yWindowInfoById(windowId);
+ AccessibilityWindowInfo window =
+ mA11yWindowManager.findA11yWindowInfoByIdLocked(windowId);
if (window != null) {
AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
windowClone.setConnectionId(mId);
@@ -1362,11 +1363,11 @@
|| (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS);
if (!isA11yFocusAction) {
final WindowInfo windowInfo =
- mA11yWindowManager.findWindowInfoById(resolvedWindowId);
+ mA11yWindowManager.findWindowInfoByIdLocked(resolvedWindowId);
if (windowInfo != null) activityToken = windowInfo.activityToken;
}
final AccessibilityWindowInfo a11yWindowInfo =
- mA11yWindowManager.findA11yWindowInfoById(resolvedWindowId);
+ mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId);
if (a11yWindowInfo != null && a11yWindowInfo.isInPictureInPictureMode()
&& mA11yWindowManager.getPictureInPictureActionReplacingConnection() != null
&& !isA11yFocusAction) {
@@ -1419,11 +1420,13 @@
int interactionId, int interrogatingPid, long interrogatingTid) {
final RemoteAccessibilityConnection pipActionReplacingConnection =
mA11yWindowManager.getPictureInPictureActionReplacingConnection();
- final AccessibilityWindowInfo windowInfo =
- mA11yWindowManager.findA11yWindowInfoById(resolvedWindowId);
- if ((windowInfo == null) || !windowInfo.isInPictureInPictureMode()
+ synchronized (mLock) {
+ final AccessibilityWindowInfo windowInfo =
+ mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId);
+ if ((windowInfo == null) || !windowInfo.isInPictureInPictureMode()
|| (pipActionReplacingConnection == null)) {
- return originalCallback;
+ return originalCallback;
+ }
}
return new ActionReplacingCallback(originalCallback,
pipActionReplacingConnection.getRemote(), interactionId,
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 81485369..5ba777c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -542,7 +542,7 @@
if (event.getWindowId() ==
AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID) {
// The replacer window isn't shown to services. Move its events into the pip.
- AccessibilityWindowInfo pip = mA11yWindowManager.getPictureInPictureWindow();
+ AccessibilityWindowInfo pip = mA11yWindowManager.getPictureInPictureWindowLocked();
if (pip != null) {
int pipId = pip.getId();
event.setWindowId(pipId);
@@ -771,7 +771,7 @@
if (resolvedUserId != mCurrentUserId) {
return null;
}
- if (mA11yWindowManager.findA11yWindowInfoById(windowId) == null) {
+ if (mA11yWindowManager.findA11yWindowInfoByIdLocked(windowId) == null) {
return null;
}
return mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(userId, windowId);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
index 1e224cf..315d6fa 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
@@ -429,7 +429,7 @@
if (windowId == mAccessibilityWindowManager.getActiveWindowId(userId)) {
return true;
}
- return mAccessibilityWindowManager.findA11yWindowInfoById(windowId) != null;
+ return mAccessibilityWindowManager.findA11yWindowInfoByIdLocked(windowId) != null;
}
private boolean isShellAllowedToRetrieveWindowLocked(int userId, int windowId) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index c129291..9687098 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -52,13 +52,10 @@
import java.util.List;
/**
- * This class implements {@link WindowManagerInternal.WindowsForAccessibilityCallback} to receive
- * {@link WindowInfo}s from window manager when there's an accessibility change in window. It also
- * provides APIs for accessibility manager to manage {@link AccessibilityWindowInfo}s and
+ * This class provides APIs for accessibility manager to manage {@link AccessibilityWindowInfo}s and
* {@link WindowInfo}s.
*/
-public class AccessibilityWindowManager
- implements WindowManagerInternal.WindowsForAccessibilityCallback {
+public class AccessibilityWindowManager {
private static final String LOG_TAG = "AccessibilityWindowManager";
private static final boolean DEBUG = false;
@@ -71,9 +68,6 @@
private final AccessibilitySecurityPolicy mSecurityPolicy;
private final AccessibilityUserManager mAccessibilityUserManager;
- private final SparseArray<AccessibilityWindowInfo> mA11yWindowInfoById = new SparseArray<>();
- private final SparseArray<WindowInfo> mWindowInfoById = new SparseArray<>();
-
// Connections and window tokens for cross-user windows
private final SparseArray<RemoteAccessibilityConnection>
mGlobalInteractionConnections = new SparseArray<>();
@@ -84,9 +78,6 @@
mInteractionConnections = new SparseArray<>();
private final SparseArray<SparseArray<IBinder>> mWindowTokens = new SparseArray<>();
- private final List<WindowInfo> mCachedWindowInfos = new ArrayList<>();
- private List<AccessibilityWindowInfo> mWindows;
-
private RemoteAccessibilityConnection mPictureInPictureActionReplacingConnection;
private int mActiveWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
@@ -95,15 +86,641 @@
private long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
private boolean mTouchInteractionInProgress;
- private boolean mHasWatchOutsideTouchWindow;
- private boolean mTrackingWindows = false;
+ // TO-DO [Multi-Display] : make DisplayWindowObserver to plural
+ private DisplayWindowsObserver mDisplayWindowsObserver;
+
+ /**
+ * This class implements {@link WindowManagerInternal.WindowsForAccessibilityCallback} to
+ * receive {@link WindowInfo}s from window manager when there's an accessibility change in
+ * window and holds window lists information per display.
+ */
+ private final class DisplayWindowsObserver implements
+ WindowManagerInternal.WindowsForAccessibilityCallback {
+
+ private final int mDisplayId;
+ private final SparseArray<AccessibilityWindowInfo> mA11yWindowInfoById =
+ new SparseArray<>();
+ private final SparseArray<WindowInfo> mWindowInfoById = new SparseArray<>();
+ private final List<WindowInfo> mCachedWindowInfos = new ArrayList<>();
+ private List<AccessibilityWindowInfo> mWindows;
+ private boolean mTrackingWindows = false;
+ private boolean mHasWatchOutsideTouchWindow;
+
+ /**
+ * Constructor for DisplayWindowsObserver.
+ */
+ DisplayWindowsObserver(int displayId) {
+ mDisplayId = displayId;
+ }
+
+ /**
+ * Starts tracking windows changes from window manager by registering callback.
+ *
+ * @return true if callback registers successful.
+ */
+ boolean startTrackingWindowsLocked() {
+ boolean result = true;
+
+ if (!mTrackingWindows) {
+ // Turns on the flag before setup the callback.
+ // In some cases, onWindowsForAccessibilityChanged will be called immediately in
+ // setWindowsForAccessibilityCallback. We'll lost windows if flag is false.
+ mTrackingWindows = true;
+ result = mWindowManagerInternal.setWindowsForAccessibilityCallback(
+ mDisplayId, this);
+ if (!result) {
+ mTrackingWindows = false;
+ Slog.w(LOG_TAG, "set windowsObserver callbacks fail, displayId:"
+ + mDisplayId);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Stops tracking windows changes from window manager, and clear all windows info.
+ */
+ void stopTrackingWindowsLocked() {
+ if (mTrackingWindows) {
+ mWindowManagerInternal.setWindowsForAccessibilityCallback(
+ mDisplayId, null);
+ mTrackingWindows = false;
+ clearWindowsLocked();
+ }
+ }
+
+ /**
+ * Returns true if windows changes tracking.
+ *
+ * @return true if windows changes tracking
+ */
+ boolean isTrackingWindowsLocked() {
+ return mTrackingWindows;
+ }
+
+ /**
+ * Returns accessibility windows.
+ * @return accessibility windows.
+ */
+ @Nullable
+ List<AccessibilityWindowInfo> getWindowListLocked() {
+ return mWindows;
+ }
+
+ /**
+ * Returns accessibility window info according to given windowId.
+ *
+ * @param windowId The windowId
+ * @return The accessibility window info
+ */
+ @Nullable
+ AccessibilityWindowInfo findA11yWindowInfoByIdLocked(int windowId) {
+ return mA11yWindowInfoById.get(windowId);
+ }
+
+ /**
+ * Returns the window info according to given windowId.
+ *
+ * @param windowId The windowId
+ * @return The window info
+ */
+ @Nullable
+ WindowInfo findWindowInfoByIdLocked(int windowId) {
+ return mWindowInfoById.get(windowId);
+ }
+
+ /**
+ * Returns {@link AccessibilityWindowInfo} of PIP window.
+ *
+ * @return PIP accessibility window info
+ */
+ @Nullable
+ AccessibilityWindowInfo getPictureInPictureWindowLocked() {
+ if (mWindows != null) {
+ final int windowCount = mWindows.size();
+ for (int i = 0; i < windowCount; i++) {
+ final AccessibilityWindowInfo window = mWindows.get(i);
+ if (window.isInPictureInPictureMode()) {
+ return window;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Sets the active flag of the window according to given windowId, others set to inactive.
+ *
+ * @param windowId The windowId
+ */
+ void setActiveWindowLocked(int windowId) {
+ if (mWindows != null) {
+ final int windowCount = mWindows.size();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = mWindows.get(i);
+ if (window.getId() == windowId) {
+ window.setActive(true);
+ mAccessibilityEventSender.sendAccessibilityEventForCurrentUserLocked(
+ AccessibilityEvent.obtainWindowsChangedEvent(windowId,
+ AccessibilityEvent.WINDOWS_CHANGE_ACTIVE));
+ } else {
+ window.setActive(false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the window accessibility focused according to given windowId, others set
+ * unfocused.
+ *
+ * @param windowId The windowId
+ */
+ void setAccessibilityFocusedWindowLocked(int windowId) {
+ if (mWindows != null) {
+ final int windowCount = mWindows.size();
+ for (int i = 0; i < windowCount; i++) {
+ AccessibilityWindowInfo window = mWindows.get(i);
+ if (window.getId() == windowId) {
+ window.setAccessibilityFocused(true);
+ mAccessibilityEventSender.sendAccessibilityEventForCurrentUserLocked(
+ AccessibilityEvent.obtainWindowsChangedEvent(
+ windowId, WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
+
+ } else {
+ window.setAccessibilityFocused(false);
+ }
+ }
+ }
+ }
+
+ /**
+ * Computes partial interactive region of given windowId.
+ *
+ * @param windowId The windowId
+ * @param outRegion The output to which to write the bounds.
+ * @return true if outRegion is not empty.
+ */
+ boolean computePartialInteractiveRegionForWindowLocked(int windowId,
+ @NonNull Region outRegion) {
+ if (mWindows == null) {
+ return false;
+ }
+
+ // Windows are ordered in z order so start from the bottom and find
+ // the window of interest. After that all windows that cover it should
+ // be subtracted from the resulting region. Note that for accessibility
+ // we are returning only interactive windows.
+ Region windowInteractiveRegion = null;
+ boolean windowInteractiveRegionChanged = false;
+
+ final int windowCount = mWindows.size();
+ final Region currentWindowRegions = new Region();
+ for (int i = windowCount - 1; i >= 0; i--) {
+ AccessibilityWindowInfo currentWindow = mWindows.get(i);
+ if (windowInteractiveRegion == null) {
+ if (currentWindow.getId() == windowId) {
+ currentWindow.getRegionInScreen(currentWindowRegions);
+ outRegion.set(currentWindowRegions);
+ windowInteractiveRegion = outRegion;
+ continue;
+ }
+ } else if (currentWindow.getType()
+ != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
+ currentWindow.getRegionInScreen(currentWindowRegions);
+ if (windowInteractiveRegion.op(currentWindowRegions, Region.Op.DIFFERENCE)) {
+ windowInteractiveRegionChanged = true;
+ }
+ }
+ }
+
+ return windowInteractiveRegionChanged;
+ }
+
+ List<Integer> getWatchOutsideTouchWindowIdLocked(int targetWindowId) {
+ final WindowInfo targetWindow = mWindowInfoById.get(targetWindowId);
+ if (targetWindow != null && mHasWatchOutsideTouchWindow) {
+ final List<Integer> outsideWindowsId = new ArrayList<>();
+ for (int i = 0; i < mWindowInfoById.size(); i++) {
+ final WindowInfo window = mWindowInfoById.valueAt(i);
+ if (window != null && window.layer < targetWindow.layer
+ && window.hasFlagWatchOutsideTouch) {
+ outsideWindowsId.add(mWindowInfoById.keyAt(i));
+ }
+ }
+ return outsideWindowsId;
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * Callbacks from window manager when there's an accessibility change in windows.
+ *
+ * @param forceSend Send the windows for accessibility even if they haven't changed.
+ * @param windows The windows for accessibility.
+ */
+ @Override
+ public void onWindowsForAccessibilityChanged(boolean forceSend,
+ @NonNull List<WindowInfo> windows) {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Display Id = " + mDisplayId);
+ Slog.i(LOG_TAG, "Windows changed: " + windows);
+ }
+ if (shouldUpdateWindowsLocked(forceSend, windows)) {
+ cacheWindows(windows);
+ // Lets the policy update the focused and active windows.
+ updateWindowsLocked(mAccessibilityUserManager.getCurrentUserIdLocked(),
+ windows);
+ // Someone may be waiting for the windows - advertise it.
+ mLock.notifyAll();
+ }
+ }
+ }
+
+ private boolean shouldUpdateWindowsLocked(boolean forceSend,
+ @NonNull List<WindowInfo> windows) {
+ if (forceSend) {
+ return true;
+ }
+
+ final int windowCount = windows.size();
+ // We computed the windows and if they changed notify the client.
+ if (mCachedWindowInfos.size() != windowCount) {
+ // Different size means something changed.
+ return true;
+ } else if (!mCachedWindowInfos.isEmpty() || !windows.isEmpty()) {
+ // Since we always traverse windows from high to low layer
+ // the old and new windows at the same index should be the
+ // same, otherwise something changed.
+ for (int i = 0; i < windowCount; i++) {
+ WindowInfo oldWindow = mCachedWindowInfos.get(i);
+ WindowInfo newWindow = windows.get(i);
+ // We do not care for layer changes given the window
+ // order does not change. This brings no new information
+ // to the clients.
+ if (windowChangedNoLayer(oldWindow, newWindow)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private void cacheWindows(List<WindowInfo> windows) {
+ final int oldWindowCount = mCachedWindowInfos.size();
+ for (int i = oldWindowCount - 1; i >= 0; i--) {
+ mCachedWindowInfos.remove(i).recycle();
+ }
+ final int newWindowCount = windows.size();
+ for (int i = 0; i < newWindowCount; i++) {
+ WindowInfo newWindow = windows.get(i);
+ mCachedWindowInfos.add(WindowInfo.obtain(newWindow));
+ }
+ }
+
+ private boolean windowChangedNoLayer(WindowInfo oldWindow, WindowInfo newWindow) {
+ if (oldWindow == newWindow) {
+ return false;
+ }
+ if (oldWindow == null) {
+ return true;
+ }
+ if (newWindow == null) {
+ return true;
+ }
+ if (oldWindow.type != newWindow.type) {
+ return true;
+ }
+ if (oldWindow.focused != newWindow.focused) {
+ return true;
+ }
+ if (oldWindow.token == null) {
+ if (newWindow.token != null) {
+ return true;
+ }
+ } else if (!oldWindow.token.equals(newWindow.token)) {
+ return true;
+ }
+ if (oldWindow.parentToken == null) {
+ if (newWindow.parentToken != null) {
+ return true;
+ }
+ } else if (!oldWindow.parentToken.equals(newWindow.parentToken)) {
+ return true;
+ }
+ if (oldWindow.activityToken == null) {
+ if (newWindow.activityToken != null) {
+ return true;
+ }
+ } else if (!oldWindow.activityToken.equals(newWindow.activityToken)) {
+ return true;
+ }
+ if (!oldWindow.regionInScreen.equals(newWindow.regionInScreen)) {
+ return true;
+ }
+ if (oldWindow.childTokens != null && newWindow.childTokens != null
+ && !oldWindow.childTokens.equals(newWindow.childTokens)) {
+ return true;
+ }
+ if (!TextUtils.equals(oldWindow.title, newWindow.title)) {
+ return true;
+ }
+ if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) {
+ return true;
+ }
+ if (oldWindow.inPictureInPicture != newWindow.inPictureInPicture) {
+ return true;
+ }
+ if (oldWindow.hasFlagWatchOutsideTouch != newWindow.hasFlagWatchOutsideTouch) {
+ return true;
+ }
+ if (oldWindow.displayId != newWindow.displayId) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Clears all {@link AccessibilityWindowInfo}s and {@link WindowInfo}s.
+ */
+ private void clearWindowsLocked() {
+ final List<WindowInfo> windows = Collections.emptyList();
+ final int activeWindowId = mActiveWindowId;
+ // UserId is useless in updateWindowsLocked, when we update a empty window list.
+ // Just pass current userId here.
+ updateWindowsLocked(mAccessibilityUserManager.getCurrentUserIdLocked(), windows);
+ // Do not reset mActiveWindowId here. mActiveWindowId will be clear after accessibility
+ // interaction connection removed.
+ mActiveWindowId = activeWindowId;
+ mWindows = null;
+ }
+
+ /**
+ * Updates windows info according to specified userId and windows.
+ *
+ * @param userId The userId to update
+ * @param windows The windows to update
+ */
+ private void updateWindowsLocked(int userId, @NonNull List<WindowInfo> windows) {
+ if (mWindows == null) {
+ mWindows = new ArrayList<>();
+ }
+
+ final List<AccessibilityWindowInfo> oldWindowList = new ArrayList<>(mWindows);
+ final SparseArray<AccessibilityWindowInfo> oldWindowsById = mA11yWindowInfoById.clone();
+
+ mWindows.clear();
+ mA11yWindowInfoById.clear();
+
+ for (int i = 0; i < mWindowInfoById.size(); i++) {
+ mWindowInfoById.valueAt(i).recycle();
+ }
+ mWindowInfoById.clear();
+ mHasWatchOutsideTouchWindow = false;
+ mFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ if (!mTouchInteractionInProgress) {
+ mActiveWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ }
+
+ // If the active window goes away while the user is touch exploring we
+ // reset the active window id and wait for the next hover event from
+ // under the user's finger to determine which one is the new one. It
+ // is possible that the finger is not moving and the input system
+ // filters out such events.
+ boolean activeWindowGone = true;
+
+ final int windowCount = windows.size();
+
+ // We'll clear accessibility focus if the window with focus is no longer visible to
+ // accessibility services
+ boolean shouldClearAccessibilityFocus =
+ mAccessibilityFocusedWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
+ if (windowCount > 0) {
+ for (int i = 0; i < windowCount; i++) {
+ final WindowInfo windowInfo = windows.get(i);
+ final AccessibilityWindowInfo window;
+ if (isTrackingWindowsLocked()) {
+ window = populateReportedWindowLocked(userId, windowInfo);
+ } else {
+ window = null;
+ }
+ if (window != null) {
+
+ // Flip layers in list to be consistent with AccessibilityService#getWindows
+ window.setLayer(windowCount - 1 - window.getLayer());
+
+ final int windowId = window.getId();
+ if (window.isFocused()) {
+ mFocusedWindowId = windowId;
+ if (!mTouchInteractionInProgress) {
+ mActiveWindowId = windowId;
+ window.setActive(true);
+ } else if (windowId == mActiveWindowId) {
+ activeWindowGone = false;
+ }
+ }
+ if (!mHasWatchOutsideTouchWindow && windowInfo.hasFlagWatchOutsideTouch) {
+ mHasWatchOutsideTouchWindow = true;
+ }
+ mWindows.add(window);
+ mA11yWindowInfoById.put(windowId, window);
+ mWindowInfoById.put(windowId, WindowInfo.obtain(windowInfo));
+ }
+ }
+
+ if (mTouchInteractionInProgress && activeWindowGone) {
+ mActiveWindowId = mFocusedWindowId;
+ }
+
+ // Focused window may change the active one, so set the
+ // active window once we decided which it is.
+ final int accessibilityWindowCount = mWindows.size();
+ for (int i = 0; i < accessibilityWindowCount; i++) {
+ final AccessibilityWindowInfo window = mWindows.get(i);
+ if (window.getId() == mActiveWindowId) {
+ window.setActive(true);
+ }
+ if (window.getId() == mAccessibilityFocusedWindowId) {
+ window.setAccessibilityFocused(true);
+ shouldClearAccessibilityFocus = false;
+ }
+ }
+ }
+
+ sendEventsForChangedWindowsLocked(oldWindowList, oldWindowsById);
+
+ final int oldWindowCount = oldWindowList.size();
+ for (int i = oldWindowCount - 1; i >= 0; i--) {
+ oldWindowList.remove(i).recycle();
+ }
+
+ if (shouldClearAccessibilityFocus) {
+ clearAccessibilityFocusLocked(mAccessibilityFocusedWindowId);
+ }
+ }
+
+ private void sendEventsForChangedWindowsLocked(List<AccessibilityWindowInfo> oldWindows,
+ SparseArray<AccessibilityWindowInfo> oldWindowsById) {
+ List<AccessibilityEvent> events = new ArrayList<>();
+ // Sends events for all removed windows.
+ final int oldWindowsCount = oldWindows.size();
+ for (int i = 0; i < oldWindowsCount; i++) {
+ final AccessibilityWindowInfo window = oldWindows.get(i);
+ if (mA11yWindowInfoById.get(window.getId()) == null) {
+ events.add(AccessibilityEvent.obtainWindowsChangedEvent(
+ window.getId(), AccessibilityEvent.WINDOWS_CHANGE_REMOVED));
+ }
+ }
+
+ // Looks for other changes.
+ final int newWindowCount = mWindows.size();
+ for (int i = 0; i < newWindowCount; i++) {
+ final AccessibilityWindowInfo newWindow = mWindows.get(i);
+ final AccessibilityWindowInfo oldWindow = oldWindowsById.get(newWindow.getId());
+ if (oldWindow == null) {
+ events.add(AccessibilityEvent.obtainWindowsChangedEvent(
+ newWindow.getId(), AccessibilityEvent.WINDOWS_CHANGE_ADDED));
+ } else {
+ int changes = newWindow.differenceFrom(oldWindow);
+ if (changes != 0) {
+ events.add(AccessibilityEvent.obtainWindowsChangedEvent(
+ newWindow.getId(), changes));
+ }
+ }
+ }
+
+ final int numEvents = events.size();
+ for (int i = 0; i < numEvents; i++) {
+ mAccessibilityEventSender.sendAccessibilityEventForCurrentUserLocked(events.get(i));
+ }
+ }
+
+ private AccessibilityWindowInfo populateReportedWindowLocked(int userId,
+ WindowInfo window) {
+ final int windowId = findWindowIdLocked(userId, window.token);
+ if (windowId < 0) {
+ return null;
+ }
+
+ final AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain();
+
+ reportedWindow.setId(windowId);
+ reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
+ reportedWindow.setLayer(window.layer);
+ reportedWindow.setFocused(window.focused);
+ reportedWindow.setRegionInScreen(window.regionInScreen);
+ reportedWindow.setTitle(window.title);
+ reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
+ reportedWindow.setPictureInPicture(window.inPictureInPicture);
+ reportedWindow.setDisplayId(window.displayId);
+
+ final int parentId = findWindowIdLocked(userId, window.parentToken);
+ if (parentId >= 0) {
+ reportedWindow.setParentId(parentId);
+ }
+
+ if (window.childTokens != null) {
+ final int childCount = window.childTokens.size();
+ for (int i = 0; i < childCount; i++) {
+ final IBinder childToken = window.childTokens.get(i);
+ final int childId = findWindowIdLocked(userId, childToken);
+ if (childId >= 0) {
+ reportedWindow.addChild(childId);
+ }
+ }
+ }
+
+ return reportedWindow;
+ }
+
+ private int getTypeForWindowManagerWindowType(int windowType) {
+ switch (windowType) {
+ case WindowManager.LayoutParams.TYPE_APPLICATION:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL:
+ case WindowManager.LayoutParams.TYPE_BASE_APPLICATION:
+ case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION:
+ case WindowManager.LayoutParams.TYPE_PHONE:
+ case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
+ case WindowManager.LayoutParams.TYPE_TOAST:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: {
+ return AccessibilityWindowInfo.TYPE_APPLICATION;
+ }
+
+ case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
+ case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: {
+ return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
+ }
+
+ case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
+ case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
+ case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
+ case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
+ case WindowManager.LayoutParams.TYPE_STATUS_BAR:
+ case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL:
+ case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL:
+ case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_SCREENSHOT: {
+ return AccessibilityWindowInfo.TYPE_SYSTEM;
+ }
+
+ case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
+ return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
+ }
+
+ case TYPE_ACCESSIBILITY_OVERLAY: {
+ return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
+ }
+
+ default: {
+ return -1;
+ }
+ }
+ }
+
+ /**
+ * Dumps all {@link AccessibilityWindowInfo}s here.
+ */
+ void dumpLocked(FileDescriptor fd, final PrintWriter pw, String[] args) {
+ if (mWindows != null) {
+ final int windowCount = mWindows.size();
+ for (int j = 0; j < windowCount; j++) {
+ if (j == 0) {
+ pw.append("Display[");
+ pw.append(Integer.toString(mDisplayId));
+ pw.append("] : ");
+ pw.println();
+ }
+ if (j > 0) {
+ pw.append(',');
+ pw.println();
+ }
+ pw.append("Window[");
+ AccessibilityWindowInfo window = mWindows.get(j);
+ pw.append(window.toString());
+ pw.append(']');
+ }
+ pw.println();
+ }
+ }
+ }
/**
* Interface to send {@link AccessibilityEvent}.
*/
public interface AccessibilityEventSender {
/**
- * Send {@link AccessibilityEvent} for current user.
+ * Sends {@link AccessibilityEvent} for current user.
*/
void sendAccessibilityEventForCurrentUserLocked(AccessibilityEvent event);
}
@@ -171,166 +788,24 @@
mAccessibilityEventSender = accessibilityEventSender;
mSecurityPolicy = securityPolicy;
mAccessibilityUserManager = accessibilityUserManager;
-
+ mDisplayWindowsObserver = new DisplayWindowsObserver(Display.DEFAULT_DISPLAY);
}
/**
- * Callbacks from window manager when there's an accessibility change in windows.
- *
- * @param forceSend Send the windows for accessibility even if they haven't changed.
- * @param windows The windows of current display for accessibility.
- */
- @Override
- public void onWindowsForAccessibilityChanged(boolean forceSend,
- @NonNull List<WindowInfo> windows) {
- synchronized (mLock) {
- if (DEBUG) {
- Slog.i(LOG_TAG, "Windows changed: " + windows);
- }
-
- if (shouldUpdateWindowsLocked(forceSend, windows)) {
- cacheWindows(windows);
- // Let the policy update the focused and active windows.
- updateWindowsLocked(mAccessibilityUserManager.getCurrentUserIdLocked(), windows);
- // Someone may be waiting for the windows - advertise it.
- mLock.notifyAll();
- }
- }
- }
-
- private boolean shouldUpdateWindowsLocked(boolean forceSend,
- @NonNull List<WindowInfo> windows) {
- if (forceSend) {
- return true;
- }
-
- final int windowCount = windows.size();
- // We computed the windows and if they changed notify the client.
- if (mCachedWindowInfos.size() != windowCount) {
- // Different size means something changed.
- return true;
- } else if (!mCachedWindowInfos.isEmpty() || !windows.isEmpty()) {
- // Since we always traverse windows from high to low layer
- // the old and new windows at the same index should be the
- // same, otherwise something changed.
- for (int i = 0; i < windowCount; i++) {
- WindowInfo oldWindow = mCachedWindowInfos.get(i);
- WindowInfo newWindow = windows.get(i);
- // We do not care for layer changes given the window
- // order does not change. This brings no new information
- // to the clients.
- if (windowChangedNoLayer(oldWindow, newWindow)) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- private void cacheWindows(List<WindowInfo> windows) {
- final int oldWindowCount = mCachedWindowInfos.size();
- for (int i = oldWindowCount - 1; i >= 0; i--) {
- mCachedWindowInfos.remove(i).recycle();
- }
- final int newWindowCount = windows.size();
- for (int i = 0; i < newWindowCount; i++) {
- WindowInfo newWindow = windows.get(i);
- mCachedWindowInfos.add(WindowInfo.obtain(newWindow));
- }
- }
-
- private boolean windowChangedNoLayer(WindowInfo oldWindow, WindowInfo newWindow) {
- if (oldWindow == newWindow) {
- return false;
- }
- if (oldWindow == null) {
- return true;
- }
- if (newWindow == null) {
- return true;
- }
- if (oldWindow.type != newWindow.type) {
- return true;
- }
- if (oldWindow.focused != newWindow.focused) {
- return true;
- }
- if (oldWindow.token == null) {
- if (newWindow.token != null) {
- return true;
- }
- } else if (!oldWindow.token.equals(newWindow.token)) {
- return true;
- }
- if (oldWindow.parentToken == null) {
- if (newWindow.parentToken != null) {
- return true;
- }
- } else if (!oldWindow.parentToken.equals(newWindow.parentToken)) {
- return true;
- }
- if (oldWindow.activityToken == null) {
- if (newWindow.activityToken != null) {
- return true;
- }
- } else if (!oldWindow.activityToken.equals(newWindow.activityToken)) {
- return true;
- }
- if (!oldWindow.regionInScreen.equals(newWindow.regionInScreen)) {
- return true;
- }
- if (oldWindow.childTokens != null && newWindow.childTokens != null
- && !oldWindow.childTokens.equals(newWindow.childTokens)) {
- return true;
- }
- if (!TextUtils.equals(oldWindow.title, newWindow.title)) {
- return true;
- }
- if (oldWindow.accessibilityIdOfAnchor != newWindow.accessibilityIdOfAnchor) {
- return true;
- }
- if (oldWindow.inPictureInPicture != newWindow.inPictureInPicture) {
- return true;
- }
- if (oldWindow.hasFlagWatchOutsideTouch != newWindow.hasFlagWatchOutsideTouch) {
- return true;
- }
- if (oldWindow.displayId != newWindow.displayId) {
- return true;
- }
- return false;
- }
-
- /**
- * Start tracking windows changes from window manager.
+ * Starts tracking windows changes from window manager.
*/
public void startTrackingWindows() {
synchronized (mLock) {
- if (!mTrackingWindows) {
- // Turn on the flag before setup the callback.
- // In some cases, onWindowsForAccessibilityChanged will be called immediately in
- // setWindowsForAccessibilityCallback. We'll lost windows if flag is false.
- mTrackingWindows = true;
- // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
- mWindowManagerInternal.setWindowsForAccessibilityCallback(Display.DEFAULT_DISPLAY,
- this);
- }
+ mDisplayWindowsObserver.startTrackingWindowsLocked();
}
}
/**
- * stop tracking windows changes from window manager, and clear all windows info.
+ * Stops tracking windows changes from window manager, and clear all windows info.
*/
public void stopTrackingWindows() {
synchronized (mLock) {
- if (mTrackingWindows) {
- // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
- mWindowManagerInternal.setWindowsForAccessibilityCallback(Display.DEFAULT_DISPLAY,
- null);
- mTrackingWindows = false;
- clearWindowsLocked();
- }
+ mDisplayWindowsObserver.stopTrackingWindowsLocked();
}
}
@@ -340,127 +815,7 @@
* @return true if windows changes tracking
*/
public boolean isTrackingWindowsLocked() {
- return mTrackingWindows;
- }
-
- /**
- * Clears all {@link AccessibilityWindowInfo}s and {@link WindowInfo}s.
- */
- private void clearWindowsLocked() {
- final List<WindowInfo> windows = Collections.emptyList();
- final int activeWindowId = mActiveWindowId;
- // userId is useless in updateWindowsLocked, when we update a empty window list. Just pass
- // current userId here.
- updateWindowsLocked(mAccessibilityUserManager.getCurrentUserIdLocked(), windows);
- // Do not reset mActiveWindowId here. mActiveWindowId will be clear after accessibility
- // interaction connection removed.
- mActiveWindowId = activeWindowId;
- mWindows = null;
- }
-
- /**
- * Update windows info according to specified userId and windows.
- *
- * @param userId The userId to update
- * @param windows The windows to update
- */
- private void updateWindowsLocked(int userId, @NonNull List<WindowInfo> windows) {
- if (mWindows == null) {
- mWindows = new ArrayList<>();
- }
-
- final List<AccessibilityWindowInfo> oldWindowList = new ArrayList<>(mWindows);
- final SparseArray<AccessibilityWindowInfo> oldWindowsById = mA11yWindowInfoById.clone();
-
- mWindows.clear();
- mA11yWindowInfoById.clear();
-
- for (int i = 0; i < mWindowInfoById.size(); i++) {
- mWindowInfoById.valueAt(i).recycle();
- }
- mWindowInfoById.clear();
- mHasWatchOutsideTouchWindow = false;
-
- mFocusedWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
- if (!mTouchInteractionInProgress) {
- mActiveWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
- }
-
- // If the active window goes away while the user is touch exploring we
- // reset the active window id and wait for the next hover event from
- // under the user's finger to determine which one is the new one. It
- // is possible that the finger is not moving and the input system
- // filters out such events.
- boolean activeWindowGone = true;
-
- final int windowCount = windows.size();
-
- // We'll clear accessibility focus if the window with focus is no longer visible to
- // accessibility services
- boolean shouldClearAccessibilityFocus =
- mAccessibilityFocusedWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
- if (windowCount > 0) {
- for (int i = 0; i < windowCount; i++) {
- final WindowInfo windowInfo = windows.get(i);
- final AccessibilityWindowInfo window;
- if (isTrackingWindowsLocked()) {
- window = populateReportedWindowLocked(userId, windowInfo);
- } else {
- window = null;
- }
- if (window != null) {
-
- // Flip layers in list to be consistent with AccessibilityService#getWindows
- window.setLayer(windowCount - 1 - window.getLayer());
-
- final int windowId = window.getId();
- if (window.isFocused()) {
- mFocusedWindowId = windowId;
- if (!mTouchInteractionInProgress) {
- mActiveWindowId = windowId;
- window.setActive(true);
- } else if (windowId == mActiveWindowId) {
- activeWindowGone = false;
- }
- }
- if (!mHasWatchOutsideTouchWindow && windowInfo.hasFlagWatchOutsideTouch) {
- mHasWatchOutsideTouchWindow = true;
- }
- mWindows.add(window);
- mA11yWindowInfoById.put(windowId, window);
- mWindowInfoById.put(windowId, WindowInfo.obtain(windowInfo));
- }
- }
-
- if (mTouchInteractionInProgress && activeWindowGone) {
- mActiveWindowId = mFocusedWindowId;
- }
-
- // Focused window may change the active one, so set the
- // active window once we decided which it is.
- final int accessibilityWindowCount = mWindows.size();
- for (int i = 0; i < accessibilityWindowCount; i++) {
- final AccessibilityWindowInfo window = mWindows.get(i);
- if (window.getId() == mActiveWindowId) {
- window.setActive(true);
- }
- if (window.getId() == mAccessibilityFocusedWindowId) {
- window.setAccessibilityFocused(true);
- shouldClearAccessibilityFocus = false;
- }
- }
- }
-
- sendEventsForChangedWindowsLocked(oldWindowList, oldWindowsById);
-
- final int oldWindowCount = oldWindowList.size();
- for (int i = oldWindowCount - 1; i >= 0; i--) {
- oldWindowList.remove(i).recycle();
- }
-
- if (shouldClearAccessibilityFocus) {
- clearAccessibilityFocusLocked(mAccessibilityFocusedWindowId);
- }
+ return mDisplayWindowsObserver.isTrackingWindowsLocked();
}
/**
@@ -468,7 +823,7 @@
*/
@Nullable
public List<AccessibilityWindowInfo> getWindowListLocked() {
- return mWindows;
+ return mDisplayWindowsObserver.getWindowListLocked();
}
/**
@@ -494,7 +849,7 @@
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
final int resolvedUid = UserHandle.getUid(resolvedUserId, UserHandle.getCallingAppId());
- // Make sure the reported package is one the caller has access to.
+ // Makes sure the reported package is one the caller has access to.
packageName = mSecurityPolicy.resolveValidReportedPackageLocked(
packageName, UserHandle.getCallingAppId(), resolvedUserId);
@@ -576,7 +931,7 @@
}
/**
- * Resolve a connection wrapper for a window id
+ * Resolves a connection wrapper for a window id.
*
* @param userId The user id for any user-specific windows
* @param windowId The id of the window of interest
@@ -672,7 +1027,7 @@
}
/**
- * Return the userId that owns the given window token, {@link UserHandle#USER_NULL}
+ * Returns the userId that owns the given window token, {@link UserHandle#USER_NULL}
* if not found.
*
* @param windowToken The winodw token
@@ -703,42 +1058,6 @@
return -1;
}
- private void sendEventsForChangedWindowsLocked(List<AccessibilityWindowInfo> oldWindows,
- SparseArray<AccessibilityWindowInfo> oldWindowsById) {
- List<AccessibilityEvent> events = new ArrayList<>();
- // Send events for all removed windows
- final int oldWindowsCount = oldWindows.size();
- for (int i = 0; i < oldWindowsCount; i++) {
- final AccessibilityWindowInfo window = oldWindows.get(i);
- if (mA11yWindowInfoById.get(window.getId()) == null) {
- events.add(AccessibilityEvent.obtainWindowsChangedEvent(
- window.getId(), AccessibilityEvent.WINDOWS_CHANGE_REMOVED));
- }
- }
-
- // Look for other changes
- final int newWindowCount = mWindows.size();
- for (int i = 0; i < newWindowCount; i++) {
- final AccessibilityWindowInfo newWindow = mWindows.get(i);
- final AccessibilityWindowInfo oldWindow = oldWindowsById.get(newWindow.getId());
- if (oldWindow == null) {
- events.add(AccessibilityEvent.obtainWindowsChangedEvent(
- newWindow.getId(), AccessibilityEvent.WINDOWS_CHANGE_ADDED));
- } else {
- int changes = newWindow.differenceFrom(oldWindow);
- if (changes != 0) {
- events.add(AccessibilityEvent.obtainWindowsChangedEvent(
- newWindow.getId(), changes));
- }
- }
- }
-
- final int numEvents = events.size();
- for (int i = 0; i < numEvents; i++) {
- mAccessibilityEventSender.sendAccessibilityEventForCurrentUserLocked(events.get(i));
- }
- }
-
/**
* Computes partial interactive region of given windowId.
*
@@ -748,38 +1067,8 @@
*/
public boolean computePartialInteractiveRegionForWindowLocked(int windowId,
@NonNull Region outRegion) {
- if (mWindows == null) {
- return false;
- }
-
- // Windows are ordered in z order so start from the bottom and find
- // the window of interest. After that all windows that cover it should
- // be subtracted from the resulting region. Note that for accessibility
- // we are returning only interactive windows.
- Region windowInteractiveRegion = null;
- boolean windowInteractiveRegionChanged = false;
-
- final int windowCount = mWindows.size();
- final Region currentWindowRegions = new Region();
- for (int i = windowCount - 1; i >= 0; i--) {
- AccessibilityWindowInfo currentWindow = mWindows.get(i);
- if (windowInteractiveRegion == null) {
- if (currentWindow.getId() == windowId) {
- currentWindow.getRegionInScreen(currentWindowRegions);
- outRegion.set(currentWindowRegions);
- windowInteractiveRegion = outRegion;
- continue;
- }
- } else if (currentWindow.getType()
- != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
- currentWindow.getRegionInScreen(currentWindowRegions);
- if (windowInteractiveRegion.op(currentWindowRegions, Region.Op.DIFFERENCE)) {
- windowInteractiveRegionChanged = true;
- }
- }
- }
-
- return windowInteractiveRegionChanged;
+ return mDisplayWindowsObserver.computePartialInteractiveRegionForWindowLocked(windowId,
+ outRegion);
}
/**
@@ -846,7 +1135,7 @@
mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
}
// Clear the window with focus if it no longer has focus and we aren't
- // just moving focus from one view to the other in the same window
+ // just moving focus from one view to the other in the same window.
if ((mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
&& (mAccessibilityFocusedWindowId == windowId)
&& (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)) {
@@ -904,7 +1193,7 @@
}
/**
- * Get the id of the current active window.
+ * Gets the id of the current active window.
*
* @return The userId
*/
@@ -923,20 +1212,7 @@
mActiveWindowId, AccessibilityEvent.WINDOWS_CHANGE_ACTIVE));
mActiveWindowId = windowId;
- if (mWindows != null) {
- final int windowCount = mWindows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = mWindows.get(i);
- if (window.getId() == windowId) {
- window.setActive(true);
- mAccessibilityEventSender.sendAccessibilityEventForCurrentUserLocked(
- AccessibilityEvent.obtainWindowsChangedEvent(windowId,
- AccessibilityEvent.WINDOWS_CHANGE_ACTIVE));
- } else {
- window.setActive(false);
- }
- }
- }
+ mDisplayWindowsObserver.setActiveWindowLocked(windowId);
}
}
@@ -948,21 +1224,7 @@
WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
mAccessibilityFocusedWindowId = windowId;
- if (mWindows != null) {
- final int windowCount = mWindows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = mWindows.get(i);
- if (window.getId() == windowId) {
- window.setAccessibilityFocused(true);
- mAccessibilityEventSender.sendAccessibilityEventForCurrentUserLocked(
- AccessibilityEvent.obtainWindowsChangedEvent(
- windowId, WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED));
-
- } else {
- window.setAccessibilityFocused(false);
- }
- }
- }
+ mDisplayWindowsObserver.setAccessibilityFocusedWindowLocked(windowId);
}
}
@@ -973,8 +1235,8 @@
* @return The accessibility window info
*/
@Nullable
- public AccessibilityWindowInfo findA11yWindowInfoById(int windowId) {
- return mA11yWindowInfoById.get(windowId);
+ public AccessibilityWindowInfo findA11yWindowInfoByIdLocked(int windowId) {
+ return mDisplayWindowsObserver.findA11yWindowInfoByIdLocked(windowId);
}
/**
@@ -984,8 +1246,8 @@
* @return The window info
*/
@Nullable
- public WindowInfo findWindowInfoById(int windowId) {
- return mWindowInfoById.get(windowId);
+ public WindowInfo findWindowInfoByIdLocked(int windowId) {
+ return mDisplayWindowsObserver.findWindowInfoByIdLocked(windowId);
}
/**
@@ -1010,21 +1272,12 @@
* @return PIP accessibility window info
*/
@Nullable
- public AccessibilityWindowInfo getPictureInPictureWindow() {
- if (mWindows != null) {
- final int windowCount = mWindows.size();
- for (int i = 0; i < windowCount; i++) {
- final AccessibilityWindowInfo window = mWindows.get(i);
- if (window.isInPictureInPictureMode()) {
- return window;
- }
- }
- }
- return null;
+ public AccessibilityWindowInfo getPictureInPictureWindowLocked() {
+ return mDisplayWindowsObserver.getPictureInPictureWindowLocked();
}
/**
- * Set an IAccessibilityInteractionConnection to replace the actions of a picture-in-picture
+ * Sets an IAccessibilityInteractionConnection to replace the actions of a picture-in-picture
* window.
*/
public void setPictureInPictureActionReplacingConnection(
@@ -1060,7 +1313,8 @@
final List<Integer> outsideWindowsIds;
final List<RemoteAccessibilityConnection> connectionList = new ArrayList<>();
synchronized (mLock) {
- outsideWindowsIds = getWatchOutsideTouchWindowIdLocked(targetWindowId);
+ outsideWindowsIds =
+ mDisplayWindowsObserver.getWatchOutsideTouchWindowIdLocked(targetWindowId);
for (int i = 0; i < outsideWindowsIds.size(); i++) {
connectionList.add(getConnectionLocked(userId, outsideWindowsIds.get(i)));
}
@@ -1079,22 +1333,6 @@
}
}
- private List<Integer> getWatchOutsideTouchWindowIdLocked(int targetWindowId) {
- final WindowInfo targetWindow = mWindowInfoById.get(targetWindowId);
- if (targetWindow != null && mHasWatchOutsideTouchWindow) {
- final List<Integer> outsideWindowsId = new ArrayList<>();
- for (int i = 0; i < mWindowInfoById.size(); i++) {
- final WindowInfo window = mWindowInfoById.valueAt(i);
- if (window != null && window.layer < targetWindow.layer
- && window.hasFlagWatchOutsideTouch) {
- outsideWindowsId.add(mWindowInfoById.keyAt(i));
- }
- }
- return outsideWindowsId;
- }
- return Collections.emptyList();
- }
-
/**
* Gets current input focused window token from window manager, and returns its windowId.
*
@@ -1108,96 +1346,6 @@
}
}
- private AccessibilityWindowInfo populateReportedWindowLocked(int userId, WindowInfo window) {
- final int windowId = findWindowIdLocked(userId, window.token);
- if (windowId < 0) {
- return null;
- }
-
- final AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain();
-
- reportedWindow.setId(windowId);
- reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
- reportedWindow.setLayer(window.layer);
- reportedWindow.setFocused(window.focused);
- reportedWindow.setRegionInScreen(window.regionInScreen);
- reportedWindow.setTitle(window.title);
- reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
- reportedWindow.setPictureInPicture(window.inPictureInPicture);
- reportedWindow.setDisplayId(window.displayId);
-
- final int parentId = findWindowIdLocked(userId, window.parentToken);
- if (parentId >= 0) {
- reportedWindow.setParentId(parentId);
- }
-
- if (window.childTokens != null) {
- final int childCount = window.childTokens.size();
- for (int i = 0; i < childCount; i++) {
- final IBinder childToken = window.childTokens.get(i);
- final int childId = findWindowIdLocked(userId, childToken);
- if (childId >= 0) {
- reportedWindow.addChild(childId);
- }
- }
- }
-
- return reportedWindow;
- }
-
- private int getTypeForWindowManagerWindowType(int windowType) {
- switch (windowType) {
- case WindowManager.LayoutParams.TYPE_APPLICATION:
- case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
- case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
- case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING:
- case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
- case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL:
- case WindowManager.LayoutParams.TYPE_BASE_APPLICATION:
- case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION:
- case WindowManager.LayoutParams.TYPE_PHONE:
- case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
- case WindowManager.LayoutParams.TYPE_TOAST:
- case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: {
- return AccessibilityWindowInfo.TYPE_APPLICATION;
- }
-
- case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
- case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: {
- return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
- }
-
- case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
- case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
- case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
- case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
- case WindowManager.LayoutParams.TYPE_STATUS_BAR:
- case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL:
- case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL:
- case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
- case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
- case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
- case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
- case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
- case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:
- case WindowManager.LayoutParams.TYPE_SCREENSHOT: {
- return AccessibilityWindowInfo.TYPE_SYSTEM;
- }
-
- case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
- return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
- }
-
- case TYPE_ACCESSIBILITY_OVERLAY: {
- return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
- }
-
- default: {
- return -1;
- }
- }
- }
-
private boolean isValidUserForInteractionConnectionsLocked(int userId) {
return mInteractionConnections.indexOfKey(userId) >= 0;
}
@@ -1251,22 +1399,9 @@
}
/**
- * Dump all {@link AccessibilityWindowInfo}s here.
+ * Dumps all {@link AccessibilityWindowInfo}s here.
*/
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
- if (mWindows != null) {
- final int windowCount = mWindows.size();
- for (int j = 0; j < windowCount; j++) {
- if (j > 0) {
- pw.append(',');
- pw.println();
- }
- pw.append("Window[");
- AccessibilityWindowInfo window = mWindows.get(j);
- pw.append(window.toString());
- pw.append(']');
- }
- pw.println();
- }
+ mDisplayWindowsObserver.dumpLocked(fd, pw, args);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 0dd7199..a0900b6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -528,12 +528,12 @@
options.setLockTaskEnabled(true);
}
if (mWaitOption) {
- result = mInternal.startActivityAndWait(null, null, intent, mimeType,
+ result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, intent, mimeType,
null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
res = result.result;
} else {
- res = mInternal.startActivityAsUser(null, null, intent, mimeType,
+ res = mInternal.startActivityAsUser(null, SHELL_PACKAGE_NAME, intent, mimeType,
null, null, 0, mStartFlags, profilerInfo,
options != null ? options.toBundle() : null, mUserId);
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 4957eed..73d160d 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -772,7 +772,6 @@
case WifiManager.WIFI_AP_STATE_FAILED:
default:
disableWifiIpServingLocked(ifname, curState);
- mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
break;
}
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 09e9375..f20003a2 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2551,7 +2551,7 @@
final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis);
if (mStatusBar != null) {
mStatusBar.setImeWindowStatus(mCurTokenDisplayId, mCurToken, vis, backDisposition,
- needsToShowImeSwitcher);
+ needsToShowImeSwitcher, false /*isMultiClientImeEnabled*/);
}
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
if (imi != null && needsToShowImeSwitcher) {
diff --git a/core/java/android/view/inputmethod/InputMethodSystemProperty.java b/services/core/java/com/android/server/inputmethod/InputMethodSystemProperty.java
similarity index 81%
rename from core/java/android/view/inputmethod/InputMethodSystemProperty.java
rename to services/core/java/com/android/server/inputmethod/InputMethodSystemProperty.java
index e20c2fd..a6a6893 100644
--- a/core/java/android/view/inputmethod/InputMethodSystemProperty.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodSystemProperty.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.view.inputmethod;
+package com.android.server.inputmethod;
import android.annotation.Nullable;
import android.content.ComponentName;
@@ -23,8 +23,6 @@
/**
* Various (pseudo) constants about IME behaviors.
- *
- * @hide
*/
public class InputMethodSystemProperty {
/**
@@ -58,23 +56,12 @@
/**
* {@link ComponentName} of multi-client IME to be used.
- *
- * <p>TODO: Move this back to MultiClientInputMethodManagerService once
- * {@link #PER_PROFILE_IME_ENABLED} always becomes {@code true}.</p>
- *
- * @hide
*/
@Nullable
- public static final ComponentName sMultiClientImeComponentName =
- getMultiClientImeComponentName();
+ static final ComponentName sMultiClientImeComponentName = getMultiClientImeComponentName();
/**
* {@code true} when multi-client IME is enabled.
- *
- * <p>TODO: Move this back to MultiClientInputMethodManagerService once
- * {@link #PER_PROFILE_IME_ENABLED} always becomes {@code true}.</p>
- *
- * @hide
*/
public static final boolean MULTI_CLIENT_IME_ENABLED = (sMultiClientImeComponentName != null);
}
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 3dd7304..02e29e0 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -67,7 +67,6 @@
import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
-import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 984f22f..c712431 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -281,20 +281,7 @@
mAbortIdleOptimization.set(false);
long lowStorageThreshold = getLowStorageThreshold(context);
- // Optimize primary apks.
- int result = optimizePackages(pm, pkgs, lowStorageThreshold,
- /*isForPrimaryDex=*/ true);
- if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
- return result;
- }
- if (supportSecondaryDex()) {
- result = reconcileSecondaryDexFiles(pm.getDexManager());
- if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
- return result;
- }
- result = optimizePackages(pm, pkgs, lowStorageThreshold,
- /*isForPrimaryDex=*/ false);
- }
+ int result = idleOptimizePackages(pm, pkgs, lowStorageThreshold);
return result;
}
@@ -342,11 +329,20 @@
return 0;
}
- private int optimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
- long lowStorageThreshold, boolean isForPrimaryDex) {
+ private int idleOptimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
+ long lowStorageThreshold) {
ArraySet<String> updatedPackages = new ArraySet<>();
try {
+ final boolean supportSecondaryDex = supportSecondaryDex();
+
+ if (supportSecondaryDex) {
+ int result = reconcileSecondaryDexFiles(pm.getDexManager());
+ if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
+ return result;
+ }
+ }
+
// Only downgrade apps when space is low on device.
// Threshold is selected above the lowStorageThreshold so that we can pro-actively clean
// up disk before user hits the actual lowStorageThreshold.
@@ -359,43 +355,61 @@
pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
Log.d(TAG, "Unsused Packages " + String.join(",", unusedPackages));
- for (String pkg : unusedPackages) {
- int abortCode = abortIdleOptimizations(/*lowStorageThreshold*/ -1);
- if (abortCode != OPTIMIZE_CONTINUE) {
- // Should be aborted by the scheduler.
- return abortCode;
- }
- if (downgradePackage(pm, pkg, isForPrimaryDex)) {
- updatedPackages.add(pkg);
- }
- }
-
if (!unusedPackages.isEmpty()) {
+ for (String pkg : unusedPackages) {
+ int abortCode = abortIdleOptimizations(/*lowStorageThreshold*/ -1);
+ if (abortCode != OPTIMIZE_CONTINUE) {
+ // Should be aborted by the scheduler.
+ return abortCode;
+ }
+ if (downgradePackage(pm, pkg, /*isForPrimaryDex*/ true)) {
+ updatedPackages.add(pkg);
+ }
+ if (supportSecondaryDex) {
+ downgradePackage(pm, pkg, /*isForPrimaryDex*/ false);
+ }
+ }
+
pkgs = new ArraySet<>(pkgs);
pkgs.removeAll(unusedPackages);
}
}
- for (String pkg : pkgs) {
- int abortCode = abortIdleOptimizations(lowStorageThreshold);
- if (abortCode != OPTIMIZE_CONTINUE) {
- // Either aborted by the scheduler or no space left.
- return abortCode;
- }
-
- boolean dexOptPerformed = optimizePackage(pm, pkg, isForPrimaryDex);
- if (dexOptPerformed) {
- updatedPackages.add(pkg);
- }
+ int primaryResult = optimizePackages(pm, pkgs, lowStorageThreshold,
+ /*isForPrimaryDex*/ true, updatedPackages);
+ if (primaryResult != OPTIMIZE_PROCESSED) {
+ return primaryResult;
}
- return OPTIMIZE_PROCESSED;
+ if (!supportSecondaryDex) {
+ return OPTIMIZE_PROCESSED;
+ }
+
+ int secondaryResult = optimizePackages(pm, pkgs, lowStorageThreshold,
+ /*isForPrimaryDex*/ false, updatedPackages);
+ return secondaryResult;
} finally {
// Always let the pinner service know about changes.
notifyPinService(updatedPackages);
}
}
+ private int optimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
+ long lowStorageThreshold, boolean isForPrimaryDex, ArraySet<String> updatedPackages) {
+ for (String pkg : pkgs) {
+ int abortCode = abortIdleOptimizations(lowStorageThreshold);
+ if (abortCode != OPTIMIZE_CONTINUE) {
+ // Either aborted by the scheduler or no space left.
+ return abortCode;
+ }
+
+ boolean dexOptPerformed = optimizePackage(pm, pkg, isForPrimaryDex);
+ if (dexOptPerformed) {
+ updatedPackages.add(pkg);
+ }
+ }
+ return OPTIMIZE_PROCESSED;
+ }
/**
* Try to downgrade the package to a smaller compilation filter.
diff --git a/services/core/java/com/android/server/pm/ProtectedPackages.java b/services/core/java/com/android/server/pm/ProtectedPackages.java
index a374e14..231168e 100644
--- a/services/core/java/com/android/server/pm/ProtectedPackages.java
+++ b/services/core/java/com/android/server/pm/ProtectedPackages.java
@@ -92,6 +92,9 @@
if (mDeviceOwnerUserId == userId) {
return mDeviceOwnerPackage;
}
+ if (mProfileOwnerPackages == null) {
+ return null;
+ }
return mProfileOwnerPackages.get(userId);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 828f790..d67048f 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -841,7 +841,8 @@
@Override
public void setImeWindowStatus(int displayId, final IBinder token, final int vis,
- final int backDisposition, final boolean showImeSwitcher) {
+ final int backDisposition, final boolean showImeSwitcher,
+ boolean isMultiClientImeEnabled) {
enforceStatusBar();
if (SPEW) {
@@ -858,7 +859,8 @@
if (mBar == null) return;
try {
mBar.setImeWindowStatus(
- displayId, token, vis, backDisposition, showImeSwitcher);
+ displayId, token, vis, backDisposition, showImeSwitcher,
+ isMultiClientImeEnabled);
} catch (RemoteException ex) { }
});
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index f231af9..20ccfa8 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -225,7 +225,6 @@
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;
-import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -262,6 +261,7 @@
import com.android.server.am.UserState;
import com.android.server.appop.AppOpsService;
import com.android.server.firewall.IntentFirewall;
+import com.android.server.inputmethod.InputMethodSystemProperty;
import com.android.server.pm.UserManagerService;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.uri.UriGrantsManagerInternal;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 26e37d6..8fb23a4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2006,6 +2006,7 @@
int attrChanges = 0;
int flagChanges = 0;
+ int privateFlagChanges = 0;
if (attrs != null) {
displayPolicy.adjustWindowParamsLw(win, attrs, pid, uid);
// if they don't have the permission, mask out the status bar bits
@@ -2033,7 +2034,8 @@
attrs.height = win.mAttrs.height;
}
- flagChanges = win.mAttrs.flags ^= attrs.flags;
+ flagChanges = win.mAttrs.flags ^ attrs.flags;
+ privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags;
attrChanges = win.mAttrs.copyFrom(attrs);
if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
| WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
@@ -2050,7 +2052,7 @@
win.getDisplayContent().getDisplayId());
}
- if ((flagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
+ if ((privateFlagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
updateNonSystemOverlayWindowsVisibilityIfNeeded(
win, win.mWinAnimator.getShown());
}
@@ -7543,7 +7545,7 @@
return;
}
final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty();
- if (surfaceShown) {
+ if (surfaceShown && win.hideNonSystemOverlayWindowsWhenVisible()) {
if (!mHidingNonSystemOverlayWindows.contains(win)) {
mHidingNonSystemOverlayWindows.add(win);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 16007d7..6e0d834 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -67,7 +67,6 @@
import android.util.Slog;
import android.view.WindowManager;
import android.view.contentcapture.ContentCaptureManager;
-import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
@@ -101,6 +100,7 @@
import com.android.server.incident.IncidentCompanionService;
import com.android.server.input.InputManagerService;
import com.android.server.inputmethod.InputMethodManagerService;
+import com.android.server.inputmethod.InputMethodSystemProperty;
import com.android.server.inputmethod.MultiClientInputMethodManagerService;
import com.android.server.lights.LightsService;
import com.android.server.media.MediaResourceMonitorService;
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 328e8f4..1c88c40 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -400,22 +400,7 @@
}
@Test
- public void testEvaluateStateLocked_HeartbeatsOn() {
- mConstants.USE_HEARTBEATS = true;
- final ConnectivityController controller = new ConnectivityController(mService);
- final JobStatus red = createJobStatus(createJob()
- .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
- .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED), UID_RED);
-
- controller.evaluateStateLocked(red);
- assertFalse(controller.isStandbyExceptionRequestedLocked(UID_RED));
- verify(mNetPolicyManagerInternal, never())
- .setAppIdleWhitelist(eq(UID_RED), anyBoolean());
- }
-
- @Test
public void testEvaluateStateLocked_JobWithoutConnectivity() {
- mConstants.USE_HEARTBEATS = false;
final ConnectivityController controller = new ConnectivityController(mService);
final JobStatus red = createJobStatus(createJob().setMinimumLatency(1));
@@ -427,7 +412,6 @@
@Test
public void testEvaluateStateLocked_JobWouldBeReady() {
- mConstants.USE_HEARTBEATS = false;
final ConnectivityController controller = spy(new ConnectivityController(mService));
doReturn(true).when(controller).wouldBeReadyWithConnectivityLocked(any());
final JobStatus red = createJobStatus(createJob()
@@ -466,7 +450,6 @@
@Test
public void testEvaluateStateLocked_JobWouldNotBeReady() {
- mConstants.USE_HEARTBEATS = false;
final ConnectivityController controller = spy(new ConnectivityController(mService));
doReturn(false).when(controller).wouldBeReadyWithConnectivityLocked(any());
final JobStatus red = createJobStatus(createJob()
@@ -502,7 +485,6 @@
@Test
public void testReevaluateStateLocked() {
- mConstants.USE_HEARTBEATS = false;
final ConnectivityController controller = spy(new ConnectivityController(mService));
final JobStatus redOne = createJobStatus(createJob(1)
.setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
@@ -625,7 +607,7 @@
private static JobStatus createJobStatus(JobInfo.Builder job, int uid,
long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) {
- return new JobStatus(job.build(), uid, null, -1, 0, 0, null,
+ return new JobStatus(job.build(), uid, null, -1, 0, null,
earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, 0, 0, null, 0);
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 94e02d3b..64da6f6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -573,7 +573,7 @@
long latestRunTimeElapsedMillis) {
final JobInfo job = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY).build();
- return new JobStatus(job, 0, null, -1, 0, 0, null, earliestRunTimeElapsedMillis,
+ return new JobStatus(job, 0, null, -1, 0, null, earliestRunTimeElapsedMillis,
latestRunTimeElapsedMillis, 0, 0, null, 0);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 2d70231..8863d5a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -107,7 +107,6 @@
private static final int SOURCE_USER_ID = 0;
private BroadcastReceiver mChargingReceiver;
- private Constants mJsConstants;
private QuotaController mQuotaController;
private QuotaController.QcConstants mQcConstants;
private int mSourceUid;
@@ -134,14 +133,11 @@
.strictness(Strictness.LENIENT)
.mockStatic(LocalServices.class)
.startMocking();
- // Make sure constants turn on QuotaController.
- mJsConstants = new Constants();
- mJsConstants.USE_HEARTBEATS = false;
// Called in StateController constructor.
when(mJobSchedulerService.getTestableContext()).thenReturn(mContext);
when(mJobSchedulerService.getLock()).thenReturn(mJobSchedulerService);
- when(mJobSchedulerService.getConstants()).thenReturn(mJsConstants);
+ when(mJobSchedulerService.getConstants()).thenReturn(mock(Constants.class));
// Called in QuotaController constructor.
IActivityManager activityManager = ActivityManager.getService();
spyOn(activityManager);
@@ -1809,30 +1805,6 @@
.set(anyInt(), eq(expectedAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
}
- /** Tests that QuotaController doesn't throttle if throttling is turned off. */
- @Test
- public void testThrottleToggling() throws Exception {
- setDischarging();
- mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
- createTimingSession(
- JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS,
- 10 * MINUTE_IN_MILLIS, 4));
- JobStatus jobStatus = createJobStatus("testThrottleToggling", 1);
- setStandbyBucket(WORKING_INDEX, jobStatus); // 2 hour window
- mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
- assertFalse(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
-
- mJsConstants.USE_HEARTBEATS = true;
- mQuotaController.onConstantsUpdatedLocked();
- Thread.sleep(SECOND_IN_MILLIS); // Job updates are done in the background.
- assertTrue(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
-
- mJsConstants.USE_HEARTBEATS = false;
- mQuotaController.onConstantsUpdatedLocked();
- Thread.sleep(SECOND_IN_MILLIS); // Job updates are done in the background.
- assertFalse(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
- }
-
@Test
public void testConstantsUpdating_ValidValues() {
mQcConstants.ALLOWED_TIME_PER_PERIOD_MS = 5 * MINUTE_IN_MILLIS;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index a4267b8..1084d62 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -179,9 +179,9 @@
addA11yWindowInfo(mA11yWindowInfos, WINDOWID, false);
addA11yWindowInfo(mA11yWindowInfos, PIP_WINDOWID, true);
when(mMockA11yWindowManager.getWindowListLocked()).thenReturn(mA11yWindowInfos);
- when(mMockA11yWindowManager.findA11yWindowInfoById(WINDOWID))
+ when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID))
.thenReturn(mA11yWindowInfos.get(0));
- when(mMockA11yWindowManager.findA11yWindowInfoById(PIP_WINDOWID))
+ when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(PIP_WINDOWID))
.thenReturn(mA11yWindowInfos.get(1));
final RemoteAccessibilityConnection conn = getRemoteA11yConnection(
WINDOWID, mMockIA11yInteractionConnection, PACKAGE_NAME1);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
index bb35776..04ac7fe 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
@@ -166,7 +166,7 @@
public void canDispatchAccessibilityEvent_otherEvents_windowIdExist_returnTrue() {
when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM))
.thenReturn(WINDOWID2);
- when(mMockA11yWindowManager.findA11yWindowInfoById(WINDOWID))
+ when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID))
.thenReturn(AccessibilityWindowInfo.obtain());
for (int i = 0; i < OTHER_EVENTS.length; i++) {
final AccessibilityEvent event = AccessibilityEvent.obtain(OTHER_EVENTS[i]);
@@ -287,7 +287,7 @@
.thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM))
.thenReturn(WINDOWID2);
- when(mMockA11yWindowManager.findA11yWindowInfoById(WINDOWID))
+ when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID))
.thenReturn(AccessibilityWindowInfo.obtain());
assertTrue(mA11ySecurityPolicy.canGetAccessibilityNodeInfoLocked(UserHandle.USER_SYSTEM,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
index 7e64caf..7887d5b 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
@@ -34,6 +34,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -53,6 +54,7 @@
import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection;
import com.android.server.wm.WindowManagerInternal;
+import com.android.server.wm.WindowManagerInternal.WindowsForAccessibilityCallback;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
@@ -75,9 +77,12 @@
private static final boolean FORCE_SEND = true;
private static final boolean SEND_ON_WINDOW_CHANGES = false;
private static final int USER_SYSTEM_ID = UserHandle.USER_SYSTEM;
+ // TO-DO [Multi-Display] : change the display count to 2
+ private static final int DISPLAY_COUNT = 1;
private static final int NUM_GLOBAL_WINDOWS = 4;
private static final int NUM_APP_WINDOWS = 4;
- private static final int NUM_OF_WINDOWS = NUM_GLOBAL_WINDOWS + NUM_APP_WINDOWS;
+ private static final int NUM_OF_WINDOWS = (NUM_GLOBAL_WINDOWS + NUM_APP_WINDOWS)
+ * DISPLAY_COUNT;
private static final int DEFAULT_FOCUSED_INDEX = 1;
private static final int SCREEN_WIDTH = 1080;
private static final int SCREEN_HEIGHT = 1920;
@@ -86,7 +91,13 @@
// List of window token, mapping from windowId -> window token.
private final SparseArray<IWindow> mA11yWindowTokens = new SparseArray<>();
- private final ArrayList<WindowInfo> mWindowInfos = new ArrayList<>();
+ // List of window info lists, mapping from displayId -> window info lists.
+ private final SparseArray<ArrayList<WindowInfo>> mWindowInfos =
+ new SparseArray<>();
+ // List of callback, mapping from displayId -> callback.
+ private final SparseArray<WindowsForAccessibilityCallback> mCallbackOfWindows =
+ new SparseArray<>();
+
private final MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
@Mock private WindowManagerInternal mMockWindowManagerInternal;
@@ -109,29 +120,14 @@
mMockA11ySecurityPolicy,
mMockA11yUserManager);
- // Add RemoteAccessibilityConnection into AccessibilityWindowManager, and copy
- // mock window token into mA11yWindowTokens. Also, preparing WindowInfo mWindowInfos
- // for the test.
- int layer = 0;
- for (int i = 0; i < NUM_GLOBAL_WINDOWS; i++) {
- final IWindow token = addAccessibilityInteractionConnection(true);
- addWindowInfo(token, layer++);
-
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ when(mMockWindowManagerInternal.setWindowsForAccessibilityCallback(eq(i), any()))
+ .thenReturn(true);
+ startTrackingPerDisplay(i);
}
- for (int i = 0; i < NUM_APP_WINDOWS; i++) {
- final IWindow token = addAccessibilityInteractionConnection(false);
- addWindowInfo(token, layer++);
- }
- // setup default focus
- mWindowInfos.get(DEFAULT_FOCUSED_INDEX).focused = true;
- // Turn on windows tracking, and update window info
- mA11yWindowManager.startTrackingWindows();
- mA11yWindowManager.onWindowsForAccessibilityChanged(FORCE_SEND, mWindowInfos);
- assertEquals(mA11yWindowManager.getWindowListLocked().size(),
- mWindowInfos.size());
// AccessibilityEventSender is invoked during onWindowsForAccessibilityChanged.
- // Reset it for mockito verify of further test case.
+ // Resets it for mockito verify of further test case.
Mockito.reset(mMockA11yEventSender);
}
@@ -142,11 +138,12 @@
@Test
public void startTrackingWindows_shouldEnableWindowManagerCallback() {
- // AccessibilityWindowManager#startTrackingWindows already invoked in setup
+ // AccessibilityWindowManager#startTrackingWindows already invoked in setup.
assertTrue(mA11yWindowManager.isTrackingWindowsLocked());
- // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
+ final WindowsForAccessibilityCallback callbacks =
+ mCallbackOfWindows.get(Display.DEFAULT_DISPLAY);
verify(mMockWindowManagerInternal).setWindowsForAccessibilityCallback(
- eq(Display.DEFAULT_DISPLAY), any());
+ eq(Display.DEFAULT_DISPLAY), eq(callbacks));
}
@Test
@@ -156,9 +153,9 @@
mA11yWindowManager.stopTrackingWindows();
assertFalse(mA11yWindowManager.isTrackingWindowsLocked());
- // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
verify(mMockWindowManagerInternal).setWindowsForAccessibilityCallback(
- eq(Display.DEFAULT_DISPLAY), any());
+ eq(Display.DEFAULT_DISPLAY), isNull());
+
}
@Test
@@ -177,87 +174,102 @@
@Test
public void onWindowsChanged_duringTouchInteractAndFocusChange_shouldChangeActiveWindow() {
final int activeWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID);
- WindowInfo focusedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX);
+ WindowInfo focusedWindowInfo =
+ mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX);
assertEquals(activeWindowId, mA11yWindowManager.findWindowIdLocked(
USER_SYSTEM_ID, focusedWindowInfo.token));
focusedWindowInfo.focused = false;
- focusedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX + 1);
+ focusedWindowInfo =
+ mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX + 1);
focusedWindowInfo.focused = true;
mA11yWindowManager.onTouchInteractionStart();
- mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
+ setTopFocusedWindowAndDisplay(Display.DEFAULT_DISPLAY, DEFAULT_FOCUSED_INDEX + 1);
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
+
assertNotEquals(activeWindowId, mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID));
}
@Test
public void onWindowsChanged_shouldReportCorrectLayer() {
- // AccessibilityWindowManager#onWindowsForAccessibilityChanged already invoked in setup
- List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
+ // AccessibilityWindowManager#onWindowsForAccessibilityChanged already invoked in setup.
+ List<AccessibilityWindowInfo> a11yWindows =
+ mA11yWindowManager.getWindowListLocked();
for (int i = 0; i < a11yWindows.size(); i++) {
final AccessibilityWindowInfo a11yWindow = a11yWindows.get(i);
- final WindowInfo windowInfo = mWindowInfos.get(i);
- assertThat(mWindowInfos.size() - windowInfo.layer - 1,
+ final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(i);
+ assertThat(mWindowInfos.get(Display.DEFAULT_DISPLAY).size() - windowInfo.layer - 1,
is(a11yWindow.getLayer()));
}
}
@Test
public void onWindowsChanged_shouldReportCorrectOrder() {
- // AccessibilityWindowManager#onWindowsForAccessibilityChanged already invoked in setup
- List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
+ // AccessibilityWindowManager#onWindowsForAccessibilityChanged already invoked in setup.
+ List<AccessibilityWindowInfo> a11yWindows =
+ mA11yWindowManager.getWindowListLocked();
for (int i = 0; i < a11yWindows.size(); i++) {
final AccessibilityWindowInfo a11yWindow = a11yWindows.get(i);
final IBinder windowToken = mA11yWindowManager
.getWindowTokenForUserAndWindowIdLocked(USER_SYSTEM_ID, a11yWindow.getId());
- final WindowInfo windowInfo = mWindowInfos.get(i);
+ final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(i);
assertThat(windowToken, is(windowInfo.token));
}
}
@Test
public void onWindowsChangedAndForceSend_shouldUpdateWindows() {
- final WindowInfo windowInfo = mWindowInfos.get(0);
- final int correctLayer = mA11yWindowManager.getWindowListLocked().get(0).getLayer();
+ final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0);
+ final int correctLayer =
+ mA11yWindowManager.getWindowListLocked().get(0).getLayer();
windowInfo.layer += 1;
- mA11yWindowManager.onWindowsForAccessibilityChanged(FORCE_SEND, mWindowInfos);
- assertNotEquals(correctLayer, mA11yWindowManager.getWindowListLocked().get(0).getLayer());
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, FORCE_SEND);
+ assertNotEquals(correctLayer,
+ mA11yWindowManager.getWindowListLocked().get(0).getLayer());
}
@Test
public void onWindowsChangedNoForceSend_layerChanged_shouldNotUpdateWindows() {
- final WindowInfo windowInfo = mWindowInfos.get(0);
- final int correctLayer = mA11yWindowManager.getWindowListLocked().get(0).getLayer();
+ final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0);
+ final int correctLayer =
+ mA11yWindowManager.getWindowListLocked().get(0).getLayer();
windowInfo.layer += 1;
- mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
- assertEquals(correctLayer, mA11yWindowManager.getWindowListLocked().get(0).getLayer());
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
+ assertEquals(correctLayer,
+ mA11yWindowManager.getWindowListLocked().get(0).getLayer());
}
@Test
public void onWindowsChangedNoForceSend_windowChanged_shouldUpdateWindows()
throws RemoteException {
- final AccessibilityWindowInfo oldWindow = mA11yWindowManager.getWindowListLocked().get(0);
- final IWindow token = addAccessibilityInteractionConnection(true);
+ final AccessibilityWindowInfo oldWindow =
+ mA11yWindowManager.getWindowListLocked().get(0);
+ final IWindow token =
+ addAccessibilityInteractionConnection(Display.DEFAULT_DISPLAY, true);
final WindowInfo windowInfo = WindowInfo.obtain();
windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION;
windowInfo.token = token.asBinder();
windowInfo.layer = 0;
windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
- mWindowInfos.set(0, windowInfo);
+ mWindowInfos.get(Display.DEFAULT_DISPLAY).set(0, windowInfo);
- mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
- assertNotEquals(oldWindow, mA11yWindowManager.getWindowListLocked().get(0));
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
+ assertNotEquals(oldWindow,
+ mA11yWindowManager.getWindowListLocked().get(0));
}
@Test
public void onWindowsChangedNoForceSend_focusChanged_shouldUpdateWindows() {
- final WindowInfo focusedWindowInfo = mWindowInfos.get(DEFAULT_FOCUSED_INDEX);
- final WindowInfo windowInfo = mWindowInfos.get(0);
+ final WindowInfo focusedWindowInfo =
+ mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX);
+ final WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0);
focusedWindowInfo.focused = false;
windowInfo.focused = true;
- mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
+
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
assertTrue(mA11yWindowManager.getWindowListLocked().get(0).isFocused());
}
@@ -288,7 +300,8 @@
@Test
public void getWindowTokenForUserAndWindowId_shouldNotNull() {
- final List<AccessibilityWindowInfo> windows = mA11yWindowManager.getWindowListLocked();
+ final List<AccessibilityWindowInfo> windows =
+ mA11yWindowManager.getWindowListLocked();
for (int i = 0; i < windows.size(); i++) {
final int windowId = windows.get(i).getId();
@@ -299,7 +312,8 @@
@Test
public void findWindowId() {
- final List<AccessibilityWindowInfo> windows = mA11yWindowManager.getWindowListLocked();
+ final List<AccessibilityWindowInfo> windows =
+ mA11yWindowManager.getWindowListLocked();
for (int i = 0; i < windows.size(); i++) {
final int windowId = windows.get(i).getId();
final IBinder windowToken = mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(
@@ -313,13 +327,15 @@
@Test
public void computePartialInteractiveRegionForWindow_wholeVisible_returnWholeRegion() {
// Updates top 2 z-order WindowInfo are whole visible.
- WindowInfo windowInfo = mWindowInfos.get(0);
+ WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0);
windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
- windowInfo = mWindowInfos.get(1);
- windowInfo.regionInScreen.set(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT);
- mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
+ windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(1);
+ windowInfo.regionInScreen.set(0, SCREEN_HEIGHT / 2,
+ SCREEN_WIDTH, SCREEN_HEIGHT);
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
- final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
+ final List<AccessibilityWindowInfo> a11yWindows =
+ mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(0).getId();
@@ -336,12 +352,13 @@
@Test
public void computePartialInteractiveRegionForWindow_halfVisible_returnHalfRegion() {
- // Updates z-order #1 WindowInfo is half visible
- WindowInfo windowInfo = mWindowInfos.get(0);
+ // Updates z-order #1 WindowInfo is half visible.
+ WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0);
windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
- mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
- final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
+ final List<AccessibilityWindowInfo> a11yWindows =
+ mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
@@ -353,7 +370,8 @@
@Test
public void computePartialInteractiveRegionForWindow_notVisible_returnEmptyRegion() {
// Since z-order #0 WindowInfo is full screen, z-order #1 WindowInfo should be invisible.
- final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
+ final List<AccessibilityWindowInfo> a11yWindows =
+ mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
@@ -366,11 +384,12 @@
// Updates z-order #0 WindowInfo to have two interact-able areas.
Region region = new Region(0, 0, SCREEN_WIDTH, 200);
region.op(0, SCREEN_HEIGHT - 200, SCREEN_WIDTH, SCREEN_HEIGHT, Region.Op.UNION);
- WindowInfo windowInfo = mWindowInfos.get(0);
+ WindowInfo windowInfo = mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0);
windowInfo.regionInScreen.set(region);
- mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
- final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
+ final List<AccessibilityWindowInfo> a11yWindows =
+ mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
@@ -382,7 +401,8 @@
@Test
public void updateActiveAndA11yFocusedWindow_windowStateChangedEvent_noTracking_shouldUpdate() {
- final IBinder eventWindowToken = mWindowInfos.get(DEFAULT_FOCUSED_INDEX + 1).token;
+ final IBinder eventWindowToken =
+ mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX + 1).token;
final int eventWindowId = mA11yWindowManager.findWindowIdLocked(
USER_SYSTEM_ID, eventWindowToken);
when(mMockWindowManagerInternal.getFocusedWindowToken())
@@ -402,7 +422,8 @@
@Test
public void updateActiveAndA11yFocusedWindow_hoverEvent_touchInteract_shouldSetActiveWindow() {
- final int eventWindowId = getWindowIdFromWindowInfos(DEFAULT_FOCUSED_INDEX + 1);
+ final int eventWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY,
+ DEFAULT_FOCUSED_INDEX + 1);
final int currentActiveWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID);
assertThat(currentActiveWindowId, is(not(eventWindowId)));
@@ -428,7 +449,8 @@
@Test
public void updateActiveAndA11yFocusedWindow_a11yFocusEvent_shouldUpdateA11yFocus() {
- final int eventWindowId = getWindowIdFromWindowInfos(DEFAULT_FOCUSED_INDEX);
+ final int eventWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY,
+ DEFAULT_FOCUSED_INDEX);
final int currentA11yFocusedWindowId = mA11yWindowManager.getFocusedWindowId(
AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
assertThat(currentA11yFocusedWindowId, is(not(eventWindowId)));
@@ -457,7 +479,8 @@
@Test
public void updateActiveAndA11yFocusedWindow_clearA11yFocusEvent_shouldClearA11yFocus() {
- final int eventWindowId = getWindowIdFromWindowInfos(DEFAULT_FOCUSED_INDEX);
+ final int eventWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY,
+ DEFAULT_FOCUSED_INDEX);
final int currentA11yFocusedWindowId = mA11yWindowManager.getFocusedWindowId(
AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
assertThat(currentA11yFocusedWindowId, is(not(eventWindowId)));
@@ -482,7 +505,8 @@
@Test
public void onTouchInteractionEnd_shouldRollbackActiveWindow() {
- final int eventWindowId = getWindowIdFromWindowInfos(DEFAULT_FOCUSED_INDEX + 1);
+ final int eventWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY,
+ DEFAULT_FOCUSED_INDEX + 1);
final int currentActiveWindowId = mA11yWindowManager.getActiveWindowId(USER_SYSTEM_ID);
assertThat(currentActiveWindowId, is(not(eventWindowId)));
@@ -513,12 +537,14 @@
@Test
public void onTouchInteractionEnd_noServiceInteractiveWindow_shouldClearA11yFocus()
throws RemoteException {
- final IBinder defaultFocusWinToken = mWindowInfos.get(DEFAULT_FOCUSED_INDEX).token;
+ final IBinder defaultFocusWinToken =
+ mWindowInfos.get(Display.DEFAULT_DISPLAY).get(DEFAULT_FOCUSED_INDEX).token;
final int defaultFocusWindowId = mA11yWindowManager.findWindowIdLocked(
USER_SYSTEM_ID, defaultFocusWinToken);
when(mMockWindowManagerInternal.getFocusedWindowToken())
.thenReturn(defaultFocusWinToken);
- final int newFocusWindowId = getWindowIdFromWindowInfos(DEFAULT_FOCUSED_INDEX + 1);
+ final int newFocusWindowId = getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY,
+ DEFAULT_FOCUSED_INDEX + 1);
final IAccessibilityInteractionConnection mockNewFocusConnection =
mA11yWindowManager.getConnectionLocked(
USER_SYSTEM_ID, newFocusWindowId).getRemote();
@@ -556,28 +582,72 @@
@Test
public void getPictureInPictureWindow_shouldNotNull() {
- assertNull(mA11yWindowManager.getPictureInPictureWindow());
- mWindowInfos.get(1).inPictureInPicture = true;
- mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
+ assertNull(mA11yWindowManager.getPictureInPictureWindowLocked());
+ mWindowInfos.get(Display.DEFAULT_DISPLAY).get(1).inPictureInPicture = true;
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
- assertNotNull(mA11yWindowManager.getPictureInPictureWindow());
+ assertNotNull(mA11yWindowManager.getPictureInPictureWindowLocked());
}
@Test
public void notifyOutsideTouch() throws RemoteException {
- final int targetWindowId = getWindowIdFromWindowInfos(1);
- final int outsideWindowId = getWindowIdFromWindowInfos(0);
+ final int targetWindowId =
+ getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 1);
+ final int outsideWindowId =
+ getWindowIdFromWindowInfosForDisplay(Display.DEFAULT_DISPLAY, 0);
final IAccessibilityInteractionConnection mockRemoteConnection =
mA11yWindowManager.getConnectionLocked(
USER_SYSTEM_ID, outsideWindowId).getRemote();
- mWindowInfos.get(0).hasFlagWatchOutsideTouch = true;
- mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
+ mWindowInfos.get(Display.DEFAULT_DISPLAY).get(0).hasFlagWatchOutsideTouch = true;
+ onWindowsForAccessibilityChanged(Display.DEFAULT_DISPLAY, SEND_ON_WINDOW_CHANGES);
mA11yWindowManager.notifyOutsideTouch(USER_SYSTEM_ID, targetWindowId);
verify(mockRemoteConnection).notifyOutsideTouch();
}
- private IWindow addAccessibilityInteractionConnection(boolean bGlobal)
+ private void startTrackingPerDisplay(int displayId) throws RemoteException {
+ ArrayList<WindowInfo> windowInfosForDisplay = new ArrayList<>();
+ // Adds RemoteAccessibilityConnection into AccessibilityWindowManager, and copy
+ // mock window token into mA11yWindowTokens. Also, preparing WindowInfo mWindowInfos
+ // for the test.
+ int layer = 0;
+ for (int i = 0; i < NUM_GLOBAL_WINDOWS; i++) {
+ final IWindow token = addAccessibilityInteractionConnection(displayId, true);
+ addWindowInfo(windowInfosForDisplay, token, layer++);
+
+ }
+ for (int i = 0; i < NUM_APP_WINDOWS; i++) {
+ final IWindow token = addAccessibilityInteractionConnection(displayId, false);
+ addWindowInfo(windowInfosForDisplay, token, layer++);
+ }
+ // Setups default focus.
+ windowInfosForDisplay.get(DEFAULT_FOCUSED_INDEX).focused = true;
+ // Turns on windows tracking, and update window info.
+ mA11yWindowManager.startTrackingWindows();
+ // Puts window lists into array.
+ mWindowInfos.put(displayId, windowInfosForDisplay);
+ // Sets the default display as the top focused display.
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ setTopFocusedWindowAndDisplay(displayId, DEFAULT_FOCUSED_INDEX);
+ }
+ // Invokes callback for sending window lists to A11y framework.
+ onWindowsForAccessibilityChanged(displayId, FORCE_SEND);
+
+ assertEquals(mA11yWindowManager.getWindowListLocked().size(),
+ windowInfosForDisplay.size());
+ }
+
+ private WindowsForAccessibilityCallback getWindowsForAccessibilityCallbacks(int displayId) {
+ ArgumentCaptor<WindowsForAccessibilityCallback> windowsForAccessibilityCallbacksCaptor =
+ ArgumentCaptor.forClass(
+ WindowManagerInternal.WindowsForAccessibilityCallback.class);
+ verify(mMockWindowManagerInternal)
+ .setWindowsForAccessibilityCallback(eq(displayId),
+ windowsForAccessibilityCallbacksCaptor.capture());
+ return windowsForAccessibilityCallbacksCaptor.getValue();
+ }
+
+ private IWindow addAccessibilityInteractionConnection(int displayId, boolean bGlobal)
throws RemoteException {
final IWindow mockWindowToken = Mockito.mock(IWindow.class);
final IAccessibilityInteractionConnection mockA11yConnection = Mockito.mock(
@@ -588,6 +658,8 @@
when(mockWindowToken.asBinder()).thenReturn(mockWindowBinder);
when(mMockA11ySecurityPolicy.isCallerInteractingAcrossUsers(USER_SYSTEM_ID))
.thenReturn(bGlobal);
+ when(mMockWindowManagerInternal.getDisplayIdForWindow(mockWindowToken.asBinder()))
+ .thenReturn(displayId);
int windowId = mA11yWindowManager.addAccessibilityInteractionConnection(
mockWindowToken, mockA11yConnection, PACKAGE_NAME, USER_SYSTEM_ID);
@@ -595,21 +667,40 @@
return mockWindowToken;
}
- private void addWindowInfo(IWindow windowToken, int layer) {
+ private void addWindowInfo(ArrayList<WindowInfo> windowInfos, IWindow windowToken, int layer) {
final WindowInfo windowInfo = WindowInfo.obtain();
windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION;
windowInfo.token = windowToken.asBinder();
windowInfo.layer = layer;
windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
- mWindowInfos.add(windowInfo);
+ windowInfos.add(windowInfo);
}
- private int getWindowIdFromWindowInfos(int index) {
- final IBinder windowToken = mWindowInfos.get(index).token;
+ private int getWindowIdFromWindowInfosForDisplay(int displayId, int index) {
+ final IBinder windowToken = mWindowInfos.get(displayId).get(index).token;
return mA11yWindowManager.findWindowIdLocked(
USER_SYSTEM_ID, windowToken);
}
+ private void setTopFocusedWindowAndDisplay(int displayId, int index) {
+ // Sets the top focus window.
+ final IBinder eventWindowToken = mWindowInfos.get(displayId).get(index).token;
+ when(mMockWindowManagerInternal.getFocusedWindowToken())
+ .thenReturn(eventWindowToken);
+ // Sets the top focused display.
+ when(mMockWindowManagerInternal.getDisplayIdForWindow(eventWindowToken))
+ .thenReturn(displayId);
+ }
+
+ private void onWindowsForAccessibilityChanged(int displayId, boolean forceSend) {
+ WindowsForAccessibilityCallback callbacks = mCallbackOfWindows.get(displayId);
+ if (callbacks == null) {
+ callbacks = getWindowsForAccessibilityCallbacks(displayId);
+ mCallbackOfWindows.put(displayId, callbacks);
+ }
+ callbacks.onWindowsForAccessibilityChanged(forceSend, mWindowInfos.get(displayId));
+ }
+
static class WindowIdMatcher extends TypeSafeMatcher<AccessibilityEvent> {
private int mWindowId;
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 0309dbe..cae7b57 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -273,7 +273,7 @@
invalidLateRuntimeElapsedMillis - TWO_HOURS; // Early is (late - period).
final Pair<Long, Long> persistedExecutionTimesUTC = new Pair<>(rtcNow, rtcNow + ONE_HOUR);
final JobStatus js = new JobStatus(b.build(), SOME_UID, "somePackage",
- 0 /* sourceUserId */, 0, 0, "someTag",
+ 0 /* sourceUserId */, 0, "someTag",
invalidEarlyRuntimeElapsedMillis, invalidLateRuntimeElapsedMillis,
0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */,
persistedExecutionTimesUTC, 0 /* innerFlagg */);
diff --git a/startop/scripts/app_startup/app_startup_runner.py b/startop/scripts/app_startup/app_startup_runner.py
index 7b3bf33..eb582f9 100755
--- a/startop/scripts/app_startup/app_startup_runner.py
+++ b/startop/scripts/app_startup/app_startup_runner.py
@@ -32,21 +32,25 @@
import os
import sys
import tempfile
+from datetime import timedelta
from typing import Any, Callable, Iterable, List, NamedTuple, TextIO, Tuple, \
TypeVar, Union, Optional
# local import
DIR = os.path.abspath(os.path.dirname(__file__))
sys.path.append(os.path.dirname(DIR))
+import lib.cmd_utils as cmd_utils
+import lib.print_utils as print_utils
+import iorap.compiler as compiler
from app_startup.run_app_with_prefetch import PrefetchAppRunner
import app_startup.lib.args_utils as args_utils
from app_startup.lib.data_frame import DataFrame
-import lib.cmd_utils as cmd_utils
-import lib.print_utils as print_utils
+from app_startup.lib.perfetto_trace_collector import PerfettoTraceCollector
# The following command line options participate in the combinatorial generation.
# All other arguments have a global effect.
-_COMBINATORIAL_OPTIONS = ['package', 'readahead', 'compiler_filter', 'activity']
+_COMBINATORIAL_OPTIONS = ['package', 'readahead', 'compiler_filter',
+ 'activity', 'trace_duration']
_TRACING_READAHEADS = ['mlock', 'fadvise']
_FORWARD_OPTIONS = {'loop_count': '--count'}
_RUN_SCRIPT = os.path.join(os.path.dirname(os.path.realpath(__file__)),
@@ -54,9 +58,8 @@
CollectorPackageInfo = NamedTuple('CollectorPackageInfo',
[('package', str), ('compiler_filter', str)])
-_COLLECTOR_SCRIPT = os.path.join(os.path.dirname(os.path.realpath(__file__)),
- '../iorap/collector')
-_COLLECTOR_TIMEOUT_MULTIPLIER = 10 # take the regular --timeout and multiply
+_COMPILER_SCRIPT = os.path.join(os.path.dirname(os.path.dirname(
+ os.path.realpath(__file__))), 'iorap/compiler.py')
# by 2; systrace starts up slowly.
_UNLOCK_SCREEN_SCRIPT = os.path.join(
@@ -70,11 +73,14 @@
('timeout', Optional[int]),
('debug', bool),
('simulate', bool),
- ('input', Optional[str])])
+ ('input', Optional[str]),
+ ('trace_duration', Optional[timedelta])])
# This must be the only mutable global variable. All other global variables are constants to avoid magic literals.
_debug = False # See -d/--debug flag.
_DEBUG_FORCE = None # Ignore -d/--debug if this is not none.
+_PERFETTO_TRACE_DURATION_MS = 5000 # milliseconds
+_PERFETTO_TRACE_DURATION = timedelta(milliseconds=_PERFETTO_TRACE_DURATION_MS)
# Type hinting names.
T = TypeVar('T')
@@ -123,26 +129,15 @@
optional_named.add_argument('-in', '--inodes', dest='inodes', type=str,
action='store',
help='Path to inodes file (system/extras/pagecache/pagecache.py -d inodes)')
+ optional_named.add_argument('--compiler-trace-duration-ms',
+ dest='trace_duration',
+ type=lambda ms_str: timedelta(milliseconds=int(ms_str)),
+ action='append',
+ help='The trace duration (milliseconds) in '
+ 'compilation')
return parser.parse_args(argv)
-def make_script_command_with_temp_output(script: str,
- args: List[str],
- **kwargs) -> Tuple[str, TextIO]:
- """
- Create a command to run a script given the args.
- Appends --count <loop_count> --output <tmp-file-name>.
- Returns a tuple (cmd, tmp_file)
- """
- tmp_output_file = tempfile.NamedTemporaryFile(mode='r')
- cmd = [script] + args
- for key, value in kwargs.items():
- cmd += ['--%s' % (key), "%s" % (value)]
- if _debug:
- cmd += ['--verbose']
- cmd = cmd + ["--output", tmp_output_file.name]
- return cmd, tmp_output_file
-
def key_to_cmdline_flag(key: str) -> str:
"""Convert key into a command line flag, e.g. 'foo-bars' -> '--foo-bar' """
if key.endswith("s"):
@@ -163,26 +158,26 @@
args.append(value)
return args
-def run_collector_script(collector_info: CollectorPackageInfo,
- inodes_path: str,
- timeout: int,
- simulate: bool) -> Tuple[bool, TextIO]:
- """Run collector to collect prefetching trace. """
- # collector_args = ["--package", package_name]
- collector_args = as_run_command(collector_info)
- # TODO: forward --wait_time for how long systrace runs?
- # TODO: forward --trace_buffer_size for size of systrace buffer size?
- collector_cmd, collector_tmp_output_file = make_script_command_with_temp_output(
- _COLLECTOR_SCRIPT, collector_args, inodes=inodes_path)
+def run_perfetto_collector(collector_info: CollectorPackageInfo,
+ timeout: int,
+ simulate: bool) -> Tuple[bool, TextIO]:
+ """Run collector to collect prefetching trace.
- collector_timeout = timeout and _COLLECTOR_TIMEOUT_MULTIPLIER * timeout
- (collector_passed, collector_script_output) = \
- cmd_utils.execute_arbitrary_command(collector_cmd,
- collector_timeout,
- shell=False,
- simulate=simulate)
+ Returns:
+ A tuple of whether the collection succeeds and the generated trace file.
+ """
+ tmp_output_file = tempfile.NamedTemporaryFile()
- return collector_passed, collector_tmp_output_file
+ collector = PerfettoTraceCollector(package=collector_info.package,
+ activity=None,
+ compiler_filter=collector_info.compiler_filter,
+ timeout=timeout,
+ simulate=simulate,
+ trace_duration=_PERFETTO_TRACE_DURATION,
+ save_destination_file_path=tmp_output_file.name)
+ result = collector.run()
+
+ return result is not None, tmp_output_file
def parse_run_script_csv_file(csv_file: TextIO) -> DataFrame:
"""Parse a CSV file full of integers into a DataFrame."""
@@ -216,6 +211,52 @@
return DataFrame(d)
+def compile_perfetto_trace(inodes_path: str,
+ perfetto_trace_file: str,
+ trace_duration: Optional[timedelta]) -> TextIO:
+ compiler_trace_file = tempfile.NamedTemporaryFile()
+ argv = [_COMPILER_SCRIPT, '-i', inodes_path, '--perfetto-trace',
+ perfetto_trace_file, '-o', compiler_trace_file.name]
+
+ if trace_duration is not None:
+ argv += ['--duration', str(int(trace_duration.total_seconds()
+ * PerfettoTraceCollector.MS_PER_SEC))]
+
+ print_utils.debug_print(argv)
+ compiler.main(argv)
+ return compiler_trace_file
+
+def execute_run_using_perfetto_trace(collector_info,
+ run_combos: Iterable[RunCommandArgs],
+ simulate: bool,
+ inodes_path: str,
+ timeout: int) -> DataFrame:
+ """ Executes run based on perfetto trace. """
+ passed, perfetto_trace_file = run_perfetto_collector(collector_info,
+ timeout,
+ simulate)
+ if not passed:
+ raise RuntimeError('Cannot run perfetto collector!')
+
+ with perfetto_trace_file:
+ for combos in run_combos:
+ if combos.readahead in _TRACING_READAHEADS:
+ if simulate:
+ compiler_trace_file = tempfile.NamedTemporaryFile()
+ else:
+ compiler_trace_file = compile_perfetto_trace(inodes_path,
+ perfetto_trace_file.name,
+ combos.trace_duration)
+ with compiler_trace_file:
+ combos = combos._replace(input=compiler_trace_file.name)
+ print_utils.debug_print(combos)
+ output = PrefetchAppRunner(**combos._asdict()).run()
+ else:
+ print_utils.debug_print(combos)
+ output = PrefetchAppRunner(**combos._asdict()).run()
+
+ yield DataFrame(dict((x, [y]) for x, y in output)) if output else None
+
def execute_run_combos(
grouped_run_combos: Iterable[Tuple[CollectorPackageInfo, Iterable[RunCommandArgs]]],
simulate: bool,
@@ -228,19 +269,11 @@
shell=False)
for collector_info, run_combos in grouped_run_combos:
- for combos in run_combos:
- args = as_run_command(combos)
- if combos.readahead in _TRACING_READAHEADS:
- passed, collector_tmp_output_file = run_collector_script(collector_info,
- inodes_path,
- timeout,
- simulate)
- combos = combos._replace(input=collector_tmp_output_file.name)
-
- print_utils.debug_print(combos)
- output = PrefetchAppRunner(**combos._asdict()).run()
-
- yield DataFrame(dict((x, [y]) for x, y in output)) if output else None
+ yield from execute_run_using_perfetto_trace(collector_info,
+ run_combos,
+ simulate,
+ inodes_path,
+ timeout)
def gather_results(commands: Iterable[Tuple[DataFrame]],
key_list: List[str], value_list: List[Tuple[str, ...]]):
diff --git a/startop/scripts/app_startup/app_startup_runner_test.py b/startop/scripts/app_startup/app_startup_runner_test.py
index 9aa7014..42ea5f0 100755
--- a/startop/scripts/app_startup/app_startup_runner_test.py
+++ b/startop/scripts/app_startup/app_startup_runner_test.py
@@ -91,7 +91,8 @@
# Combine it with all of the "optional" parameters' default values.
"""
d = {'compiler_filters': None, 'simulate': False, 'debug': False,
- 'output': None, 'timeout': 10, 'loop_count': 1, 'inodes': None}
+ 'output': None, 'timeout': 10, 'loop_count': 1, 'inodes': None,
+ 'trace_duration': None}
d.update(kwargs)
return d
@@ -159,19 +160,6 @@
assert asr.key_to_cmdline_flag("ba_r") == "--ba-r"
assert asr.key_to_cmdline_flag("ba_zs") == "--ba-z"
-def test_make_script_command_with_temp_output():
- cmd_str, tmp_file = asr.make_script_command_with_temp_output("fake_script",
- args=[], count=1)
- with tmp_file:
- assert cmd_str == ["fake_script", "--count", "1", "--output", tmp_file.name]
-
- cmd_str, tmp_file = asr.make_script_command_with_temp_output("fake_script",
- args=['a', 'b'],
- count=2)
- with tmp_file:
- assert cmd_str == ["fake_script", "a", "b", "--count", "2", "--output",
- tmp_file.name]
-
def test_parse_run_script_csv_file():
# empty file -> empty list
f = io.StringIO("")
diff --git a/startop/scripts/app_startup/lib/app_runner.py b/startop/scripts/app_startup/lib/app_runner.py
index a8afd6a..78873fa 100644
--- a/startop/scripts/app_startup/lib/app_runner.py
+++ b/startop/scripts/app_startup/lib/app_runner.py
@@ -51,6 +51,7 @@
returns:
a string in the format of "<metric>=<value>\n<metric>=<value>\n..."
for further parsing. For example "TotalTime=123\nDisplayedTime=121".
+ Return an empty string if no metrics need to be parsed further.
"""
pass
@@ -61,7 +62,7 @@
APP_STARTUP_DIR = os.path.dirname(DIR)
IORAP_COMMON_BASH_SCRIPT = os.path.realpath(os.path.join(DIR,
'../../iorap/common'))
- DEFAULT_TIMEOUT = 30
+ DEFAULT_TIMEOUT = 30 # seconds
def __init__(self,
package: str,
diff --git a/startop/scripts/app_startup/lib/perfetto_trace_collector.py b/startop/scripts/app_startup/lib/perfetto_trace_collector.py
index 20a6c52..9ffb349 100644
--- a/startop/scripts/app_startup/lib/perfetto_trace_collector.py
+++ b/startop/scripts/app_startup/lib/perfetto_trace_collector.py
@@ -14,11 +14,11 @@
"""Class to collector perfetto trace."""
import datetime
-from datetime import timedelta
import os
import re
import sys
import time
+from datetime import timedelta
from typing import Optional, List, Tuple
# global variables
@@ -40,7 +40,9 @@
"""
TRACE_FILE_SUFFIX = 'perfetto_trace.pb'
TRACE_DURATION_PROP = 'iorapd.perfetto.trace_duration_ms'
- SECONDS_TO_MILLISECONDS = 1000
+ MS_PER_SEC = 1000
+ DEFAULT_TRACE_DURATION = timedelta(milliseconds=5000) # 5 seconds
+ _COLLECTOR_TIMEOUT_MULTIPLIER = 10 # take the regular timeout and multiply
def __init__(self,
package: str,
@@ -48,7 +50,7 @@
compiler_filter: Optional[str],
timeout: Optional[int],
simulate: bool,
- trace_duration: timedelta = timedelta(milliseconds=5000),
+ trace_duration: timedelta = DEFAULT_TRACE_DURATION,
save_destination_file_path: Optional[str] = None):
""" Initialize the perfetto trace collector. """
self.app_runner = AppRunner(package,
@@ -89,7 +91,7 @@
# Set perfetto trace duration prop to milliseconds.
adb_utils.set_prop(PerfettoTraceCollector.TRACE_DURATION_PROP,
int(self.trace_duration.total_seconds()*
- PerfettoTraceCollector.SECONDS_TO_MILLISECONDS))
+ PerfettoTraceCollector.MS_PER_SEC))
if not iorapd_utils.stop_iorapd():
raise RuntimeError('Cannot stop iorapd!')
@@ -122,7 +124,7 @@
manner until all metrics have been found".
Returns:
- An empty string.
+ An empty string because the metric needs no further parsing.
"""
if not self._wait_for_perfetto_trace(pre_launch_timestamp):
raise RuntimeError('Could not save perfetto app trace file!')
@@ -143,14 +145,19 @@
format(self._get_remote_path()))
# The pre_launch_timestamp is longer than what the datetime can parse. Trim
- # last three digits to make them align.
+ # last three digits to make them align. For example:
+ # 2019-07-02 23:20:06.972674825999 -> 2019-07-02 23:20:06.972674825
+ assert len(pre_launch_timestamp) == len('2019-07-02 23:20:06.972674825')
timestamp = datetime.datetime.strptime(pre_launch_timestamp[:-3],
'%Y-%m-%d %H:%M:%S.%f')
- timeout_dt = timestamp + datetime.timedelta(0, self.app_runner.timeout)
+
+ # The timeout of perfetto trace is longer than the normal app run timeout.
+ timeout_dt = self.app_runner.timeout * PerfettoTraceCollector._COLLECTOR_TIMEOUT_MULTIPLIER
+ timeout_end = timestamp + datetime.timedelta(seconds=timeout_dt)
return logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
pattern,
- timeout_dt)
+ timeout_end)
def _get_remote_path(self):
# For example: android.music%2Fmusic.TopLevelActivity.perfetto_trace.pb
diff --git a/startop/scripts/iorap/compiler.py b/startop/scripts/iorap/compiler.py
index 9527e28..ef9b870 100755
--- a/startop/scripts/iorap/compiler.py
+++ b/startop/scripts/iorap/compiler.py
@@ -31,8 +31,10 @@
from pathlib import Path
from typing import Iterable, Optional, List
-from generated.TraceFile_pb2 import *
-from lib.inode2filename import Inode2Filename
+DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(os.path.dirname(DIR))
+from iorap.generated.TraceFile_pb2 import *
+from iorap.lib.inode2filename import Inode2Filename
parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(parent_dir_name)
diff --git a/startop/view_compiler/dex_layout_compiler.cc b/startop/view_compiler/dex_layout_compiler.cc
index c68793d..8febfb7 100644
--- a/startop/view_compiler/dex_layout_compiler.cc
+++ b/startop/view_compiler/dex_layout_compiler.cc
@@ -23,25 +23,6 @@
using android::base::StringPrintf;
-void LayoutValidationVisitor::VisitStartTag(const std::u16string& name) {
- if (0 == name.compare(u"merge")) {
- message_ = "Merge tags are not supported";
- can_compile_ = false;
- }
- if (0 == name.compare(u"include")) {
- message_ = "Include tags are not supported";
- can_compile_ = false;
- }
- if (0 == name.compare(u"view")) {
- message_ = "View tags are not supported";
- can_compile_ = false;
- }
- if (0 == name.compare(u"fragment")) {
- message_ = "Fragment tags are not supported";
- can_compile_ = false;
- }
-}
-
DexViewBuilder::DexViewBuilder(dex::MethodBuilder* method)
: method_{method},
context_{dex::Value::Parameter(0)},
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index cd79f37..ce21112 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2328,6 +2328,13 @@
public static final String KEY_RTT_DOWNGRADE_SUPPORTED_BOOL = "rtt_downgrade_supported_bool";
/**
+ * Indicates if the TTY HCO and VCO options should be hidden in the accessibility menu
+ * if the device is capable of RTT.
+ * @hide
+ */
+ public static final String KEY_HIDE_TTY_HCO_VCO_WITH_RTT_BOOL = "hide_tty_hco_vco_with_rtt";
+
+ /**
* The flag to disable the popup dialog which warns the user of data charges.
* @hide
*/
@@ -3406,6 +3413,7 @@
sDefaults.putBoolean(KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false);
sDefaults.putBoolean(KEY_RTT_SUPPORTED_BOOL, false);
sDefaults.putBoolean(KEY_TTY_SUPPORTED_BOOL, true);
+ sDefaults.putBoolean(KEY_HIDE_TTY_HCO_VCO_WITH_RTT_BOOL, false);
sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true);
sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index cdf4c93..aa7e21a 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -340,6 +340,19 @@
*/
public static final int MEDIA_TIMEOUT = 77;
+ /**
+ * Indicates that an emergency call cannot be placed over WFC because the service is not
+ * available in the current location.
+ * @hide
+ */
+ public static final int EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE = 78;
+
+ /**
+ * Indicates that WiFi calling service is not available in the current location.
+ * @hide
+ */
+ public static final int WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 79;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Update toString() with the newly added disconnect type.
@@ -510,6 +523,10 @@
return "OTASP_PROVISIONING_IN_PROCESS";
case MEDIA_TIMEOUT:
return "MEDIA_TIMEOUT";
+ case EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE:
+ return "EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE";
+ case WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION:
+ return "WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index a478606..20aba4d 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -871,6 +871,19 @@
*/
public static final int CODE_REJECT_ONGOING_CS_CALL = 1621;
+ /**
+ * An attempt was made to place an emergency call over WFC when emergency services is not
+ * currently available in the current location.
+ * @hide
+ */
+ public static final int CODE_EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE = 1622;
+
+ /**
+ * Indicates that WiFi calling service is not available in the current location.
+ * @hide
+ */
+ public static final int CODE_WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 1623;
+
/*
* OEM specific error codes. To be used by OEMs when they don't want to reveal error code which
* would be replaced by ERROR_UNSPECIFIED.
diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/java/com/android/internal/telephony/SmsApplication.java
index 98f52cb..6df5457 100644
--- a/telephony/java/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/java/com/android/internal/telephony/SmsApplication.java
@@ -158,7 +158,7 @@
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfoAsUser(mPackageName, 0,
- UserHandle.getUserId(mUid));
+ UserHandle.getUserHandleForUid(mUid));
} catch (NameNotFoundException e) {
return null;
}
@@ -300,7 +300,7 @@
Uri.fromParts(SCHEME_SMSTO, "", null));
List<ResolveInfo> respondServices = packageManager.queryIntentServicesAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ UserHandle.getUserHandleForUid(userId));
for (ResolveInfo resolveInfo : respondServices) {
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
if (serviceInfo == null) {
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 72a6c9d..67103bf 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -367,7 +367,7 @@
ApplicationInfo callingPackageInfo = null;
try {
callingPackageInfo = context.getPackageManager().getApplicationInfoAsUser(
- callingPackage, 0, UserHandle.getUserId(uid));
+ callingPackage, 0, UserHandle.getUserHandleForUid(uid));
if (callingPackageInfo != null) {
if (callingPackageInfo.isSystemApp()) {
isPreinstalled = true;