diff options
139 files changed, 3384 insertions, 5102 deletions
diff --git a/Android.bp b/Android.bp index eae0d73f449f..30b38d302a2d 100644 --- a/Android.bp +++ b/Android.bp @@ -72,7 +72,6 @@ filegroup { ":framework-keystore-sources", ":framework-identity-sources", ":framework-location-sources", - ":framework-lowpan-sources", ":framework-mca-effect-sources", ":framework-mca-filterfw-sources", ":framework-mca-filterpacks-sources", @@ -167,7 +166,6 @@ java_defaults { "identity/java", "keystore/java", "location/java", - "lowpan/java", "media/java", "media/mca/effect/java", "media/mca/filterfw/java", @@ -277,7 +275,6 @@ java_defaults { ":framework-keystore-sources", ":framework-identity-sources", ":framework-location-sources", - ":framework-lowpan-sources", ":framework-mca-effect-sources", ":framework-mca-filterfw-sources", ":framework-mca-filterpacks-sources", diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java index e69cbedb955e..2e41dfd2888c 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java @@ -46,6 +46,7 @@ import com.android.server.job.JobSchedulerService; import com.android.server.utils.AlarmQueue; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.function.Predicate; @@ -68,56 +69,60 @@ public final class FlexibilityController extends StateController { private static final int FLEXIBLE_CONSTRAINTS = JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS | SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS; - @VisibleForTesting - static final int NUM_JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS = + private static final int NUM_JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS = Integer.bitCount(JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS); static final int NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS = Integer.bitCount(SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS); - @VisibleForTesting static final int NUM_FLEXIBLE_CONSTRAINTS = Integer.bitCount(FLEXIBLE_CONSTRAINTS); private static final long NO_LIFECYCLE_END = Long.MAX_VALUE; + /** + * Keeps track of what flexible constraints are satisfied at the moment. + * Is updated by the other controllers. + */ + @VisibleForTesting + @GuardedBy("mLock") + int mSatisfiedFlexibleConstraints; + /** Hard cutoff to remove flexible constraints. */ - private static final long DEADLINE_PROXIMITY_LIMIT_MS = 15 * MINUTE_IN_MILLIS; + private long mDeadlineProximityLimitMs = + FcConfig.DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS; /** * The default deadline that all flexible constraints should be dropped by if a job lacks * a deadline. */ + private long mFallbackFlexibilityDeadlineMs = + FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS; + + @GuardedBy("mLock") @VisibleForTesting - static final long DEFAULT_FLEXIBILITY_DEADLINE = 72 * HOUR_IN_MILLIS; + boolean mFlexibilityEnabled = FcConfig.DEFAULT_FLEXIBILITY_ENABLED; + + private long mMinTimeBetweenFlexibilityAlarmsMs = + FcConfig.DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS; /** - * Keeps track of what flexible constraints are satisfied at the moment. - * Is updated by the other controllers. + * The percent of a job's lifecycle to drop number of required constraints. + * mPercentToDropConstraints[i] denotes that at x% of a Jobs lifecycle, + * the controller should have i+1 constraints dropped. */ - @VisibleForTesting - @GuardedBy("mLock") - int mSatisfiedFlexibleConstraints; - @GuardedBy("mLock") - private boolean mFlexibilityEnabled = FcConstants.DEFAULT_FLEXIBILITY_ENABLED; + private int[] mPercentToDropConstraints; @VisibleForTesting @GuardedBy("mLock") final FlexibilityTracker mFlexibilityTracker; - private final FcConstants mFcConstants; - @VisibleForTesting - final PrefetchController mPrefetchController; - @GuardedBy("mLock") - private final FlexibilityAlarmQueue mFlexibilityAlarmQueue; - private static final long MIN_TIME_BETWEEN_ALARMS_MS = MINUTE_IN_MILLIS; + final FlexibilityAlarmQueue mFlexibilityAlarmQueue; + @VisibleForTesting + final FcConfig mFcConfig; - /** - * The percent of a Jobs lifecycle to drop number of required constraints. - * PERCENT_TO_DROP_CONSTRAINTS[i] denotes that at x% of a Jobs lifecycle, - * the controller should have i+1 constraints dropped. - */ - private static final int[] PERCENT_TO_DROP_CONSTRAINTS = {50, 60, 70, 80}; + @VisibleForTesting + final PrefetchController mPrefetchController; /** * Stores the beginning of prefetch jobs lifecycle per app as a maximum of @@ -164,9 +169,11 @@ public final class FlexibilityController extends StateController { JobSchedulerService service, PrefetchController prefetchController) { super(service); mFlexibilityTracker = new FlexibilityTracker(NUM_FLEXIBLE_CONSTRAINTS); - mFcConstants = new FcConstants(); + mFcConfig = new FcConfig(); mFlexibilityAlarmQueue = new FlexibilityAlarmQueue( mContext, JobSchedulerBackgroundThread.get().getLooper()); + mPercentToDropConstraints = + mFcConfig.DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; mPrefetchController = prefetchController; if (mFlexibilityEnabled) { mPrefetchController.registerPrefetchChangedListener(mPrefetchChangedListener); @@ -317,8 +324,7 @@ public final class FlexibilityController extends StateController { return NO_LIFECYCLE_END; } return js.getLatestRunTimeElapsed() == JobStatus.NO_LATEST_RUNTIME - ? earliest + DEFAULT_FLEXIBILITY_DEADLINE - : js.getLatestRunTimeElapsed(); + ? earliest + mFallbackFlexibilityDeadlineMs : js.getLatestRunTimeElapsed(); } @VisibleForTesting @@ -327,7 +333,7 @@ public final class FlexibilityController extends StateController { final long earliest = getLifeCycleBeginningElapsedLocked(js); final long latest = getLifeCycleEndElapsedLocked(js, earliest); final long nowElapsed = sElapsedRealtimeClock.millis(); - if (latest == NO_LIFECYCLE_END || earliest > nowElapsed) { + if (latest == NO_LIFECYCLE_END || earliest >= nowElapsed) { return 0; } if (nowElapsed > latest || latest == earliest) { @@ -344,11 +350,19 @@ public final class FlexibilityController extends StateController { long getNextConstraintDropTimeElapsedLocked(JobStatus js) { final long earliest = getLifeCycleBeginningElapsedLocked(js); final long latest = getLifeCycleEndElapsedLocked(js, earliest); + return getNextConstraintDropTimeElapsedLocked(js, earliest, latest); + } + + /** The elapsed time that marks when the next constraint should be dropped. */ + @VisibleForTesting + @ElapsedRealtimeLong + @GuardedBy("mLock") + long getNextConstraintDropTimeElapsedLocked(JobStatus js, long earliest, long latest) { if (latest == NO_LIFECYCLE_END - || js.getNumDroppedFlexibleConstraints() == PERCENT_TO_DROP_CONSTRAINTS.length) { + || js.getNumDroppedFlexibleConstraints() == mPercentToDropConstraints.length) { return NO_LIFECYCLE_END; } - final int percent = PERCENT_TO_DROP_CONSTRAINTS[js.getNumDroppedFlexibleConstraints()]; + final int percent = mPercentToDropConstraints[js.getNumDroppedFlexibleConstraints()]; final long percentInTime = ((latest - earliest) * percent) / 100; return earliest + percentInTime; } @@ -390,8 +404,7 @@ public final class FlexibilityController extends StateController { @Override @GuardedBy("mLock") public void onConstantsUpdatedLocked() { - if (mFcConstants.mShouldReevaluateConstraints) { - // Update job bookkeeping out of band. + if (mFcConfig.mShouldReevaluateConstraints) { JobSchedulerBackgroundThread.getHandler().post(() -> { final ArraySet<JobStatus> changedJobs = new ArraySet<>(); synchronized (mLock) { @@ -401,6 +414,8 @@ public final class FlexibilityController extends StateController { .getJobsByNumRequiredConstraints(j); for (int i = 0; i < jobs.size(); i++) { JobStatus js = jobs.valueAt(i); + mFlexibilityTracker.resetJobNumDroppedConstraints(js); + mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js); if (js.setFlexibilityConstraintSatisfied( nowElapsed, isFlexibilitySatisfiedLocked(js))) { changedJobs.add(js); @@ -418,7 +433,13 @@ public final class FlexibilityController extends StateController { @Override @GuardedBy("mLock") public void prepareForUpdatedConstantsLocked() { - mFcConstants.mShouldReevaluateConstraints = false; + mFcConfig.mShouldReevaluateConstraints = false; + } + + @Override + @GuardedBy("mLock") + public void processConstantLocked(DeviceConfig.Properties properties, String key) { + mFcConfig.processConstantLocked(properties, key); } @VisibleForTesting @@ -461,8 +482,10 @@ public final class FlexibilityController extends StateController { public void resetJobNumDroppedConstraints(JobStatus js) { final int curPercent = getCurPercentOfLifecycleLocked(js); int toDrop = 0; - for (int i = 0; i < PERCENT_TO_DROP_CONSTRAINTS.length; i++) { - if (curPercent >= PERCENT_TO_DROP_CONSTRAINTS[i]) { + final int jsMaxFlexibleConstraints = NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS + + (js.getPreferUnmetered() ? 1 : 0); + for (int i = 0; i < jsMaxFlexibleConstraints; i++) { + if (curPercent >= mPercentToDropConstraints[i]) { toDrop++; } } @@ -480,6 +503,9 @@ public final class FlexibilityController extends StateController { * Jobs with 0 required flexible constraints are removed from the tracker. */ public boolean adjustJobsRequiredConstraints(JobStatus js, int n) { + if (n == 0) { + return false; + } remove(js); js.adjustNumRequiredFlexibleConstraints(n); final long nowElapsed = sElapsedRealtimeClock.millis(); @@ -499,7 +525,7 @@ public final class FlexibilityController extends StateController { public void dump(IndentingPrintWriter pw, Predicate<JobStatus> predicate) { for (int i = 0; i < mTrackedJobs.size(); i++) { ArraySet<JobStatus> jobs = mTrackedJobs.get(i); - for (int j = 0; j < mTrackedJobs.size(); j++) { + for (int j = 0; j < jobs.size(); j++) { final JobStatus js = jobs.valueAt(j); if (!predicate.test(js)) { continue; @@ -514,11 +540,12 @@ public final class FlexibilityController extends StateController { } } - private class FlexibilityAlarmQueue extends AlarmQueue<JobStatus> { + @VisibleForTesting + class FlexibilityAlarmQueue extends AlarmQueue<JobStatus> { private FlexibilityAlarmQueue(Context context, Looper looper) { super(context, looper, "*job.flexibility_check*", "Flexible Constraint Check", false, - MIN_TIME_BETWEEN_ALARMS_MS); + mMinTimeBetweenFlexibilityAlarmsMs); } @Override @@ -526,16 +553,24 @@ public final class FlexibilityController extends StateController { return js.getSourceUserId() == userId; } - protected void scheduleDropNumConstraintsAlarm(JobStatus js) { + public void scheduleDropNumConstraintsAlarm(JobStatus js) { long nextTimeElapsed; synchronized (mLock) { - nextTimeElapsed = getNextConstraintDropTimeElapsedLocked(js); + final long earliest = getLifeCycleBeginningElapsedLocked(js); + final long latest = getLifeCycleEndElapsedLocked(js, earliest); + nextTimeElapsed = getNextConstraintDropTimeElapsedLocked(js, earliest, latest); if (nextTimeElapsed == NO_LIFECYCLE_END) { // There is no known or estimated next time to drop a constraint. removeAlarmForKey(js); return; } - mFlexibilityAlarmQueue.addAlarm(js, nextTimeElapsed); + + if (latest - nextTimeElapsed < mDeadlineProximityLimitMs) { + mFlexibilityTracker.adjustJobsRequiredConstraints( + js, -js.getNumRequiredFlexibleConstraints()); + return; + } + addAlarm(js, nextTimeElapsed); } } @@ -546,13 +581,21 @@ public final class FlexibilityController extends StateController { for (int i = 0; i < expired.size(); i++) { JobStatus js = expired.valueAt(i); boolean wasFlexibilitySatisfied = js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE); - long time = getNextConstraintDropTimeElapsedLocked(js); - int toDecrease = - js.getLatestRunTimeElapsed() - time < DEADLINE_PROXIMITY_LIMIT_MS - ? -js.getNumRequiredFlexibleConstraints() : -1; - if (mFlexibilityTracker.adjustJobsRequiredConstraints(js, toDecrease) - && time != NO_LIFECYCLE_END) { - mFlexibilityAlarmQueue.addAlarm(js, time); + + final long earliest = getLifeCycleBeginningElapsedLocked(js); + final long latest = getLifeCycleEndElapsedLocked(js, earliest); + final long nowElapsed = sElapsedRealtimeClock.millis(); + + if (latest - nowElapsed < mDeadlineProximityLimitMs) { + mFlexibilityTracker.adjustJobsRequiredConstraints(js, + -js.getNumRequiredFlexibleConstraints()); + } else { + long nextTimeElapsed = + getNextConstraintDropTimeElapsedLocked(js, earliest, latest); + if (mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1) + && nextTimeElapsed != NO_LIFECYCLE_END) { + mFlexibilityAlarmQueue.addAlarm(js, nextTimeElapsed); + } } if (wasFlexibilitySatisfied != js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE)) { changedJobs.add(js); @@ -564,19 +607,46 @@ public final class FlexibilityController extends StateController { } @VisibleForTesting - class FcConstants { + class FcConfig { private boolean mShouldReevaluateConstraints = false; + /** Prefix to use with all constant keys in order to "sub-namespace" the keys. */ + private static final String FC_CONFIG_PREFIX = "fc_"; + + static final String KEY_FLEXIBILITY_ENABLED = FC_CONFIG_PREFIX + "enable_flexibility"; + static final String KEY_DEADLINE_PROXIMITY_LIMIT = + FC_CONFIG_PREFIX + "flexibility_deadline_proximity_limit_ms"; + static final String KEY_FALLBACK_FLEXIBILITY_DEADLINE = + FC_CONFIG_PREFIX + "fallback_flexibility_deadline_ms"; + static final String KEY_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS = + FC_CONFIG_PREFIX + "min_alarm_time_flexibility_ms"; + static final String KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS = + FC_CONFIG_PREFIX + "percents_to_drop_num_flexible_constraints"; + private static final boolean DEFAULT_FLEXIBILITY_ENABLED = false; + @VisibleForTesting + static final long DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS = 15 * MINUTE_IN_MILLIS; + @VisibleForTesting + static final long DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS = 72 * HOUR_IN_MILLIS; + private static final long DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS = MINUTE_IN_MILLIS; + @VisibleForTesting + final int[] DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS = {50, 60, 70, 80}; + /** + * If false the controller will not track new jobs + * and the flexibility constraint will always be satisfied. + */ public boolean FLEXIBILITY_ENABLED = DEFAULT_FLEXIBILITY_ENABLED; + /** How close to a jobs' deadline all flexible constraints will be dropped. */ + public long DEADLINE_PROXIMITY_LIMIT_MS = DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS; + /** For jobs that lack a deadline, the time that will be used to drop all constraints by. */ + public long FALLBACK_FLEXIBILITY_DEADLINE_MS = DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS; + public long MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS = + DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS; + /** The percentages of a jobs' lifecycle to drop the number of required constraints. */ + public int[] PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS = + DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; - /** Prefix to use with all constant keys in order to "sub-namespace" the keys. */ - private static final String FC_CONSTANT_PREFIX = "fc_"; - - static final String KEY_FLEXIBILITY_ENABLED = FC_CONSTANT_PREFIX + "enable_flexibility"; - - // TODO(b/239925946): properly handle DeviceConfig and changing variables @GuardedBy("mLock") public void processConstantLocked(@NonNull DeviceConfig.Properties properties, @NonNull String key) { @@ -595,7 +665,68 @@ public final class FlexibilityController extends StateController { } } break; + case KEY_DEADLINE_PROXIMITY_LIMIT: + DEADLINE_PROXIMITY_LIMIT_MS = + properties.getLong(key, DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS); + if (mDeadlineProximityLimitMs != DEADLINE_PROXIMITY_LIMIT_MS) { + mDeadlineProximityLimitMs = DEADLINE_PROXIMITY_LIMIT_MS; + mShouldReevaluateConstraints = true; + } + break; + case KEY_FALLBACK_FLEXIBILITY_DEADLINE: + FALLBACK_FLEXIBILITY_DEADLINE_MS = + properties.getLong(key, DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS); + if (mFallbackFlexibilityDeadlineMs != FALLBACK_FLEXIBILITY_DEADLINE_MS) { + mFallbackFlexibilityDeadlineMs = FALLBACK_FLEXIBILITY_DEADLINE_MS; + mShouldReevaluateConstraints = true; + } + break; + case KEY_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS: + MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS = + properties.getLong(key, DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS); + if (mMinTimeBetweenFlexibilityAlarmsMs + != MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS) { + mMinTimeBetweenFlexibilityAlarmsMs = MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS; + mShouldReevaluateConstraints = true; + } + break; + case KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS: + String dropPercentString = properties.getString(key, ""); + PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS = + parsePercentToDropString(dropPercentString); + if (PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS != null + && !Arrays.equals(mPercentToDropConstraints, + PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS)) { + mPercentToDropConstraints = PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS; + mShouldReevaluateConstraints = true; + } + break; + } + } + + private int[] parsePercentToDropString(String s) { + String[] dropPercentString = s.split(","); + int[] dropPercentInt = new int[NUM_FLEXIBLE_CONSTRAINTS]; + if (dropPercentInt.length != dropPercentString.length) { + return DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; } + int prevPercent = 0; + for (int i = 0; i < dropPercentString.length; i++) { + try { + dropPercentInt[i] = + Integer.parseInt(dropPercentString[i]); + } catch (NumberFormatException ex) { + Slog.e(TAG, "Provided string was improperly formatted.", ex); + return DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; + } + if (dropPercentInt[i] < prevPercent) { + Slog.wtf(TAG, "Percents to drop constraints were not in increasing order."); + return DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; + } + prevPercent = dropPercentInt[i]; + } + + return dropPercentInt; } private void dump(IndentingPrintWriter pw) { @@ -612,8 +743,8 @@ public final class FlexibilityController extends StateController { @VisibleForTesting @NonNull - FcConstants getFcConstants() { - return mFcConstants; + FcConfig getFcConfig() { + return mFcConfig; } @Override @@ -623,6 +754,6 @@ public final class FlexibilityController extends StateController { pw.println(); mFlexibilityTracker.dump(pw, predicate); - mFcConstants.dump(pw); + mFcConfig.dump(pw); } } diff --git a/core/api/current.txt b/core/api/current.txt index 4734e8a75de6..1eb4c02ed1c3 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -14006,49 +14006,49 @@ package android.graphics { public final class Bitmap implements android.os.Parcelable { method @NonNull public android.graphics.Bitmap asShared(); - method @WorkerThread public boolean compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream); - method public android.graphics.Bitmap copy(android.graphics.Bitmap.Config, boolean); - method public void copyPixelsFromBuffer(java.nio.Buffer); - method public void copyPixelsToBuffer(java.nio.Buffer); - method public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Bitmap); - method public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Bitmap, int, int, int, int); - method public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Bitmap, int, int, int, int, @Nullable android.graphics.Matrix, boolean); - method public static android.graphics.Bitmap createBitmap(int, int, @NonNull android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(int, int, @NonNull android.graphics.Bitmap.Config, boolean); - method public static android.graphics.Bitmap createBitmap(int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace); - method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean); - method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace); - method public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@NonNull android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, @NonNull android.graphics.Bitmap.Config); + method @WorkerThread public boolean compress(@NonNull android.graphics.Bitmap.CompressFormat, int, @NonNull java.io.OutputStream); + method public android.graphics.Bitmap copy(@NonNull android.graphics.Bitmap.Config, boolean); + method public void copyPixelsFromBuffer(@NonNull java.nio.Buffer); + method public void copyPixelsToBuffer(@NonNull java.nio.Buffer); + method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Bitmap); + method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Bitmap, int, int, int, int); + method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Bitmap, int, int, int, int, @Nullable android.graphics.Matrix, boolean); + method @NonNull public static android.graphics.Bitmap createBitmap(int, int, @NonNull android.graphics.Bitmap.Config); + method @NonNull public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config); + method @NonNull public static android.graphics.Bitmap createBitmap(int, int, @NonNull android.graphics.Bitmap.Config, boolean); + method @NonNull public static android.graphics.Bitmap createBitmap(int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace); + method @NonNull public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean); + method @NonNull public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace); + method @NonNull public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); + method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config); + method @NonNull public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, android.graphics.Bitmap.Config); + method @NonNull public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, @NonNull android.graphics.Bitmap.Config); method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Picture); method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Picture, int, int, @NonNull android.graphics.Bitmap.Config); - method public static android.graphics.Bitmap createScaledBitmap(@NonNull android.graphics.Bitmap, int, int, boolean); + method @NonNull public static android.graphics.Bitmap createScaledBitmap(@NonNull android.graphics.Bitmap, int, int, boolean); method public int describeContents(); method public void eraseColor(@ColorInt int); method public void eraseColor(@ColorLong long); - method @CheckResult public android.graphics.Bitmap extractAlpha(); - method @CheckResult public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]); + method @CheckResult @NonNull public android.graphics.Bitmap extractAlpha(); + method @CheckResult @NonNull public android.graphics.Bitmap extractAlpha(@Nullable android.graphics.Paint, int[]); method public int getAllocationByteCount(); method public int getByteCount(); method @NonNull public android.graphics.Color getColor(int, int); method @Nullable public android.graphics.ColorSpace getColorSpace(); - method public android.graphics.Bitmap.Config getConfig(); + method @NonNull public android.graphics.Bitmap.Config getConfig(); method public int getDensity(); method public int getGenerationId(); method @NonNull public android.hardware.HardwareBuffer getHardwareBuffer(); method public int getHeight(); - method public byte[] getNinePatchChunk(); + method @Nullable public byte[] getNinePatchChunk(); method @ColorInt public int getPixel(int, int); - method public void getPixels(@ColorInt int[], int, int, int, int, int, int); + method public void getPixels(@ColorInt @NonNull int[], int, int, int, int, int, int); method public int getRowBytes(); - method public int getScaledHeight(android.graphics.Canvas); - method public int getScaledHeight(android.util.DisplayMetrics); + method public int getScaledHeight(@NonNull android.graphics.Canvas); + method public int getScaledHeight(@NonNull android.util.DisplayMetrics); method public int getScaledHeight(int); - method public int getScaledWidth(android.graphics.Canvas); - method public int getScaledWidth(android.util.DisplayMetrics); + method public int getScaledWidth(@NonNull android.graphics.Canvas); + method public int getScaledWidth(@NonNull android.util.DisplayMetrics); method public int getScaledWidth(int); method public int getWidth(); method public boolean hasAlpha(); @@ -14057,21 +14057,21 @@ package android.graphics { method public boolean isPremultiplied(); method public boolean isRecycled(); method public void prepareToDraw(); - method public void reconfigure(int, int, android.graphics.Bitmap.Config); + method public void reconfigure(int, int, @NonNull android.graphics.Bitmap.Config); method public void recycle(); - method public boolean sameAs(android.graphics.Bitmap); + method @WorkerThread public boolean sameAs(@Nullable android.graphics.Bitmap); method public void setColorSpace(@NonNull android.graphics.ColorSpace); - method public void setConfig(android.graphics.Bitmap.Config); + method public void setConfig(@NonNull android.graphics.Bitmap.Config); method public void setDensity(int); method public void setHasAlpha(boolean); method public void setHasMipMap(boolean); method public void setHeight(int); method public void setPixel(int, int, @ColorInt int); - method public void setPixels(@ColorInt int[], int, int, int, int, int, int); + method public void setPixels(@ColorInt @NonNull int[], int, int, int, int, int, int); method public void setPremultiplied(boolean); method public void setWidth(int); method @Nullable public static android.graphics.Bitmap wrapHardwareBuffer(@NonNull android.hardware.HardwareBuffer, @Nullable android.graphics.ColorSpace); - method public void writeToParcel(android.os.Parcel, int); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.graphics.Bitmap> CREATOR; field public static final int DENSITY_NONE = 0; // 0x0 } @@ -49957,7 +49957,6 @@ package android.view { method public void invalidate(); method public void invalidateDrawable(@NonNull android.graphics.drawable.Drawable); method public void invalidateOutline(); - method public boolean isAccessibilityDataPrivate(); method public boolean isAccessibilityFocused(); method public boolean isAccessibilityHeading(); method public boolean isActivated(); @@ -50135,7 +50134,6 @@ package android.view { method public void scrollTo(int, int); method public void sendAccessibilityEvent(int); method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent); - method public void setAccessibilityDataPrivate(int); method public void setAccessibilityDelegate(@Nullable android.view.View.AccessibilityDelegate); method public void setAccessibilityHeading(boolean); method public void setAccessibilityLiveRegion(int); @@ -50316,9 +50314,6 @@ package android.view { method @CallSuper protected boolean verifyDrawable(@NonNull android.graphics.drawable.Drawable); method @Deprecated public boolean willNotCacheDrawing(); method public boolean willNotDraw(); - field public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0; // 0x0 - field public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 2; // 0x2 - field public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 1; // 0x1 field public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2; // 0x2 field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0 field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1 @@ -51771,11 +51766,9 @@ package android.view.accessibility { method public int getSpeechStateChangeTypes(); method public int getWindowChanges(); method public void initFromParcel(android.os.Parcel); - method public boolean isAccessibilityDataPrivate(); method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(int); method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(android.view.accessibility.AccessibilityEvent); method @Deprecated public static android.view.accessibility.AccessibilityEvent obtain(); - method public void setAccessibilityDataPrivate(boolean); method public void setAction(int); method public void setContentChangeTypes(int); method public void setEventTime(long); @@ -51866,7 +51859,6 @@ package android.view.accessibility { method public static boolean isAccessibilityButtonSupported(); method public boolean isAudioDescriptionRequested(); method public boolean isEnabled(); - method public boolean isRequestFromAccessibilityTool(); method public boolean isTouchExplorationEnabled(); method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer); method public boolean removeAccessibilityServicesStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 572101c11bd3..be84032df9a4 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -13398,6 +13398,7 @@ package android.telephony { method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int checkCarrierPrivilegesForPackage(String); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int checkCarrierPrivilegesForPackageAnyPhone(String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void clearRadioPowerOffForReason(int); method public void dial(String); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean disableDataConnectivity(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity(); @@ -13443,6 +13444,7 @@ package android.telephony { method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup(); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.PhoneCapability getPhoneCapability(); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Set<java.lang.Integer> getRadioPowerOffReasons(); method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState(); method public int getSimApplicationState(); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int); @@ -13497,6 +13499,7 @@ package android.telephony { method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestRadioPowerOffForReason(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void resetIms(int); @@ -13521,9 +13524,9 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setNrDualConnectivityState(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int); @@ -13605,6 +13608,10 @@ package android.telephony { field public static final int PREPARE_UNATTENDED_REBOOT_SUCCESS = 0; // 0x0 field public static final int RADIO_POWER_OFF = 0; // 0x0 field public static final int RADIO_POWER_ON = 1; // 0x1 + field public static final int RADIO_POWER_REASON_CARRIER = 2; // 0x2 + field public static final int RADIO_POWER_REASON_NEARBY_DEVICE = 3; // 0x3 + field public static final int RADIO_POWER_REASON_THERMAL = 1; // 0x1 + field public static final int RADIO_POWER_REASON_USER = 0; // 0x0 field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2 field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2 field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1 diff --git a/core/api/test-current.txt b/core/api/test-current.txt index c87ea2adbd77..9a3c8a0c0d29 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -90,7 +90,6 @@ package android.accessibilityservice { public class AccessibilityServiceInfo implements android.os.Parcelable { method @NonNull public android.content.ComponentName getComponentName(); - method public void setAccessibilityTool(boolean); } } diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index 8f6bfd3b13db..2e89ce83cd36 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -784,7 +784,6 @@ public class AccessibilityServiceInfo implements Parcelable { mNonInteractiveUiTimeout = other.mNonInteractiveUiTimeout; mInteractiveUiTimeout = other.mInteractiveUiTimeout; flags = other.flags; - mIsAccessibilityTool = other.mIsAccessibilityTool; } private boolean isRequestAccessibilityButtonChangeEnabled(IPlatformCompat platformCompat) { @@ -1113,26 +1112,6 @@ public class AccessibilityServiceInfo implements Parcelable { } /** - * Sets whether the service is used to assist users with disabilities. - * - * <p> - * This property is normally provided in the service's {@link #mResolveInfo ResolveInfo}. - * </p> - * - * <p> - * This method is helpful for unit testing. However, this property is not dynamically - * configurable by a standard {@link AccessibilityService} so it's not possible to update the - * copy held by the system with this method. - * </p> - * - * @hide - */ - @TestApi - public void setAccessibilityTool(boolean isAccessibilityTool) { - mIsAccessibilityTool = isAccessibilityTool; - } - - /** * Indicates if the service is used to assist users with disabilities. * * @return {@code true} if the property is set to true. diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 36e1eee79d35..4da957c17a56 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -147,8 +147,6 @@ import android.net.NetworkWatchlistManager; import android.net.PacProxyManager; import android.net.TetheringManager; import android.net.VpnManager; -import android.net.lowpan.ILowpanManager; -import android.net.lowpan.LowpanManager; import android.net.vcn.IVcnManagementService; import android.net.vcn.VcnManager; import android.net.wifi.WifiFrameworkInitializer; @@ -779,15 +777,6 @@ public final class SystemServiceRegistry { ctx.mMainThread.getHandler()); }}); - registerService(Context.LOWPAN_SERVICE, LowpanManager.class, - new CachedServiceFetcher<LowpanManager>() { - @Override - public LowpanManager createService(ContextImpl ctx) throws ServiceNotFoundException { - IBinder b = ServiceManager.getServiceOrThrow(Context.LOWPAN_SERVICE); - ILowpanManager service = ILowpanManager.Stub.asInterface(b); - return new LowpanManager(ctx.getOuterContext(), service); - }}); - registerService(Context.WIFI_NL80211_SERVICE, WifiNl80211Manager.class, new CachedServiceFetcher<WifiNl80211Manager>() { @Override diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index 8d57e32a763c..a045157e02db 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -550,7 +550,6 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS); - info.setAccessibilityTool(true); try { // Calling out with a lock held is fine since if the system // process is gone the client calling in will be killed. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a7c72730a89f..baf3eecadedd 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7822,6 +7822,16 @@ public final class Settings { "accessibility_display_magnification_auto_update"; /** + * Accessibility Window Magnification Allow diagonal scrolling value. The value is boolean. + * 1 : on, 0 : off + * + * @hide + */ + public static final String ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING = + "accessibility_allow_diagonal_scrolling"; + + + /** * Setting that specifies what mode the soft keyboard is in (default or hidden). Can be * modified from an AccessibilityService using the SoftKeyboardController. * diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index 52dc34298ae7..a6f63e859049 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -89,7 +89,9 @@ public final class AccessibilityInteractionController { // Callbacks should have the same configuration of the flags below to allow satisfying a pending // node request on prefetch - private static final int FLAGS_AFFECTING_REPORTED_DATA = AccessibilityNodeInfo.FLAG_REPORT_MASK; + private static final int FLAGS_AFFECTING_REPORTED_DATA = + AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS + | AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; private final ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList = new ArrayList<AccessibilityNodeInfo>(); @@ -165,11 +167,6 @@ public final class AccessibilityInteractionController { return (view != null) && (view.getWindowVisibility() == View.VISIBLE && view.isShown()); } - private boolean isVisibleToAccessibilityService(View view) { - return view != null && (!view.isAccessibilityDataPrivate() - || mA11yManager.isRequestFromAccessibilityTool()); - } - public void findAccessibilityNodeInfoByAccessibilityIdClientThread( long accessibilityNodeId, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, @@ -361,7 +358,7 @@ public final class AccessibilityInteractionController { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { return; } - setAccessibilityFetchFlags(flags); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; requestedView = findViewByAccessibilityId(accessibilityViewId); if (requestedView != null && isShown(requestedView)) { requestedNode = populateAccessibilityNodeInfoForView( @@ -374,7 +371,7 @@ public final class AccessibilityInteractionController { mPrefetcher.prefetchAccessibilityNodeInfos(requestedView, requestedNode == null ? null : new AccessibilityNodeInfo(requestedNode), infos); - resetAccessibilityFetchFlags(); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; } } } finally { @@ -399,7 +396,7 @@ public final class AccessibilityInteractionController { } mPrefetcher.prefetchAccessibilityNodeInfos(requestedView, requestedNode == null ? null : new AccessibilityNodeInfo(requestedNode), infos); - resetAccessibilityFetchFlags(); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfosForViewPort(infos, spec, matrixValues, interactiveRegion); final SatisfiedFindAccessibilityNodeByAccessibilityIdRequest satisfiedRequest = getSatisfiedRequestInPrefetch(requestedNode == null ? null : requestedNode, infos, @@ -481,7 +478,7 @@ public final class AccessibilityInteractionController { || viewId == null) { return; } - setAccessibilityFetchFlags(flags); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; final View root = findViewByAccessibilityId(accessibilityViewId); if (root != null) { final int resolvedViewId = root.getContext().getResources() @@ -497,7 +494,7 @@ public final class AccessibilityInteractionController { mAddNodeInfosForViewId.reset(); } } finally { - resetAccessibilityFetchFlags(); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfosForViewportAndReturnFindNodeResult( infos, callback, interactionId, spec, matrixValues, interactiveRegion); } @@ -545,7 +542,7 @@ public final class AccessibilityInteractionController { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { return; } - setAccessibilityFetchFlags(flags); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; final View root = findViewByAccessibilityId(accessibilityViewId); if (root != null && isShown(root)) { AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider(); @@ -564,7 +561,7 @@ public final class AccessibilityInteractionController { final int viewCount = foundViews.size(); for (int i = 0; i < viewCount; i++) { View foundView = foundViews.get(i); - if (isShown(foundView) && isVisibleToAccessibilityService(foundView)) { + if (isShown(foundView)) { provider = foundView.getAccessibilityNodeProvider(); if (provider != null) { List<AccessibilityNodeInfo> infosFromProvider = @@ -582,7 +579,7 @@ public final class AccessibilityInteractionController { } } } finally { - resetAccessibilityFetchFlags(); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfosForViewportAndReturnFindNodeResult( infos, callback, interactionId, spec, matrixValues, interactiveRegion); } @@ -630,7 +627,7 @@ public final class AccessibilityInteractionController { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { return; } - setAccessibilityFetchFlags(flags); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; final View root = findViewByAccessibilityId(accessibilityViewId); if (root != null && isShown(root)) { switch (focusType) { @@ -645,9 +642,6 @@ public final class AccessibilityInteractionController { if (!isShown(host)) { break; } - if (!isVisibleToAccessibilityService(host)) { - break; - } // If the host has a provider ask this provider to search for the // focus instead fetching all provider nodes to do the search here. AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider(); @@ -668,9 +662,6 @@ public final class AccessibilityInteractionController { if (!isShown(target)) { break; } - if (!isVisibleToAccessibilityService(target)) { - break; - } AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider(); if (provider != null) { focused = provider.findFocus(focusType); @@ -684,7 +675,7 @@ public final class AccessibilityInteractionController { } } } finally { - resetAccessibilityFetchFlags(); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfoForViewportAndReturnFindNodeResult( focused, callback, interactionId, spec, matrixValues, interactiveRegion); } @@ -731,7 +722,7 @@ public final class AccessibilityInteractionController { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { return; } - setAccessibilityFetchFlags(flags); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; final View root = findViewByAccessibilityId(accessibilityViewId); if (root != null && isShown(root)) { View nextView = root.focusSearch(direction); @@ -740,7 +731,7 @@ public final class AccessibilityInteractionController { } } } finally { - resetAccessibilityFetchFlags(); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfoForViewportAndReturnFindNodeResult( next, callback, interactionId, spec, matrixValues, interactiveRegion); } @@ -787,9 +778,9 @@ public final class AccessibilityInteractionController { mViewRootImpl.mStopped || mViewRootImpl.mPausedForTransition) { return; } - setAccessibilityFetchFlags(flags); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; final View target = findViewByAccessibilityId(accessibilityViewId); - if (target != null && isShown(target) && isVisibleToAccessibilityService(target)) { + if (target != null && isShown(target)) { mA11yManager.notifyPerformingAction(action); if (action == R.id.accessibilityActionClickOnClickableSpan) { // Handle this hidden action separately @@ -808,7 +799,7 @@ public final class AccessibilityInteractionController { } } finally { try { - resetAccessibilityFetchFlags(); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; callback.setPerformAccessibilityActionResult(succeeded, interactionId); } catch (RemoteException re) { /* ignore - the other side will time out */ @@ -832,9 +823,9 @@ public final class AccessibilityInteractionController { return; } try { - setAccessibilityFetchFlags( - AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS); - final View root = getRootView(); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = + AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; + final View root = mViewRootImpl.mView; if (root != null && isShown(root)) { final View host = mViewRootImpl.mAccessibilityFocusedHost; // If there is no accessibility focus host or it is not a descendant @@ -858,7 +849,7 @@ public final class AccessibilityInteractionController { } } } finally { - resetAccessibilityFetchFlags(); + mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; } } @@ -878,7 +869,7 @@ public final class AccessibilityInteractionController { || mViewRootImpl.mStopped || mViewRootImpl.mPausedForTransition) { return; } - final View root = getRootView(); + final View root = mViewRootImpl.mView; if (root != null && isShown(root)) { // trigger ACTION_OUTSIDE to notify windows final long now = SystemClock.uptimeMillis(); @@ -891,30 +882,12 @@ public final class AccessibilityInteractionController { private View findViewByAccessibilityId(int accessibilityId) { if (accessibilityId == AccessibilityNodeInfo.ROOT_ITEM_ID) { - return getRootView(); + return mViewRootImpl.mView; } else { return AccessibilityNodeIdManager.getInstance().findView(accessibilityId); } } - private View getRootView() { - if (!isVisibleToAccessibilityService(mViewRootImpl.mView)) { - return null; - } - return mViewRootImpl.mView; - } - - private void setAccessibilityFetchFlags(int flags) { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags; - mA11yManager.setRequestFromAccessibilityTool( - (flags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) != 0); - } - - private void resetAccessibilityFetchFlags() { - mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; - mA11yManager.setRequestFromAccessibilityTool(false); - } - // The boundInScreen includes magnification effect, so we need to normalize it before // determine the visibility. private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info, @@ -1733,7 +1706,7 @@ public final class AccessibilityInteractionController { @Override public boolean test(View view) { - if (view.getId() == mViewId && isShown(view) && isVisibleToAccessibilityService(view)) { + if (view.getId() == mViewId && isShown(view)) { mInfos.add(view.createAccessibilityNodeInfo()); } return false; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 84edb3a7bdee..48937770eddb 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3085,45 +3085,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO; /** - * Automatically determine whether the view should only allow interactions from - * {@link android.accessibilityservice.AccessibilityService}s with the - * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property - * set to true. - * - * <p> - * Accessibility interactions from services without {@code isAccessibilityTool} set to true are - * disallowed for any of the following conditions: - * <li>this view's window sets {@link WindowManager.LayoutParams#FLAG_SECURE}.</li> - * <li>this view sets {@link #getFilterTouchesWhenObscured()}.</li> - * <li>any parent of this view returns true from {@link #isAccessibilityDataPrivate()}.</li> - * </p> - */ - public static final int ACCESSIBILITY_DATA_PRIVATE_AUTO = 0x00000000; - - /** - * Only allow interactions from {@link android.accessibilityservice.AccessibilityService}s - * with the {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} - * property set to true. - */ - public static final int ACCESSIBILITY_DATA_PRIVATE_YES = 0x00000001; - - /** - * Allow interactions from all {@link android.accessibilityservice.AccessibilityService}s, - * regardless of their - * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property. - */ - public static final int ACCESSIBILITY_DATA_PRIVATE_NO = 0x00000002; - - /** @hide */ - @IntDef(prefix = { "ACCESSIBILITY_DATA_PRIVATE_" }, value = { - ACCESSIBILITY_DATA_PRIVATE_AUTO, - ACCESSIBILITY_DATA_PRIVATE_YES, - ACCESSIBILITY_DATA_PRIVATE_NO, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AccessibilityDataPrivate {} - - /** * Mask for obtaining the bits which specify how to determine * whether a view is important for accessibility. */ @@ -4566,14 +4527,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private CharSequence mAccessibilityPaneTitle; /** - * Describes whether this view should only allow interactions from - * {@link android.accessibilityservice.AccessibilityService}s with the - * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property - * set to true. - */ - private int mAccessibilityDataPrivate = ACCESSIBILITY_DATA_PRIVATE_AUTO; - - /** * Specifies the id of a view for which this view serves as a label for * accessibility purposes. */ @@ -5966,10 +5919,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setImportantForAccessibility(a.getInt(attr, IMPORTANT_FOR_ACCESSIBILITY_DEFAULT)); break; - case R.styleable.View_accessibilityDataPrivate: - setAccessibilityDataPrivate(a.getInt(attr, - ACCESSIBILITY_DATA_PRIVATE_AUTO)); - break; case R.styleable.View_accessibilityLiveRegion: setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT)); break; @@ -8569,11 +8518,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * is responsible for handling this call. * </p> * <p> - * If this view sets {@link #isAccessibilityDataPrivate()} then this view should only append - * sensitive information to an event that also sets - * {@link AccessibilityEvent#isAccessibilityDataPrivate()}. - * </p> - * <p> * <em>Note:</em> Accessibility events of certain types are not dispatched for * populating the event text via this method. For details refer to {@link AccessibilityEvent}. * </p> @@ -10475,7 +10419,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if ((mAttachInfo.mAccessibilityFetchFlags - & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS) != 0 + & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0 && Resources.resourceHasPackage(mID)) { try { String viewId = getResources().getResourceName(mID); @@ -14458,75 +14402,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @UnsupportedAppUsage public boolean includeForAccessibility() { if (mAttachInfo != null) { - if (isAccessibilityDataPrivate() && !AccessibilityManager.getInstance( - mContext).isRequestFromAccessibilityTool()) { - return false; - } - return (mAttachInfo.mAccessibilityFetchFlags - & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 + & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 || isImportantForAccessibility(); } return false; } /** - * Whether this view should restrict accessibility service access only to services that have the - * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property - * set to true. - * - * <p> - * See default behavior provided by {@link #ACCESSIBILITY_DATA_PRIVATE_AUTO}. Otherwise, - * returns true for {@link #ACCESSIBILITY_DATA_PRIVATE_YES} or false for {@link - * #ACCESSIBILITY_DATA_PRIVATE_NO}. - * </p> - * - * @return True if this view should restrict accessibility service access to services that have - * the isAccessibilityTool property. - */ - @ViewDebug.ExportedProperty(category = "accessibility") - public boolean isAccessibilityDataPrivate() { - if (mAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_YES) { - return true; - } - if (mAccessibilityDataPrivate == ACCESSIBILITY_DATA_PRIVATE_NO) { - return false; - } - - // Views inside FLAG_SECURE windows default to accessibilityDataPrivate. - if (mAttachInfo != null && mAttachInfo.mWindowSecure) { - return true; - } - // Views that set filterTouchesWhenObscured default to accessibilityDataPrivate. - if (getFilterTouchesWhenObscured()) { - return true; - } - - // Descendants of an accessibilityDataPrivate View are also accessibilityDataPrivate. - ViewParent parent = mParent; - while (parent instanceof View) { - if (((View) parent).isAccessibilityDataPrivate()) { - return true; - } - parent = parent.getParent(); - } - - // Otherwise, default to not accessibilityDataPrivate. - return false; - } - - /** - * Specifies whether this view should only allow interactions from - * {@link android.accessibilityservice.AccessibilityService}s with the - * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property - * set to true. - */ - public void setAccessibilityDataPrivate( - @AccessibilityDataPrivate int accessibilityDataPrivate) { - mAccessibilityDataPrivate = accessibilityDataPrivate; - } - - /** * Returns whether the View is considered actionable from * accessibility perspective. Such view are important for * accessibility. @@ -30213,11 +30096,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int mWindowVisibility; /** - * Indicates whether the view's window sets {@link WindowManager.LayoutParams#FLAG_SECURE}. - */ - boolean mWindowSecure; - - /** * Indicates the time at which drawing started to occur. */ @UnsupportedAppUsage @@ -30394,8 +30272,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Flags related to accessibility processing. * - * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS - * @see AccessibilityNodeInfo#FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS + * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS + * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS */ int mAccessibilityFetchFlags; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index dd47bcdb2a63..674f0a283273 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2842,7 +2842,6 @@ public final class ViewRootImpl implements ViewParent, // However, windows are now always 32 bits by default, so choose 32 bits mAttachInfo.mUse32BitDrawingCache = true; mAttachInfo.mWindowVisibility = viewVisibility; - mAttachInfo.mWindowSecure = (lp.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0; mAttachInfo.mRecomputeGlobalAttributes = false; mLastConfigurationFromResources.setTo(config); mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility; @@ -6406,6 +6405,12 @@ public final class ViewRootImpl implements ViewParent, // Make sure the fallback event policy sees all keys that will be // delivered to the view hierarchy. mFallbackEventHandler.preDispatchKeyEvent(event); + + // Reset last tracked MotionEvent click toolType. + if (event.getAction() == KeyEvent.ACTION_DOWN) { + mLastClickToolType = MotionEvent.TOOL_TYPE_UNKNOWN; + } + return FORWARD; } diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index 2db0dcbce45e..cd0dd1df1249 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -46,17 +46,15 @@ import java.util.List; * </p> * <p> * The main purpose of an accessibility event is to communicate changes in the UI to an - * {@link android.accessibilityservice.AccessibilityService}. If needed, the service may then - * inspect the user interface by examining the View hierarchy through the event's - * {@link #getSource() source}, as represented by a tree of {@link AccessibilityNodeInfo}s (snapshot - * of a View state) which can be used for exploring the window content. Note that the privilege for - * accessing an event's source, thus the window content, has to be explicitly requested. For more + * {@link android.accessibilityservice.AccessibilityService}. The service may then inspect, + * if needed the user interface by examining the View hierarchy, as represented by a tree of + * {@link AccessibilityNodeInfo}s (snapshot of a View state) + * which can be used for exploring the window content. Note that the privilege for accessing + * an event's source, thus the window content, has to be explicitly requested. For more * details refer to {@link android.accessibilityservice.AccessibilityService}. If an * accessibility service has not requested to retrieve the window content the event will - * not contain reference to its source. <strong>Note: </strong> for events of type - * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available, and Views that set - * {@link android.view.View#isAccessibilityDataPrivate()} may not populate all event properties on - * events sent from higher up in the view hierarchy. + * not contain reference to its source. Also for events of type + * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available. * </p> * <p> * This class represents various semantically different accessibility event @@ -1094,47 +1092,6 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par } /** - * Whether the event should only be delivered to an - * {@link android.accessibilityservice.AccessibilityService} with the - * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property - * set to true. - * - * <p> - * Initial value matches the {@link android.view.View#isAccessibilityDataPrivate} property from - * the event's source node, if present, or false by default. - * </p> - * - * @return True if the event should be delivered only to isAccessibilityTool services, false - * otherwise. - * @see #setAccessibilityDataPrivate - */ - @Override - public boolean isAccessibilityDataPrivate() { - return super.isAccessibilityDataPrivate(); - } - - /** - * Sets whether the event should only be delivered to an - * {@link android.accessibilityservice.AccessibilityService} with the - * {@link android.accessibilityservice.AccessibilityServiceInfo#isAccessibilityTool} property - * set to true. - * - * <p> - * This will be set automatically based on the event's source (if present). If creating and - * sending an event directly through {@link AccessibilityManager} (where an event may have - * no source) then this method must be called explicitly if you want non-default behavior. - * </p> - * - * @param accessibilityDataPrivate True if the event should be delivered only to - * isAccessibilityTool services, false otherwise. - * @throws IllegalStateException If called from an AccessibilityService. - */ - @Override - public void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) { - super.setAccessibilityDataPrivate(accessibilityDataPrivate); - } - - /** * Gets the bit mask of the speech state signaled by a {@link #TYPE_SPEECH_STATE_CHANGE} event * * @see #SPEECH_STATE_SPEAKING_START diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index e89f836aaac1..9e3195aec8a6 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -276,8 +276,6 @@ public final class AccessibilityManager { private final ArrayMap<AudioDescriptionRequestedChangeListener, Executor> mAudioDescriptionRequestedChangeListeners = new ArrayMap<>(); - private boolean mRequestFromAccessibilityTool; - /** * Map from a view's accessibility id to the list of request preparers set for that view */ @@ -985,39 +983,6 @@ public final class AccessibilityManager { } /** - * Whether the current accessibility request comes from an - * {@link AccessibilityService} with the {@link AccessibilityServiceInfo#isAccessibilityTool} - * property set to true. - * - * <p> - * You can use this method inside {@link AccessibilityNodeProvider} to decide how to populate - * your nodes. - * </p> - * - * <p> - * <strong>Note:</strong> The return value is valid only when an {@link AccessibilityNodeInfo} - * request is in progress, can change from one request to another, and has no meaning when a - * request is not in progress. - * </p> - * - * @return True if the current request is from a tool that sets isAccessibilityTool. - */ - public boolean isRequestFromAccessibilityTool() { - return mRequestFromAccessibilityTool; - } - - /** - * Specifies whether the current accessibility request comes from an - * {@link AccessibilityService} with the {@link AccessibilityServiceInfo#isAccessibilityTool} - * property set to true. - * - * @hide - */ - public void setRequestFromAccessibilityTool(boolean requestFromAccessibilityTool) { - mRequestFromAccessibilityTool = requestFromAccessibilityTool; - } - - /** * Registers a {@link AccessibilityRequestPreparer}. */ public void addAccessibilityRequestPreparer(AccessibilityRequestPreparer preparer) { diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 15718c4af26f..953f2615b539 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -217,29 +217,14 @@ public class AccessibilityNodeInfo implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface PrefetchingStrategy {} - /** - * @see AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS - * @hide - */ - public static final int FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000080; - - /** - * @see AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS - * @hide - */ - public static final int FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS = 0x00000100; + /** @hide */ + public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000080; - /** - * @see AccessibilityServiceInfo#isAccessibilityTool() - * @hide - */ - public static final int FLAG_SERVICE_IS_ACCESSIBILITY_TOOL = 0x00000200; + /** @hide */ + public static final int FLAG_REPORT_VIEW_IDS = 0x00000100; /** @hide */ - public static final int FLAG_REPORT_MASK = - FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS - | FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS - | FLAG_SERVICE_IS_ACCESSIBILITY_TOOL; + public static final int FLAG_REPORT_MASK = 0x00000180; // Actions. diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java index 789c740bbba2..036316e15cb9 100644 --- a/core/java/android/view/accessibility/AccessibilityRecord.java +++ b/core/java/android/view/accessibility/AccessibilityRecord.java @@ -72,7 +72,6 @@ public class AccessibilityRecord { private static final int PROPERTY_FULL_SCREEN = 0x00000080; private static final int PROPERTY_SCROLLABLE = 0x00000100; private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200; - private static final int PROPERTY_ACCESSIBILITY_DATA_PRIVATE = 0x00000400; private static final int GET_SOURCE_PREFETCH_FLAGS = AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS @@ -160,8 +159,6 @@ public class AccessibilityRecord { important = root.isImportantForAccessibility(); rootViewId = root.getAccessibilityViewId(); mSourceWindowId = root.getAccessibilityWindowId(); - setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE, - root.isAccessibilityDataPrivate()); } setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important); mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId); @@ -391,23 +388,6 @@ public class AccessibilityRecord { } /** - * @see AccessibilityEvent#isAccessibilityDataPrivate - * @hide - */ - boolean isAccessibilityDataPrivate() { - return getBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE); - } - - /** - * @see AccessibilityEvent#setAccessibilityDataPrivate - * @hide - */ - void setAccessibilityDataPrivate(boolean accessibilityDataPrivate) { - enforceNotSealed(); - setBooleanProperty(PROPERTY_ACCESSIBILITY_DATA_PRIVATE, accessibilityDataPrivate); - } - - /** * Gets the number of items that can be visited. * * @return The number of items. @@ -961,8 +941,6 @@ public class AccessibilityRecord { appendUnless(false, PROPERTY_CHECKED, builder); appendUnless(false, PROPERTY_FULL_SCREEN, builder); appendUnless(false, PROPERTY_SCROLLABLE, builder); - appendUnless(false, PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, builder); - appendUnless(false, PROPERTY_ACCESSIBILITY_DATA_PRIVATE, builder); append(builder, "BeforeText", mBeforeText); append(builder, "FromIndex", mFromIndex); @@ -996,8 +974,6 @@ public class AccessibilityRecord { case PROPERTY_SCROLLABLE: return "Scrollable"; case PROPERTY_IMPORTANT_FOR_ACCESSIBILITY: return "ImportantForAccessibility"; - case PROPERTY_ACCESSIBILITY_DATA_PRIVATE: - return "AccessibilityDataPrivate"; default: return Integer.toHexString(prop); } } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index a01decca5224..8d3cf6d890d2 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -2331,9 +2331,6 @@ public final class InputMethodManager { editorInfo.packageName = view.getContext().getOpPackageName(); editorInfo.autofillId = view.getAutofillId(); editorInfo.fieldId = view.getId(); - synchronized (mH) { - editorInfo.setInitialToolType(mCurRootView.getLastClickToolType()); - } InputConnection ic = view.onCreateInputConnection(editorInfo); if (DEBUG) Log.v(TAG, "Starting input: editorInfo=" + editorInfo + " ic=" + ic); @@ -2373,6 +2370,8 @@ public final class InputMethodManager { startInputFlags |= StartInputFlags.INITIAL_CONNECTION; } + editorInfo.setInitialToolType(mCurRootView.getLastClickToolType()); + // Hook 'em up and let 'er rip. mCurrentEditorInfo = editorInfo.createCopyInternal(); // Store the previously served connection so that we can determine whether it is safe diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 3f87ec2beae5..1c7c5829d2bc 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4887,20 +4887,28 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Set the line break style for text wrapping. + * Sets the line-break style for text wrapping. * - * The line break style to indicates the line break strategies can be used when - * calculating the text wrapping. The line break style affects rule-based breaking. It - * specifies the strictness of line-breaking rules. - * There are several types for the line break style: - * {@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE}, - * {@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL} and - * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}. The default values of the line break style - * is {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}, indicating no breaking rule is specified. - * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property"> - * the line-break property</a> + * <p>Line-break style specifies the line-break strategies that can be used + * for text wrapping. The line-break style affects rule-based line breaking + * by specifying the strictness of line-breaking rules.</p> * - * @param lineBreakStyle the line break style for the text. + * <p>The following are types of line-break styles:</p> + * <ul> + * <li>{@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE}</li> + * <li>{@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL}</li> + * <li>{@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}</li> + * </ul> + * + * <p>The default line-break style is + * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}, which specifies that no + * line-breaking rules are used.</p> + * + * <p>See the + * <a href="https://www.w3.org/TR/css-text-3/#line-break-property" class="external"> + * line-break property</a> for more information.</p> + * + * @param lineBreakStyle The line break style for the text. */ public void setLineBreakStyle(@LineBreakConfig.LineBreakStyle int lineBreakStyle) { if (mLineBreakStyle != lineBreakStyle) { @@ -4914,17 +4922,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Set the line break word style for text wrapping. + * Sets the line-break word style for text wrapping. * - * The line break word style affects dictionary-based breaking and provide phrase-based - * breaking opportunities. The type for the line break word style is - * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}. The default values of the line break - * word style is {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}, indicating no breaking rule - * is specified. - * See <a href="https://www.w3.org/TR/css-text-3/#word-break-property"> - * the word-break property</a> + * <p>The line-break word style affects dictionary-based line breaking by + * providing phrase-based line-breaking opportunities. Use + * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE} to specify + * phrase-based line breaking.</p> * - * @param lineBreakWordStyle the line break word style for the tet + * <p>The default line-break word style is + * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}, which specifies that + * no line-breaking word style is used.</p> + * + * <p>See the + * <a href="https://www.w3.org/TR/css-text-3/#word-break-property" class="external"> + * word-break property</a> for more information.</p> + * + * @param lineBreakWordStyle The line break word style for the text. */ public void setLineBreakWordStyle(@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) { mUserSpeficiedLineBreakwordStyle = true; @@ -4939,18 +4952,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** - * Get the current line break style for text wrapping. + * Gets the current line-break style for text wrapping. * - * @return the current line break style to be used for text wrapping. + * @return The line-break style to be used for text wrapping. */ public @LineBreakConfig.LineBreakStyle int getLineBreakStyle() { return mLineBreakStyle; } /** - * Get the current line word break style for text wrapping. + * Gets the current line-break word style for text wrapping. * - * @return the current line break word style to be used for text wrapping. + * @return The line-break word style to be used for text wrapping. */ public @LineBreakConfig.LineBreakWordStyle int getLineBreakWordStyle() { return mLineBreakWordStyle; @@ -12076,13 +12089,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { super.onPopulateAccessibilityEventInternal(event); - if (this.isAccessibilityDataPrivate() && !event.isAccessibilityDataPrivate()) { - // This view's accessibility data is private, but another view that generated this event - // is not, so don't append this view's text to the event in order to prevent sharing - // this view's contents with non-accessibility-tool services. - return; - } - final CharSequence text = getTextForAccessibility(); if (!TextUtils.isEmpty(text)) { event.getText().add(text); diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java index 5e34c15c42e2..134a91710c0b 100644 --- a/core/java/com/android/internal/policy/DecorContext.java +++ b/core/java/com/android/internal/policy/DecorContext.java @@ -137,4 +137,13 @@ public class DecorContext extends ContextThemeWrapper { } return false; } + + @Override + public boolean isConfigurationContext() { + Context context = mContext.get(); + if (context != null) { + return context.isConfigurationContext(); + } + return false; + } } diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java index b866723954b5..b11ea2961c17 100644 --- a/core/java/com/android/internal/widget/LocalImageResolver.java +++ b/core/java/com/android/internal/widget/LocalImageResolver.java @@ -25,6 +25,7 @@ import android.graphics.ImageDecoder; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.net.Uri; +import android.text.TextUtils; import android.util.Log; import android.util.Size; @@ -108,6 +109,12 @@ public class LocalImageResolver { } break; case Icon.TYPE_RESOURCE: + if (!(TextUtils.isEmpty(icon.getResPackage()) + || context.getPackageName().equals(icon.getResPackage()))) { + // We can't properly resolve icons from other packages here, so fall back. + return icon.loadDrawable(context); + } + Drawable result = resolveImage(icon.getResId(), context, maxWidth, maxHeight); if (result != null) { return tintDrawable(icon, result); diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index d43a6c59a477..c7153fcf8609 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5542,22 +5542,22 @@ ignores some hyphen character related typographic features, e.g. kerning. --> <enum name="fullFast" value="4" /> </attr> - <!-- Indicates the line break strategies can be used when calculating the text wrapping. --> + <!-- Specifies the line-break strategies for text wrapping. --> <attr name="lineBreakStyle"> - <!-- No line break style specific. --> + <!-- No line-break rules are used for line breaking. --> <enum name="none" value="0" /> - <!-- Use the least restrictive rule for line-breaking. --> + <!-- The least restrictive line-break rules are used for line breaking. --> <enum name="loose" value="1" /> - <!-- Indicates breaking text with the most comment set of line-breaking rules. --> + <!-- The most common line-break rules are used for line breaking. --> <enum name="normal" value="2" /> - <!-- Indicates breaking text with the most strictest line-breaking rules. --> + <!-- The most strict line-break rules are used for line breaking. --> <enum name="strict" value="3" /> </attr> - <!-- Specify the phrase-based line break can be used when calculating the text wrapping.--> + <!-- Specifies the line-break word strategies for text wrapping.--> <attr name="lineBreakWordStyle"> - <!-- No line break word style specific. --> + <!-- No line-break word style is used for line breaking. --> <enum name="none" value="0" /> - <!-- Specify the phrase based breaking. --> + <!-- Line breaking is based on phrases, which results in text wrapping only on meaningful words. --> <enum name="phrase" value="1" /> </attr> <!-- Specify the type of auto-size. Note that this feature is not supported by EditText, diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 062523ed5f23..b5c7ea6bf4c5 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -2175,6 +2175,11 @@ tag; often this is one of the {@link android.Manifest.permission standard system permissions}. --> <attr name="name" /> + <!-- Optional: specify the minimum version of the Android OS for which the + application wishes to request the permission. When running on a version + of Android lower than the number given here, the permission will not + be requested. --> + <attr name="minSdkVersion" format="integer|string" /> <!-- Optional: specify the maximum version of the Android OS for which the application wishes to request the permission. When running on a version of Android higher than the number given here, the permission will not diff --git a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java index c63d18bfa531..0cee526651a6 100644 --- a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java +++ b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java @@ -270,4 +270,13 @@ public class LocalImageResolverTest { assertThat(bd.getBitmap().getHeight()).isEqualTo(originalHeight); } + + @Test + public void resolveImage_iconWithOtherPackageResource_usesPackageContextDefinition() + throws IOException { + Icon icon = Icon.createWithResource("this_is_invalid", R.drawable.test32x24); + Drawable d = LocalImageResolver.resolveImage(icon, mContext); + // This drawable must not be loaded - if it was, the code ignored the package specification. + assertThat(d).isNull(); + } } diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 857af11e4ca3..318cd32d19fe 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -277,7 +277,7 @@ public final class Bitmap implements Parcelable { * @see #setHeight(int) * @see #setConfig(Config) */ - public void reconfigure(int width, int height, Config config) { + public void reconfigure(int width, int height, @NonNull Config config) { checkRecycled("Can't call reconfigure() on a recycled bitmap"); if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width and height must be > 0"); @@ -336,7 +336,7 @@ public final class Bitmap implements Parcelable { * @see #setWidth(int) * @see #setHeight(int) */ - public void setConfig(Config config) { + public void setConfig(@NonNull Config config) { reconfigure(getWidth(), getHeight(), config); } @@ -590,7 +590,7 @@ public final class Bitmap implements Parcelable { * in the buffer.</p> * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE} */ - public void copyPixelsToBuffer(Buffer dst) { + public void copyPixelsToBuffer(@NonNull Buffer dst) { checkHardware("unable to copyPixelsToBuffer, " + "pixel access is not supported on Config#HARDWARE bitmaps"); int elements = dst.remaining(); @@ -632,7 +632,7 @@ public final class Bitmap implements Parcelable { * first rewind the buffer.</p> * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE} */ - public void copyPixelsFromBuffer(Buffer src) { + public void copyPixelsFromBuffer(@NonNull Buffer src) { checkRecycled("copyPixelsFromBuffer called on recycled bitmap"); checkHardware("unable to copyPixelsFromBuffer, Config#HARDWARE bitmaps are immutable"); @@ -686,7 +686,7 @@ public final class Bitmap implements Parcelable { * @return the new bitmap, or null if the copy could not be made. * @throws IllegalArgumentException if config is {@link Config#HARDWARE} and isMutable is true */ - public Bitmap copy(Config config, boolean isMutable) { + public Bitmap copy(@NonNull Config config, boolean isMutable) { checkRecycled("Can't copy a recycled bitmap"); if (config == Config.HARDWARE && isMutable) { throw new IllegalArgumentException("Hardware bitmaps are always immutable"); @@ -791,6 +791,7 @@ public final class Bitmap implements Parcelable { * @return The new scaled bitmap or the source bitmap if no scaling is required. * @throws IllegalArgumentException if width is <= 0, or height is <= 0 */ + @NonNull public static Bitmap createScaledBitmap(@NonNull Bitmap src, int dstWidth, int dstHeight, boolean filter) { Matrix m = new Matrix(); @@ -810,6 +811,7 @@ public final class Bitmap implements Parcelable { * be the same object as source, or a copy may have been made. It is * initialized with the same density and color space as the original bitmap. */ + @NonNull public static Bitmap createBitmap(@NonNull Bitmap src) { return createBitmap(src, 0, 0, src.getWidth(), src.getHeight()); } @@ -830,6 +832,7 @@ public final class Bitmap implements Parcelable { * outside of the dimensions of the source bitmap, or width is <= 0, * or height is <= 0 */ + @NonNull public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height) { return createBitmap(source, x, y, width, height, null, false); } @@ -865,6 +868,7 @@ public final class Bitmap implements Parcelable { * outside of the dimensions of the source bitmap, or width is <= 0, * or height is <= 0, or if the source bitmap has already been recycled */ + @NonNull public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height, @Nullable Matrix m, boolean filter) { @@ -985,6 +989,7 @@ public final class Bitmap implements Parcelable { * @throws IllegalArgumentException if the width or height are <= 0, or if * Config is Config.HARDWARE, because hardware bitmaps are always immutable */ + @NonNull public static Bitmap createBitmap(int width, int height, @NonNull Config config) { return createBitmap(width, height, config, true); } @@ -1003,6 +1008,7 @@ public final class Bitmap implements Parcelable { * @throws IllegalArgumentException if the width or height are <= 0, or if * Config is Config.HARDWARE, because hardware bitmaps are always immutable */ + @NonNull public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height, @NonNull Config config) { return createBitmap(display, width, height, config, true); @@ -1023,6 +1029,7 @@ public final class Bitmap implements Parcelable { * @throws IllegalArgumentException if the width or height are <= 0, or if * Config is Config.HARDWARE, because hardware bitmaps are always immutable */ + @NonNull public static Bitmap createBitmap(int width, int height, @NonNull Config config, boolean hasAlpha) { return createBitmap(null, width, height, config, hasAlpha); @@ -1050,6 +1057,7 @@ public final class Bitmap implements Parcelable { * {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if * the color space is null */ + @NonNull public static Bitmap createBitmap(int width, int height, @NonNull Config config, boolean hasAlpha, @NonNull ColorSpace colorSpace) { return createBitmap(null, width, height, config, hasAlpha, colorSpace); @@ -1073,6 +1081,7 @@ public final class Bitmap implements Parcelable { * @throws IllegalArgumentException if the width or height are <= 0, or if * Config is Config.HARDWARE, because hardware bitmaps are always immutable */ + @NonNull public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height, @NonNull Config config, boolean hasAlpha) { return createBitmap(display, width, height, config, hasAlpha, @@ -1105,6 +1114,7 @@ public final class Bitmap implements Parcelable { * {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if * the color space is null */ + @NonNull public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height, @NonNull Config config, boolean hasAlpha, @NonNull ColorSpace colorSpace) { if (width <= 0 || height <= 0) { @@ -1152,6 +1162,7 @@ public final class Bitmap implements Parcelable { * @throws IllegalArgumentException if the width or height are <= 0, or if * the color array's length is less than the number of pixels. */ + @NonNull public static Bitmap createBitmap(@NonNull @ColorInt int[] colors, int offset, int stride, int width, int height, @NonNull Config config) { return createBitmap(null, colors, offset, stride, width, height, config); @@ -1179,6 +1190,7 @@ public final class Bitmap implements Parcelable { * @throws IllegalArgumentException if the width or height are <= 0, or if * the color array's length is less than the number of pixels. */ + @NonNull public static Bitmap createBitmap(@NonNull DisplayMetrics display, @NonNull @ColorInt int[] colors, int offset, int stride, int width, int height, @NonNull Config config) { @@ -1221,6 +1233,7 @@ public final class Bitmap implements Parcelable { * @throws IllegalArgumentException if the width or height are <= 0, or if * the color array's length is less than the number of pixels. */ + @NonNull public static Bitmap createBitmap(@NonNull @ColorInt int[] colors, int width, int height, Config config) { return createBitmap(null, colors, 0, width, width, height, config); @@ -1245,6 +1258,7 @@ public final class Bitmap implements Parcelable { * @throws IllegalArgumentException if the width or height are <= 0, or if * the color array's length is less than the number of pixels. */ + @NonNull public static Bitmap createBitmap(@Nullable DisplayMetrics display, @NonNull @ColorInt int colors[], int width, int height, @NonNull Config config) { return createBitmap(display, colors, 0, width, width, height, config); @@ -1262,7 +1276,8 @@ public final class Bitmap implements Parcelable { * @return An immutable bitmap with a HARDWARE config whose contents are created * from the recorded drawing commands in the Picture source. */ - public static @NonNull Bitmap createBitmap(@NonNull Picture source) { + @NonNull + public static Bitmap createBitmap(@NonNull Picture source) { return createBitmap(source, source.getWidth(), source.getHeight(), Config.HARDWARE); } @@ -1283,7 +1298,8 @@ public final class Bitmap implements Parcelable { * * @return An immutable bitmap with a configuration specified by the config parameter */ - public static @NonNull Bitmap createBitmap(@NonNull Picture source, int width, int height, + @NonNull + public static Bitmap createBitmap(@NonNull Picture source, int width, int height, @NonNull Config config) { if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width & height must be > 0"); @@ -1330,6 +1346,7 @@ public final class Bitmap implements Parcelable { * Returns an optional array of private data, used by the UI system for * some bitmaps. Not intended to be called by applications. */ + @Nullable public byte[] getNinePatchChunk() { return mNinePatchChunk; } @@ -1431,7 +1448,8 @@ public final class Bitmap implements Parcelable { * @return true if successfully compressed to the specified stream. */ @WorkerThread - public boolean compress(CompressFormat format, int quality, OutputStream stream) { + public boolean compress(@NonNull CompressFormat format, int quality, + @NonNull OutputStream stream) { checkRecycled("Can't compress a recycled bitmap"); // do explicit check before calling the native method if (stream == null) { @@ -1548,7 +1566,7 @@ public final class Bitmap implements Parcelable { * Convenience for calling {@link #getScaledWidth(int)} with the target * density of the given {@link Canvas}. */ - public int getScaledWidth(Canvas canvas) { + public int getScaledWidth(@NonNull Canvas canvas) { return scaleFromDensity(getWidth(), mDensity, canvas.mDensity); } @@ -1556,7 +1574,7 @@ public final class Bitmap implements Parcelable { * Convenience for calling {@link #getScaledHeight(int)} with the target * density of the given {@link Canvas}. */ - public int getScaledHeight(Canvas canvas) { + public int getScaledHeight(@NonNull Canvas canvas) { return scaleFromDensity(getHeight(), mDensity, canvas.mDensity); } @@ -1564,7 +1582,7 @@ public final class Bitmap implements Parcelable { * Convenience for calling {@link #getScaledWidth(int)} with the target * density of the given {@link DisplayMetrics}. */ - public int getScaledWidth(DisplayMetrics metrics) { + public int getScaledWidth(@NonNull DisplayMetrics metrics) { return scaleFromDensity(getWidth(), mDensity, metrics.densityDpi); } @@ -1572,7 +1590,7 @@ public final class Bitmap implements Parcelable { * Convenience for calling {@link #getScaledHeight(int)} with the target * density of the given {@link DisplayMetrics}. */ - public int getScaledHeight(DisplayMetrics metrics) { + public int getScaledHeight(@NonNull DisplayMetrics metrics) { return scaleFromDensity(getHeight(), mDensity, metrics.densityDpi); } @@ -1682,6 +1700,7 @@ public final class Bitmap implements Parcelable { * If the bitmap's internal config is in one of the public formats, return * that config, otherwise return null. */ + @NonNull public final Config getConfig() { if (mRecycled) { Log.w(TAG, "Called getConfig() on a recycle()'d bitmap! This is undefined behavior!"); @@ -1967,7 +1986,7 @@ public final class Bitmap implements Parcelable { * to receive the specified number of pixels. * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE} */ - public void getPixels(@ColorInt int[] pixels, int offset, int stride, + public void getPixels(@NonNull @ColorInt int[] pixels, int offset, int stride, int x, int y, int width, int height) { checkRecycled("Can't call getPixels() on a recycled bitmap"); checkHardware("unable to getPixels(), " @@ -2084,7 +2103,7 @@ public final class Bitmap implements Parcelable { * @throws ArrayIndexOutOfBoundsException if the pixels array is too small * to receive the specified number of pixels. */ - public void setPixels(@ColorInt int[] pixels, int offset, int stride, + public void setPixels(@NonNull @ColorInt int[] pixels, int offset, int stride, int x, int y, int width, int height) { checkRecycled("Can't call setPixels() on a recycled bitmap"); if (!isMutable()) { @@ -2098,7 +2117,7 @@ public final class Bitmap implements Parcelable { x, y, width, height); } - public static final @android.annotation.NonNull Parcelable.Creator<Bitmap> CREATOR + public static final @NonNull Parcelable.Creator<Bitmap> CREATOR = new Parcelable.Creator<Bitmap>() { /** * Rebuilds a bitmap previously stored with writeToParcel(). @@ -2134,7 +2153,7 @@ public final class Bitmap implements Parcelable { * by the final pixel format * @param p Parcel object to write the bitmap data into */ - public void writeToParcel(Parcel p, int flags) { + public void writeToParcel(@NonNull Parcel p, int flags) { checkRecycled("Can't parcel a recycled bitmap"); noteHardwareBitmapSlowCall(); if (!nativeWriteToParcel(mNativePtr, mDensity, p)) { @@ -2150,6 +2169,7 @@ public final class Bitmap implements Parcelable { * @return new bitmap containing the alpha channel of the original bitmap. */ @CheckResult + @NonNull public Bitmap extractAlpha() { return extractAlpha(null, null); } @@ -2180,7 +2200,8 @@ public final class Bitmap implements Parcelable { * paint that is passed to the draw call. */ @CheckResult - public Bitmap extractAlpha(Paint paint, int[] offsetXY) { + @NonNull + public Bitmap extractAlpha(@Nullable Paint paint, int[] offsetXY) { checkRecycled("Can't extractAlpha on a recycled bitmap"); long nativePaint = paint != null ? paint.getNativeInstance() : 0; noteHardwareBitmapSlowCall(); @@ -2197,12 +2218,12 @@ public final class Bitmap implements Parcelable { * and pixel data as this bitmap. If any of those differ, return false. * If other is null, return false. */ - public boolean sameAs(Bitmap other) { + @WorkerThread + public boolean sameAs(@Nullable Bitmap other) { + StrictMode.noteSlowCall("sameAs compares pixel data, not expected to be fast"); checkRecycled("Can't call sameAs on a recycled bitmap!"); - noteHardwareBitmapSlowCall(); if (this == other) return true; if (other == null) return false; - other.noteHardwareBitmapSlowCall(); if (other.isRecycled()) { throw new IllegalArgumentException("Can't compare to a recycled bitmap!"); } @@ -2247,7 +2268,8 @@ public final class Bitmap implements Parcelable { * @throws IllegalStateException if the bitmap's config is not {@link Config#HARDWARE} * or if the bitmap has been recycled. */ - public @NonNull HardwareBuffer getHardwareBuffer() { + @NonNull + public HardwareBuffer getHardwareBuffer() { checkRecycled("Can't getHardwareBuffer from a recycled bitmap"); HardwareBuffer hardwareBuffer = mHardwareBuffer == null ? null : mHardwareBuffer.get(); if (hardwareBuffer == null || hardwareBuffer.isClosed()) { diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java index 7ad9aecaf6a3..48aecd61fc19 100644 --- a/graphics/java/android/graphics/text/LineBreakConfig.java +++ b/graphics/java/android/graphics/text/LineBreakConfig.java @@ -24,29 +24,32 @@ import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** - * Indicates the strategies can be used when calculating the text wrapping. + * Specifies the line-break strategies for text wrapping. * - * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">the line-break property</a> + * <p>See the + * <a href="https://www.w3.org/TR/css-text-3/#line-break-property" class="external"> + * line-break property</a> for more information.</p> */ public final class LineBreakConfig { /** - * No line break style specified. + * No line-break rules are used for line breaking. */ public static final int LINE_BREAK_STYLE_NONE = 0; /** - * Use the least restrictive rule for line-breaking. This is usually used for short lines. + * The least restrictive line-break rules are used for line breaking. This + * setting is typically used for short lines. */ public static final int LINE_BREAK_STYLE_LOOSE = 1; /** - * Indicate breaking text with the most comment set of line-breaking rules. + * The most common line-break rules are used for line breaking. */ public static final int LINE_BREAK_STYLE_NORMAL = 2; /** - * Indicates breaking text with the most strictest line-breaking rules. + * The most strict line-break rules are used for line breaking. */ public static final int LINE_BREAK_STYLE_STRICT = 3; @@ -59,15 +62,17 @@ public final class LineBreakConfig { public @interface LineBreakStyle {} /** - * No line break word style specified. + * No line-break word style is used for line breaking. */ public static final int LINE_BREAK_WORD_STYLE_NONE = 0; /** - * Indicates the line breaking is based on the phrased. This makes text wrapping only on - * meaningful words. The support of the text wrapping word style varies depending on the - * locales. If the locale does not support the phrase based text wrapping, - * there will be no effect. + * Line breaking is based on phrases, which results in text wrapping only on + * meaningful words. + * + * <p>Support for this line-break word style depends on locale. If the + * current locale does not support phrase-based text wrapping, this setting + * has no effect.</p> */ public static final int LINE_BREAK_WORD_STYLE_PHRASE = 1; @@ -79,7 +84,7 @@ public final class LineBreakConfig { public @interface LineBreakWordStyle {} /** - * A builder for creating {@link LineBreakConfig}. + * A builder for creating a {@code LineBreakConfig} instance. */ public static final class Builder { // The line break style for the LineBreakConfig. @@ -95,16 +100,16 @@ public final class LineBreakConfig { private boolean mAutoPhraseBreaking = false; /** - * Builder constructor with line break parameters. + * Builder constructor. */ public Builder() { } /** - * Set the line break style. + * Sets the line-break style. * - * @param lineBreakStyle the new line break style. - * @return this Builder + * @param lineBreakStyle The new line-break style. + * @return This {@code Builder}. */ public @NonNull Builder setLineBreakStyle(@LineBreakStyle int lineBreakStyle) { mLineBreakStyle = lineBreakStyle; @@ -112,10 +117,10 @@ public final class LineBreakConfig { } /** - * Set the line break word style. + * Sets the line-break word style. * - * @param lineBreakWordStyle the new line break word style. - * @return this Builder + * @param lineBreakWordStyle The new line-break word style. + * @return This {@code Builder}. */ public @NonNull Builder setLineBreakWordStyle(@LineBreakWordStyle int lineBreakWordStyle) { mLineBreakWordStyle = lineBreakWordStyle; @@ -123,7 +128,7 @@ public final class LineBreakConfig { } /** - * Enable or disable the automation of {@link LINE_BREAK_WORD_STYLE_PHRASE}. + * Enables or disables the automation of {@link LINE_BREAK_WORD_STYLE_PHRASE}. * * @hide */ @@ -133,9 +138,9 @@ public final class LineBreakConfig { } /** - * Build the {@link LineBreakConfig} + * Builds a {@link LineBreakConfig} instance. * - * @return the LineBreakConfig instance. + * @return The {@code LineBreakConfig} instance. */ public @NonNull LineBreakConfig build() { return new LineBreakConfig(mLineBreakStyle, mLineBreakWordStyle, mAutoPhraseBreaking); @@ -143,11 +148,12 @@ public final class LineBreakConfig { } /** - * Create the LineBreakConfig instance. + * Creates a {@code LineBreakConfig} instance with the provided line break + * parameters. * - * @param lineBreakStyle the line break style for text wrapping. - * @param lineBreakWordStyle the line break word style for text wrapping. - * @return the {@link LineBreakConfig} instance. + * @param lineBreakStyle The line-break style for text wrapping. + * @param lineBreakWordStyle The line-break word style for text wrapping. + * @return The {@code LineBreakConfig} instance. * @hide */ public static @NonNull LineBreakConfig getLineBreakConfig(@LineBreakStyle int lineBreakStyle, @@ -185,8 +191,10 @@ public final class LineBreakConfig { private final boolean mAutoPhraseBreaking; /** - * Constructor with the line break parameters. - * Use the {@link LineBreakConfig.Builder} to create the LineBreakConfig instance. + * Constructor with line-break parameters. + * + * <p>Use {@link LineBreakConfig.Builder} to create the + * {@code LineBreakConfig} instance.</p> */ private LineBreakConfig(@LineBreakStyle int lineBreakStyle, @LineBreakWordStyle int lineBreakWordStyle, boolean autoPhraseBreaking) { @@ -196,18 +204,18 @@ public final class LineBreakConfig { } /** - * Get the line break style. + * Gets the current line-break style. * - * @return The current line break style to be used for the text wrapping. + * @return The line-break style to be used for text wrapping. */ public @LineBreakStyle int getLineBreakStyle() { return mLineBreakStyle; } /** - * Get the line break word style. + * Gets the current line-break word style. * - * @return The current line break word style to be used for the text wrapping. + * @return The line-break word style to be used for text wrapping. */ public @LineBreakWordStyle int getLineBreakWordStyle() { return mLineBreakWordStyle; diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp index 3a8e559f6d7e..687e4dd324d3 100644 --- a/libs/hwui/FrameInfoVisualizer.cpp +++ b/libs/hwui/FrameInfoVisualizer.cpp @@ -179,7 +179,7 @@ void FrameInfoVisualizer::initializeRects(const int baseline, const int width) { void FrameInfoVisualizer::nextBarSegment(FrameInfoIndex start, FrameInfoIndex end) { int fast_i = (mNumFastRects - 1) * 4; int janky_i = (mNumJankyRects - 1) * 4; - ; + for (size_t fi = 0; fi < mFrameSource.size(); fi++) { if (mFrameSource[fi][FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame) { continue; diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp index 5a9d2508230e..9a4bda2ee1df 100644 --- a/libs/hwui/hwui/Typeface.cpp +++ b/libs/hwui/hwui/Typeface.cpp @@ -127,7 +127,7 @@ Typeface* Typeface::createWithDifferentBaseWeight(Typeface* src, int weight) { Typeface* Typeface::createFromFamilies(std::vector<std::shared_ptr<minikin::FontFamily>>&& families, int weight, int italic) { Typeface* result = new Typeface; - result->fFontCollection.reset(new minikin::FontCollection(families)); + result->fFontCollection = minikin::FontCollection::create(families); if (weight == RESOLVE_BY_FONT_TABLE || italic == RESOLVE_BY_FONT_TABLE) { int weightFromFont; @@ -191,8 +191,8 @@ void Typeface::setRobotoTypefaceForTest() { std::vector<std::shared_ptr<minikin::Font>> fonts; fonts.push_back(minikin::Font::Builder(font).build()); - std::shared_ptr<minikin::FontCollection> collection = std::make_shared<minikin::FontCollection>( - std::make_shared<minikin::FontFamily>(std::move(fonts))); + std::shared_ptr<minikin::FontCollection> collection = + minikin::FontCollection::create(minikin::FontFamily::create(std::move(fonts))); Typeface* hwTypeface = new Typeface(); hwTypeface->fFontCollection = collection; diff --git a/libs/hwui/jni/FontFamily.cpp b/libs/hwui/jni/FontFamily.cpp index acc1b0424030..c146adac6b69 100644 --- a/libs/hwui/jni/FontFamily.cpp +++ b/libs/hwui/jni/FontFamily.cpp @@ -85,9 +85,9 @@ static jlong FontFamily_create(CRITICAL_JNI_PARAMS_COMMA jlong builderPtr) { if (builder->fonts.empty()) { return 0; } - std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>( - builder->langId, builder->variant, std::move(builder->fonts), - true /* isCustomFallback */); + std::shared_ptr<minikin::FontFamily> family = + minikin::FontFamily::create(builder->langId, builder->variant, + std::move(builder->fonts), true /* isCustomFallback */); if (family->getCoverage().length() == 0) { return 0; } diff --git a/libs/hwui/jni/fonts/FontFamily.cpp b/libs/hwui/jni/fonts/FontFamily.cpp index b68213549938..fbfc07e1f89d 100644 --- a/libs/hwui/jni/fonts/FontFamily.cpp +++ b/libs/hwui/jni/fonts/FontFamily.cpp @@ -66,9 +66,9 @@ static jlong FontFamily_Builder_build(JNIEnv* env, jobject clazz, jlong builderP ScopedUtfChars str(env, langTags); localeId = minikin::registerLocaleList(str.c_str()); } - std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>( - localeId, static_cast<minikin::FamilyVariant>(variant), std::move(builder->fonts), - isCustomFallback); + std::shared_ptr<minikin::FontFamily> family = + minikin::FontFamily::create(localeId, static_cast<minikin::FamilyVariant>(variant), + std::move(builder->fonts), isCustomFallback); if (family->getCoverage().length() == 0) { // No coverage means minikin rejected given font for some reasons. jniThrowException(env, "java/lang/IllegalArgumentException", diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 976117b9bbd4..75d3ff7753cb 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -512,9 +512,19 @@ nsecs_t CanvasContext::draw() { ATRACE_FORMAT("Drawing " RECT_STRING, SK_RECT_ARGS(dirty)); - const auto drawResult = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, - &mLayerUpdateQueue, mContentDrawBounds, mOpaque, - mLightInfo, mRenderNodes, &(profiler())); + IRenderPipeline::DrawResult drawResult; + { + // FrameInfoVisualizer accesses the frame events, which cannot be mutated mid-draw + // or it can lead to memory corruption. + // This lock is overly broad, but it's the quickest fix since this mutex is otherwise + // not visible to IRenderPipeline much less FrameInfoVisualizer. And since this is + // the thread we're primarily concerned about being responsive, this being too broad + // shouldn't pose a performance issue. + std::scoped_lock lock(mFrameMetricsReporterMutex); + drawResult = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, + &mLayerUpdateQueue, mContentDrawBounds, mOpaque, + mLightInfo, mRenderNodes, &(profiler())); + } uint64_t frameCompleteNr = getFrameNumber(); @@ -754,11 +764,11 @@ void CanvasContext::onSurfaceStatsAvailable(void* context, int32_t surfaceContro FrameInfo* frameInfo = instance->getFrameInfoFromLast4(frameNumber, surfaceControlId); if (frameInfo != nullptr) { + std::scoped_lock lock(instance->mFrameMetricsReporterMutex); frameInfo->set(FrameInfoIndex::FrameCompleted) = std::max(gpuCompleteTime, frameInfo->get(FrameInfoIndex::SwapBuffersCompleted)); frameInfo->set(FrameInfoIndex::GpuCompleted) = std::max( gpuCompleteTime, frameInfo->get(FrameInfoIndex::CommandSubmissionCompleted)); - std::scoped_lock lock(instance->mFrameMetricsReporterMutex); instance->mJankTracker.finishFrame(*frameInfo, instance->mFrameMetricsReporter, frameNumber, surfaceControlId); } diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp index 9295a938f397..25cc8ca0dafb 100644 --- a/libs/hwui/tests/unit/TypefaceTests.cpp +++ b/libs/hwui/tests/unit/TypefaceTests.cpp @@ -64,7 +64,7 @@ std::shared_ptr<minikin::FontFamily> buildFamily(const char* fileName) { std::vector<minikin::FontVariation>()); std::vector<std::shared_ptr<minikin::Font>> fonts; fonts.push_back(minikin::Font::Builder(font).build()); - return std::make_shared<minikin::FontFamily>(std::move(fonts)); + return minikin::FontFamily::create(std::move(fonts)); } std::vector<std::shared_ptr<minikin::FontFamily>> makeSingleFamlyVector(const char* fileName) { diff --git a/lowpan/java/Android.bp b/lowpan/java/Android.bp deleted file mode 100644 index 58513d70042c..000000000000 --- a/lowpan/java/Android.bp +++ /dev/null @@ -1,17 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -filegroup { - name: "framework-lowpan-sources", - srcs: [ - "**/*.java", - "**/*.aidl", - ], - visibility: ["//frameworks/base"], -} diff --git a/lowpan/java/android/net/lowpan/ILowpanInterface.aidl b/lowpan/java/android/net/lowpan/ILowpanInterface.aidl deleted file mode 100644 index 603dc3cfe641..000000000000 --- a/lowpan/java/android/net/lowpan/ILowpanInterface.aidl +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.net.IpPrefix; -import android.net.lowpan.ILowpanEnergyScanCallback; -import android.net.lowpan.ILowpanInterfaceListener; -import android.net.lowpan.ILowpanNetScanCallback; -import android.net.lowpan.LowpanBeaconInfo; -import android.net.lowpan.LowpanChannelInfo; -import android.net.lowpan.LowpanCredential; -import android.net.lowpan.LowpanIdentity; -import android.net.lowpan.LowpanProvision; - -/** {@hide} */ -interface ILowpanInterface { - - // These are here for the sake of C++ interface implementations. - - const String PERM_ACCESS_LOWPAN_STATE = "android.permission.ACCESS_LOWPAN_STATE"; - const String PERM_CHANGE_LOWPAN_STATE = "android.permission.CHANGE_LOWPAN_STATE"; - const String PERM_READ_LOWPAN_CREDENTIAL = "android.permission.READ_LOWPAN_CREDENTIAL"; - - /** - * Channel mask key. - * Used for setting a channel mask when starting a scan. - * Type: int[] - * */ - const String KEY_CHANNEL_MASK = "android.net.lowpan.property.CHANNEL_MASK"; - - /** - * Max Transmit Power Key. - * Used for setting the maximum transmit power when starting a network scan. - * Type: Integer - * */ - const String KEY_MAX_TX_POWER = "android.net.lowpan.property.MAX_TX_POWER"; - - // Interface States - - const String STATE_OFFLINE = "offline"; - const String STATE_COMMISSIONING = "commissioning"; - const String STATE_ATTACHING = "attaching"; - const String STATE_ATTACHED = "attached"; - const String STATE_FAULT = "fault"; - - // Device Roles - - const String ROLE_END_DEVICE = "end-device"; - const String ROLE_ROUTER = "router"; - const String ROLE_SLEEPY_END_DEVICE = "sleepy-end-device"; - const String ROLE_SLEEPY_ROUTER = "sleepy-router"; - const String ROLE_LEADER = "leader"; - const String ROLE_COORDINATOR = "coordinator"; - const String ROLE_DETACHED = "detached"; - - const String NETWORK_TYPE_UNKNOWN = "unknown"; - - /** - * Network type for Thread 1.x networks. - * - * @see android.net.lowpan.LowpanIdentity#getType - * @see #getLowpanIdentity - */ - const String NETWORK_TYPE_THREAD_V1 = "org.threadgroup.thread.v1"; - - // Service-Specific Error Code Constants - - const int ERROR_UNSPECIFIED = 1; - const int ERROR_INVALID_ARGUMENT = 2; - const int ERROR_DISABLED = 3; - const int ERROR_WRONG_STATE = 4; - const int ERROR_TIMEOUT = 5; - const int ERROR_IO_FAILURE = 6; - const int ERROR_NCP_PROBLEM = 7; - const int ERROR_BUSY = 8; - const int ERROR_ALREADY = 9; - const int ERROR_CANCELED = 10; - const int ERROR_FEATURE_NOT_SUPPORTED = 11; - const int ERROR_JOIN_FAILED_UNKNOWN = 12; - const int ERROR_JOIN_FAILED_AT_SCAN = 13; - const int ERROR_JOIN_FAILED_AT_AUTH = 14; - const int ERROR_FORM_FAILED_AT_SCAN = 15; - - // Methods - - @utf8InCpp String getName(); - - @utf8InCpp String getNcpVersion(); - @utf8InCpp String getDriverVersion(); - LowpanChannelInfo[] getSupportedChannels(); - @utf8InCpp String[] getSupportedNetworkTypes(); - byte[] getMacAddress(); - - boolean isEnabled(); - void setEnabled(boolean enabled); - - boolean isUp(); - boolean isCommissioned(); - boolean isConnected(); - @utf8InCpp String getState(); - - @utf8InCpp String getRole(); - @utf8InCpp String getPartitionId(); - byte[] getExtendedAddress(); - - LowpanIdentity getLowpanIdentity(); - LowpanCredential getLowpanCredential(); - - @utf8InCpp String[] getLinkAddresses(); - IpPrefix[] getLinkNetworks(); - - void join(in LowpanProvision provision); - void form(in LowpanProvision provision); - void attach(in LowpanProvision provision); - void leave(); - void reset(); - - void startCommissioningSession(in LowpanBeaconInfo beaconInfo); - void closeCommissioningSession(); - oneway void sendToCommissioner(in byte[] packet); - - void beginLowPower(); - oneway void pollForData(); - - oneway void onHostWake(); - - void addListener(ILowpanInterfaceListener listener); - oneway void removeListener(ILowpanInterfaceListener listener); - - void startNetScan(in Map properties, ILowpanNetScanCallback listener); - oneway void stopNetScan(); - - void startEnergyScan(in Map properties, ILowpanEnergyScanCallback listener); - oneway void stopEnergyScan(); - - void addOnMeshPrefix(in IpPrefix prefix, int flags); - oneway void removeOnMeshPrefix(in IpPrefix prefix); - - void addExternalRoute(in IpPrefix prefix, int flags); - oneway void removeExternalRoute(in IpPrefix prefix); -} diff --git a/lowpan/java/android/net/lowpan/ILowpanInterfaceListener.aidl b/lowpan/java/android/net/lowpan/ILowpanInterfaceListener.aidl deleted file mode 100644 index 5e4049a0fab8..000000000000 --- a/lowpan/java/android/net/lowpan/ILowpanInterfaceListener.aidl +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.net.IpPrefix; -import android.net.lowpan.LowpanIdentity; - -/** {@hide} */ -interface ILowpanInterfaceListener { - oneway void onEnabledChanged(boolean value); - - oneway void onConnectedChanged(boolean value); - - oneway void onUpChanged(boolean value); - - oneway void onRoleChanged(@utf8InCpp String value); - - oneway void onStateChanged(@utf8InCpp String value); - - oneway void onLowpanIdentityChanged(in LowpanIdentity value); - - oneway void onLinkNetworkAdded(in IpPrefix value); - - oneway void onLinkNetworkRemoved(in IpPrefix value); - - oneway void onLinkAddressAdded(@utf8InCpp String value); - - oneway void onLinkAddressRemoved(@utf8InCpp String value); - - oneway void onReceiveFromCommissioner(in byte[] packet); -} diff --git a/lowpan/java/android/net/lowpan/ILowpanManager.aidl b/lowpan/java/android/net/lowpan/ILowpanManager.aidl deleted file mode 100644 index 326aa65e0fef..000000000000 --- a/lowpan/java/android/net/lowpan/ILowpanManager.aidl +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; -import android.net.lowpan.ILowpanInterface; -import android.net.lowpan.ILowpanManagerListener; - -/** {@hide} */ -interface ILowpanManager { - - /* Keep this in sync with Context.LOWPAN_SERVICE */ - const String LOWPAN_SERVICE_NAME = "lowpan"; - - ILowpanInterface getInterface(@utf8InCpp String name); - - @utf8InCpp String[] getInterfaceList(); - - void addListener(ILowpanManagerListener listener); - void removeListener(ILowpanManagerListener listener); - - void addInterface(ILowpanInterface lowpan_interface); - void removeInterface(ILowpanInterface lowpan_interface); -} diff --git a/lowpan/java/android/net/lowpan/ILowpanManagerListener.aidl b/lowpan/java/android/net/lowpan/ILowpanManagerListener.aidl deleted file mode 100644 index d4846f6740b9..000000000000 --- a/lowpan/java/android/net/lowpan/ILowpanManagerListener.aidl +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.net.lowpan.ILowpanInterface; - -/** {@hide} */ -interface ILowpanManagerListener { - oneway void onInterfaceAdded(ILowpanInterface lowpanInterface); - oneway void onInterfaceRemoved(ILowpanInterface lowpanInterface); -} diff --git a/lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl b/lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl deleted file mode 100644 index 9743fce0b128..000000000000 --- a/lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.net.lowpan.LowpanBeaconInfo; - -/** {@hide} */ -interface ILowpanNetScanCallback { - oneway void onNetScanBeacon(in LowpanBeaconInfo beacon); - oneway void onNetScanFinished(); -} diff --git a/lowpan/java/android/net/lowpan/InterfaceDisabledException.java b/lowpan/java/android/net/lowpan/InterfaceDisabledException.java deleted file mode 100644 index e917d4521bae..000000000000 --- a/lowpan/java/android/net/lowpan/InterfaceDisabledException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -/** - * Exception indicating this operation requires the interface to be enabled. - * - * @see LowpanInterface - * @hide - */ -// @SystemApi -public class InterfaceDisabledException extends LowpanException { - - public InterfaceDisabledException() {} - - public InterfaceDisabledException(String message) { - super(message); - } - - public InterfaceDisabledException(String message, Throwable cause) { - super(message, cause); - } - - protected InterfaceDisabledException(Exception cause) { - super(cause); - } -} diff --git a/lowpan/java/android/net/lowpan/JoinFailedAtAuthException.java b/lowpan/java/android/net/lowpan/JoinFailedAtAuthException.java deleted file mode 100644 index 7aceb71e2a85..000000000000 --- a/lowpan/java/android/net/lowpan/JoinFailedAtAuthException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -/** - * Exception indicating the join operation was unable to find the given network. - * - * @see LowpanInterface - * @hide - */ -// @SystemApi -public class JoinFailedAtAuthException extends JoinFailedException { - - public JoinFailedAtAuthException() {} - - public JoinFailedAtAuthException(String message) { - super(message); - } - - public JoinFailedAtAuthException(String message, Throwable cause) { - super(message, cause); - } - - public JoinFailedAtAuthException(Exception cause) { - super(cause); - } -} diff --git a/lowpan/java/android/net/lowpan/JoinFailedAtScanException.java b/lowpan/java/android/net/lowpan/JoinFailedAtScanException.java deleted file mode 100644 index a4346f98d719..000000000000 --- a/lowpan/java/android/net/lowpan/JoinFailedAtScanException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -/** - * Exception indicating the join operation was unable to find the given network. - * - * @see LowpanInterface - * @hide - */ -// @SystemApi -public class JoinFailedAtScanException extends JoinFailedException { - - public JoinFailedAtScanException() {} - - public JoinFailedAtScanException(String message) { - super(message); - } - - public JoinFailedAtScanException(String message, Throwable cause) { - super(message, cause); - } - - public JoinFailedAtScanException(Exception cause) { - super(cause); - } -} diff --git a/lowpan/java/android/net/lowpan/JoinFailedException.java b/lowpan/java/android/net/lowpan/JoinFailedException.java deleted file mode 100644 index e51d3829f9f1..000000000000 --- a/lowpan/java/android/net/lowpan/JoinFailedException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -/** - * Exception indicating the join operation has failed. - * - * @see LowpanInterface - * @hide - */ -// @SystemApi -public class JoinFailedException extends LowpanException { - - public JoinFailedException() {} - - public JoinFailedException(String message) { - super(message); - } - - public JoinFailedException(String message, Throwable cause) { - super(message, cause); - } - - protected JoinFailedException(Exception cause) { - super(cause); - } -} diff --git a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl deleted file mode 100644 index 9464fea02d18..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -parcelable LowpanBeaconInfo cpp_header "android/net/lowpan/LowpanBeaconInfo.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java b/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java deleted file mode 100644 index 5d4a3a0cb9d6..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanBeaconInfo.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.os.Parcel; -import android.os.Parcelable; -import com.android.internal.util.HexDump; -import java.util.Arrays; -import java.util.Collection; -import java.util.Objects; -import java.util.TreeSet; - -/** - * Describes a LoWPAN Beacon - * - * @hide - */ -// @SystemApi -public class LowpanBeaconInfo implements Parcelable { - public static final int UNKNOWN_RSSI = Integer.MAX_VALUE; - public static final int UNKNOWN_LQI = 0; - - private LowpanIdentity mIdentity; - private int mRssi = UNKNOWN_RSSI; - private int mLqi = UNKNOWN_LQI; - private byte[] mBeaconAddress = null; - private final TreeSet<Integer> mFlags = new TreeSet<>(); - - public static final int FLAG_CAN_ASSIST = 1; - - /** @hide */ - public static class Builder { - final LowpanIdentity.Builder mIdentityBuilder = new LowpanIdentity.Builder(); - final LowpanBeaconInfo mBeaconInfo = new LowpanBeaconInfo(); - - public Builder setLowpanIdentity(LowpanIdentity x) { - mIdentityBuilder.setLowpanIdentity(x); - return this; - } - - public Builder setName(String x) { - mIdentityBuilder.setName(x); - return this; - } - - public Builder setXpanid(byte x[]) { - mIdentityBuilder.setXpanid(x); - return this; - } - - public Builder setPanid(int x) { - mIdentityBuilder.setPanid(x); - return this; - } - - public Builder setChannel(int x) { - mIdentityBuilder.setChannel(x); - return this; - } - - public Builder setType(String x) { - mIdentityBuilder.setType(x); - return this; - } - - public Builder setRssi(int x) { - mBeaconInfo.mRssi = x; - return this; - } - - public Builder setLqi(int x) { - mBeaconInfo.mLqi = x; - return this; - } - - public Builder setBeaconAddress(byte x[]) { - mBeaconInfo.mBeaconAddress = (x != null ? x.clone() : null); - return this; - } - - public Builder setFlag(int x) { - mBeaconInfo.mFlags.add(x); - return this; - } - - public Builder setFlags(Collection<Integer> x) { - mBeaconInfo.mFlags.addAll(x); - return this; - } - - public LowpanBeaconInfo build() { - mBeaconInfo.mIdentity = mIdentityBuilder.build(); - if (mBeaconInfo.mBeaconAddress == null) { - mBeaconInfo.mBeaconAddress = new byte[0]; - } - return mBeaconInfo; - } - } - - private LowpanBeaconInfo() {} - - public LowpanIdentity getLowpanIdentity() { - return mIdentity; - } - - public int getRssi() { - return mRssi; - } - - public int getLqi() { - return mLqi; - } - - public byte[] getBeaconAddress() { - return mBeaconAddress.clone(); - } - - public Collection<Integer> getFlags() { - return (Collection<Integer>) mFlags.clone(); - } - - public boolean isFlagSet(int flag) { - return mFlags.contains(flag); - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - - sb.append(mIdentity.toString()); - - if (mRssi != UNKNOWN_RSSI) { - sb.append(", RSSI:").append(mRssi).append("dBm"); - } - - if (mLqi != UNKNOWN_LQI) { - sb.append(", LQI:").append(mLqi); - } - - if (mBeaconAddress.length > 0) { - sb.append(", BeaconAddress:").append(HexDump.toHexString(mBeaconAddress)); - } - - for (Integer flag : mFlags) { - switch (flag.intValue()) { - case FLAG_CAN_ASSIST: - sb.append(", CAN_ASSIST"); - break; - default: - sb.append(", FLAG_").append(Integer.toHexString(flag)); - break; - } - } - - return sb.toString(); - } - - @Override - public int hashCode() { - return Objects.hash(mIdentity, mRssi, mLqi, Arrays.hashCode(mBeaconAddress), mFlags); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof LowpanBeaconInfo)) { - return false; - } - LowpanBeaconInfo rhs = (LowpanBeaconInfo) obj; - return mIdentity.equals(rhs.mIdentity) - && Arrays.equals(mBeaconAddress, rhs.mBeaconAddress) - && mRssi == rhs.mRssi - && mLqi == rhs.mLqi - && mFlags.equals(rhs.mFlags); - } - - /** Implement the Parcelable interface. */ - @Override - public int describeContents() { - return 0; - } - - /** Implement the Parcelable interface. */ - @Override - public void writeToParcel(Parcel dest, int flags) { - mIdentity.writeToParcel(dest, flags); - dest.writeInt(mRssi); - dest.writeInt(mLqi); - dest.writeByteArray(mBeaconAddress); - - dest.writeInt(mFlags.size()); - for (Integer val : mFlags) { - dest.writeInt(val); - } - } - - /** Implement the Parcelable interface. */ - public static final @android.annotation.NonNull Creator<LowpanBeaconInfo> CREATOR = - new Creator<LowpanBeaconInfo>() { - public LowpanBeaconInfo createFromParcel(Parcel in) { - Builder builder = new Builder(); - - builder.setLowpanIdentity(LowpanIdentity.CREATOR.createFromParcel(in)); - - builder.setRssi(in.readInt()); - builder.setLqi(in.readInt()); - - builder.setBeaconAddress(in.createByteArray()); - - for (int i = in.readInt(); i > 0; i--) { - builder.setFlag(in.readInt()); - } - - return builder.build(); - } - - public LowpanBeaconInfo[] newArray(int size) { - return new LowpanBeaconInfo[size]; - } - }; -} diff --git a/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl b/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl deleted file mode 100644 index 0676deb6c6df..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanChannelInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -parcelable LowpanChannelInfo cpp_header "android/net/lowpan/LowpanChannelInfo.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanChannelInfo.java b/lowpan/java/android/net/lowpan/LowpanChannelInfo.java deleted file mode 100644 index 12c98b61c49e..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanChannelInfo.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.os.Parcel; -import android.os.Parcelable; -import java.util.Objects; - -/** - * Provides detailed information about a given channel. - * - * @hide - */ -// @SystemApi -public class LowpanChannelInfo implements Parcelable { - - public static final int UNKNOWN_POWER = Integer.MAX_VALUE; - public static final float UNKNOWN_FREQUENCY = 0.0f; - public static final float UNKNOWN_BANDWIDTH = 0.0f; - - private int mIndex = 0; - private String mName = null; - private float mSpectrumCenterFrequency = UNKNOWN_FREQUENCY; - private float mSpectrumBandwidth = UNKNOWN_BANDWIDTH; - private int mMaxTransmitPower = UNKNOWN_POWER; - private boolean mIsMaskedByRegulatoryDomain = false; - - /** @hide */ - public static LowpanChannelInfo getChannelInfoForIeee802154Page0(int index) { - LowpanChannelInfo info = new LowpanChannelInfo(); - - if (index < 0) { - info = null; - - } else if (index == 0) { - info.mSpectrumCenterFrequency = 868300000.0f; - info.mSpectrumBandwidth = 600000.0f; - - } else if (index < 11) { - info.mSpectrumCenterFrequency = 906000000.0f - (2000000.0f * 1) + 2000000.0f * (index); - info.mSpectrumBandwidth = 0; // Unknown - - } else if (index < 26) { - info.mSpectrumCenterFrequency = - 2405000000.0f - (5000000.0f * 11) + 5000000.0f * (index); - info.mSpectrumBandwidth = 2000000.0f; - - } else { - info = null; - } - - info.mName = Integer.toString(index); - - return info; - } - - private LowpanChannelInfo() {} - - private LowpanChannelInfo(int index, String name, float cf, float bw) { - mIndex = index; - mName = name; - mSpectrumCenterFrequency = cf; - mSpectrumBandwidth = bw; - } - - public String getName() { - return mName; - } - - public int getIndex() { - return mIndex; - } - - public int getMaxTransmitPower() { - return mMaxTransmitPower; - } - - public boolean isMaskedByRegulatoryDomain() { - return mIsMaskedByRegulatoryDomain; - } - - public float getSpectrumCenterFrequency() { - return mSpectrumCenterFrequency; - } - - public float getSpectrumBandwidth() { - return mSpectrumBandwidth; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - - sb.append("Channel ").append(mIndex); - - if (mName != null && !mName.equals(Integer.toString(mIndex))) { - sb.append(" (").append(mName).append(")"); - } - - if (mSpectrumCenterFrequency > 0.0f) { - if (mSpectrumCenterFrequency > 1000000000.0f) { - sb.append(", SpectrumCenterFrequency: ") - .append(mSpectrumCenterFrequency / 1000000000.0f) - .append("GHz"); - } else if (mSpectrumCenterFrequency > 1000000.0f) { - sb.append(", SpectrumCenterFrequency: ") - .append(mSpectrumCenterFrequency / 1000000.0f) - .append("MHz"); - } else { - sb.append(", SpectrumCenterFrequency: ") - .append(mSpectrumCenterFrequency / 1000.0f) - .append("kHz"); - } - } - - if (mSpectrumBandwidth > 0.0f) { - if (mSpectrumBandwidth > 1000000000.0f) { - sb.append(", SpectrumBandwidth: ") - .append(mSpectrumBandwidth / 1000000000.0f) - .append("GHz"); - } else if (mSpectrumBandwidth > 1000000.0f) { - sb.append(", SpectrumBandwidth: ") - .append(mSpectrumBandwidth / 1000000.0f) - .append("MHz"); - } else { - sb.append(", SpectrumBandwidth: ") - .append(mSpectrumBandwidth / 1000.0f) - .append("kHz"); - } - } - - if (mMaxTransmitPower != UNKNOWN_POWER) { - sb.append(", MaxTransmitPower: ").append(mMaxTransmitPower).append("dBm"); - } - - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof LowpanChannelInfo)) { - return false; - } - LowpanChannelInfo rhs = (LowpanChannelInfo) obj; - return Objects.equals(mName, rhs.mName) - && mIndex == rhs.mIndex - && mIsMaskedByRegulatoryDomain == rhs.mIsMaskedByRegulatoryDomain - && mSpectrumCenterFrequency == rhs.mSpectrumCenterFrequency - && mSpectrumBandwidth == rhs.mSpectrumBandwidth - && mMaxTransmitPower == rhs.mMaxTransmitPower; - } - - @Override - public int hashCode() { - return Objects.hash( - mName, - mIndex, - mIsMaskedByRegulatoryDomain, - mSpectrumCenterFrequency, - mSpectrumBandwidth, - mMaxTransmitPower); - } - - /** Implement the Parcelable interface. */ - @Override - public int describeContents() { - return 0; - } - - /** Implement the Parcelable interface. */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mIndex); - dest.writeString(mName); - dest.writeFloat(mSpectrumCenterFrequency); - dest.writeFloat(mSpectrumBandwidth); - dest.writeInt(mMaxTransmitPower); - dest.writeBoolean(mIsMaskedByRegulatoryDomain); - } - - /** Implement the Parcelable interface. */ - public static final @android.annotation.NonNull Creator<LowpanChannelInfo> CREATOR = - new Creator<LowpanChannelInfo>() { - - public LowpanChannelInfo createFromParcel(Parcel in) { - LowpanChannelInfo info = new LowpanChannelInfo(); - - info.mIndex = in.readInt(); - info.mName = in.readString(); - info.mSpectrumCenterFrequency = in.readFloat(); - info.mSpectrumBandwidth = in.readFloat(); - info.mMaxTransmitPower = in.readInt(); - info.mIsMaskedByRegulatoryDomain = in.readBoolean(); - - return info; - } - - public LowpanChannelInfo[] newArray(int size) { - return new LowpanChannelInfo[size]; - } - }; -} diff --git a/lowpan/java/android/net/lowpan/LowpanCommissioningSession.java b/lowpan/java/android/net/lowpan/LowpanCommissioningSession.java deleted file mode 100644 index 8f75e8db6243..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanCommissioningSession.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.IpPrefix; -import android.os.DeadObjectException; -import android.os.Handler; -import android.os.Looper; -import android.os.RemoteException; - -/** - * Commissioning Session. - * - * <p>This class enables a device to learn the credential needed to join a network using a technique - * called "in-band commissioning". - * - * @hide - */ -// @SystemApi -public class LowpanCommissioningSession { - - private final ILowpanInterface mBinder; - private final LowpanBeaconInfo mBeaconInfo; - private final ILowpanInterfaceListener mInternalCallback = new InternalCallback(); - private final Looper mLooper; - private Handler mHandler; - private Callback mCallback = null; - private volatile boolean mIsClosed = false; - - /** - * Callback base class for {@link LowpanCommissioningSession} - * - * @hide - */ - // @SystemApi - public abstract static class Callback { - public void onReceiveFromCommissioner(@NonNull byte[] packet) {}; - - public void onClosed() {}; - } - - private class InternalCallback extends ILowpanInterfaceListener.Stub { - @Override - public void onStateChanged(String value) { - if (!mIsClosed) { - switch (value) { - case ILowpanInterface.STATE_OFFLINE: - case ILowpanInterface.STATE_FAULT: - synchronized (LowpanCommissioningSession.this) { - lockedCleanup(); - } - } - } - } - - @Override - public void onReceiveFromCommissioner(byte[] packet) { - mHandler.post( - () -> { - synchronized (LowpanCommissioningSession.this) { - if (!mIsClosed && (mCallback != null)) { - mCallback.onReceiveFromCommissioner(packet); - } - } - }); - } - - // We ignore all other callbacks. - @Override - public void onEnabledChanged(boolean value) {} - - @Override - public void onConnectedChanged(boolean value) {} - - @Override - public void onUpChanged(boolean value) {} - - @Override - public void onRoleChanged(String value) {} - - @Override - public void onLowpanIdentityChanged(LowpanIdentity value) {} - - @Override - public void onLinkNetworkAdded(IpPrefix value) {} - - @Override - public void onLinkNetworkRemoved(IpPrefix value) {} - - @Override - public void onLinkAddressAdded(String value) {} - - @Override - public void onLinkAddressRemoved(String value) {} - } - - LowpanCommissioningSession( - ILowpanInterface binder, LowpanBeaconInfo beaconInfo, Looper looper) { - mBinder = binder; - mBeaconInfo = beaconInfo; - mLooper = looper; - - if (mLooper != null) { - mHandler = new Handler(mLooper); - } else { - mHandler = new Handler(); - } - - try { - mBinder.addListener(mInternalCallback); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - private void lockedCleanup() { - // Note: this method is only called from synchronized contexts. - - if (!mIsClosed) { - try { - mBinder.removeListener(mInternalCallback); - - } catch (DeadObjectException x) { - /* We don't care if we receive a DOE at this point. - * DOE is as good as success as far as we are concerned. - */ - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - - if (mCallback != null) { - mHandler.post(() -> mCallback.onClosed()); - } - } - - mCallback = null; - mIsClosed = true; - } - - /** TODO: doc */ - @NonNull - public LowpanBeaconInfo getBeaconInfo() { - return mBeaconInfo; - } - - /** TODO: doc */ - public void sendToCommissioner(@NonNull byte[] packet) { - if (!mIsClosed) { - try { - mBinder.sendToCommissioner(packet); - - } catch (DeadObjectException x) { - /* This method is a best-effort delivery. - * We don't care if we receive a DOE at this point. - */ - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - } - - /** TODO: doc */ - public synchronized void setCallback(@Nullable Callback cb, @Nullable Handler handler) { - if (!mIsClosed) { - /* This class can be created with or without a default looper. - * Also, this method can be called with or without a specific - * handler. If a handler is specified, it is to always be used. - * Otherwise, if there was a Looper specified when this object - * was created, we create a new handle based on that looper. - * Otherwise we just create a default handler object. Since we - * don't really know how the previous handler was created, we - * end up always replacing it here. This isn't a huge problem - * because this method should be called infrequently. - */ - if (handler != null) { - mHandler = handler; - } else if (mLooper != null) { - mHandler = new Handler(mLooper); - } else { - mHandler = new Handler(); - } - mCallback = cb; - } - } - - /** TODO: doc */ - public synchronized void close() { - if (!mIsClosed) { - try { - mBinder.closeCommissioningSession(); - - lockedCleanup(); - - } catch (DeadObjectException x) { - /* We don't care if we receive a DOE at this point. - * DOE is as good as success as far as we are concerned. - */ - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - } -} diff --git a/lowpan/java/android/net/lowpan/LowpanCredential.aidl b/lowpan/java/android/net/lowpan/LowpanCredential.aidl deleted file mode 100644 index af0c2d63474a..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanCredential.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -parcelable LowpanCredential cpp_header "android/net/lowpan/LowpanCredential.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanCredential.java b/lowpan/java/android/net/lowpan/LowpanCredential.java deleted file mode 100644 index dcbb83128f84..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanCredential.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.os.Parcel; -import android.os.Parcelable; -import com.android.internal.util.HexDump; -import java.util.Arrays; -import java.util.Objects; - -/** - * Describes a credential for a LoWPAN network. - * - * @hide - */ -// @SystemApi -public class LowpanCredential implements Parcelable { - - public static final int UNSPECIFIED_KEY_INDEX = 0; - - private byte[] mMasterKey = null; - private int mMasterKeyIndex = UNSPECIFIED_KEY_INDEX; - - LowpanCredential() {} - - private LowpanCredential(byte[] masterKey, int keyIndex) { - setMasterKey(masterKey, keyIndex); - } - - private LowpanCredential(byte[] masterKey) { - setMasterKey(masterKey); - } - - public static LowpanCredential createMasterKey(byte[] masterKey) { - return new LowpanCredential(masterKey); - } - - public static LowpanCredential createMasterKey(byte[] masterKey, int keyIndex) { - return new LowpanCredential(masterKey, keyIndex); - } - - void setMasterKey(byte[] masterKey) { - if (masterKey != null) { - masterKey = masterKey.clone(); - } - mMasterKey = masterKey; - } - - void setMasterKeyIndex(int keyIndex) { - mMasterKeyIndex = keyIndex; - } - - void setMasterKey(byte[] masterKey, int keyIndex) { - setMasterKey(masterKey); - setMasterKeyIndex(keyIndex); - } - - public byte[] getMasterKey() { - if (mMasterKey != null) { - return mMasterKey.clone(); - } - return null; - } - - public int getMasterKeyIndex() { - return mMasterKeyIndex; - } - - public boolean isMasterKey() { - return mMasterKey != null; - } - - public String toSensitiveString() { - StringBuffer sb = new StringBuffer(); - - sb.append("<LowpanCredential"); - - if (isMasterKey()) { - sb.append(" MasterKey:").append(HexDump.toHexString(mMasterKey)); - if (mMasterKeyIndex != UNSPECIFIED_KEY_INDEX) { - sb.append(", Index:").append(mMasterKeyIndex); - } - } else { - sb.append(" empty"); - } - - sb.append(">"); - - return sb.toString(); - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - - sb.append("<LowpanCredential"); - - if (isMasterKey()) { - // We don't print out the contents of the key here, - // we only do that in toSensitiveString. - sb.append(" MasterKey"); - if (mMasterKeyIndex != UNSPECIFIED_KEY_INDEX) { - sb.append(", Index:").append(mMasterKeyIndex); - } - } else { - sb.append(" empty"); - } - - sb.append(">"); - - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof LowpanCredential)) { - return false; - } - LowpanCredential rhs = (LowpanCredential) obj; - return Arrays.equals(mMasterKey, rhs.mMasterKey) && mMasterKeyIndex == rhs.mMasterKeyIndex; - } - - @Override - public int hashCode() { - return Objects.hash(Arrays.hashCode(mMasterKey), mMasterKeyIndex); - } - - /** Implement the Parcelable interface. */ - @Override - public int describeContents() { - return 0; - } - - /** Implement the Parcelable interface. */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeByteArray(mMasterKey); - dest.writeInt(mMasterKeyIndex); - } - - /** Implement the Parcelable interface. */ - public static final @android.annotation.NonNull Creator<LowpanCredential> CREATOR = - new Creator<LowpanCredential>() { - - public LowpanCredential createFromParcel(Parcel in) { - LowpanCredential credential = new LowpanCredential(); - - credential.mMasterKey = in.createByteArray(); - credential.mMasterKeyIndex = in.readInt(); - - return credential; - } - - public LowpanCredential[] newArray(int size) { - return new LowpanCredential[size]; - } - }; -} diff --git a/lowpan/java/android/net/lowpan/LowpanEnergyScanResult.java b/lowpan/java/android/net/lowpan/LowpanEnergyScanResult.java deleted file mode 100644 index da87752008c9..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanEnergyScanResult.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -/** - * Describes the result from one channel of an energy scan. - * - * @hide - */ -// @SystemApi -public class LowpanEnergyScanResult { - public static final int UNKNOWN = Integer.MAX_VALUE; - - private int mChannel = UNKNOWN; - private int mMaxRssi = UNKNOWN; - - LowpanEnergyScanResult() {} - - public int getChannel() { - return mChannel; - } - - public int getMaxRssi() { - return mMaxRssi; - } - - void setChannel(int x) { - mChannel = x; - } - - void setMaxRssi(int x) { - mMaxRssi = x; - } - - @Override - public String toString() { - return "LowpanEnergyScanResult(channel: " + mChannel + ", maxRssi:" + mMaxRssi + ")"; - } -} diff --git a/lowpan/java/android/net/lowpan/LowpanException.java b/lowpan/java/android/net/lowpan/LowpanException.java deleted file mode 100644 index 5dfce48d3f17..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanException.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.os.ServiceSpecificException; -import android.util.AndroidException; - -/** - * <code>LowpanException</code> is thrown if an action to a LoWPAN interface could not be performed - * or a LoWPAN interface property could not be fetched or changed. - * - * @see LowpanInterface - * @hide - */ -// @SystemApi -public class LowpanException extends AndroidException { - public LowpanException() {} - - public LowpanException(String message) { - super(message); - } - - public LowpanException(String message, Throwable cause) { - super(message, cause); - } - - public LowpanException(Exception cause) { - super(cause); - } - - /* This method returns LowpanException so that the caller - * can add "throw" before the invocation of this method. - * This might seem superfluous, but it is actually to - * help provide a hint to the java compiler that this - * function will not return. - */ - static LowpanException rethrowFromServiceSpecificException(ServiceSpecificException e) - throws LowpanException { - switch (e.errorCode) { - case ILowpanInterface.ERROR_DISABLED: - throw new InterfaceDisabledException(e); - - case ILowpanInterface.ERROR_WRONG_STATE: - throw new WrongStateException(e); - - case ILowpanInterface.ERROR_CANCELED: - throw new OperationCanceledException(e); - - case ILowpanInterface.ERROR_JOIN_FAILED_UNKNOWN: - throw new JoinFailedException(e); - - case ILowpanInterface.ERROR_JOIN_FAILED_AT_SCAN: - throw new JoinFailedAtScanException(e); - - case ILowpanInterface.ERROR_JOIN_FAILED_AT_AUTH: - throw new JoinFailedAtAuthException(e); - - case ILowpanInterface.ERROR_FORM_FAILED_AT_SCAN: - throw new NetworkAlreadyExistsException(e); - - case ILowpanInterface.ERROR_FEATURE_NOT_SUPPORTED: - throw new LowpanException( - e.getMessage() != null ? e.getMessage() : "Feature not supported", e); - - case ILowpanInterface.ERROR_NCP_PROBLEM: - throw new LowpanRuntimeException( - e.getMessage() != null ? e.getMessage() : "NCP problem", e); - - case ILowpanInterface.ERROR_INVALID_ARGUMENT: - throw new LowpanRuntimeException( - e.getMessage() != null ? e.getMessage() : "Invalid argument", e); - - case ILowpanInterface.ERROR_UNSPECIFIED: - default: - throw new LowpanRuntimeException(e); - } - } -} diff --git a/lowpan/java/android/net/lowpan/LowpanIdentity.aidl b/lowpan/java/android/net/lowpan/LowpanIdentity.aidl deleted file mode 100644 index fcef98f5c496..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanIdentity.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -parcelable LowpanIdentity cpp_header "android/net/lowpan/LowpanIdentity.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanIdentity.java b/lowpan/java/android/net/lowpan/LowpanIdentity.java deleted file mode 100644 index 1997bc4a4635..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanIdentity.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.annotation.NonNull; -import android.icu.text.StringPrep; -import android.icu.text.StringPrepParseException; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; -import com.android.internal.util.HexDump; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Objects; - -/** - * Describes an instance of a LoWPAN network. - * - * @hide - */ -// @SystemApi -public class LowpanIdentity implements Parcelable { - private static final String TAG = LowpanIdentity.class.getSimpleName(); - - // Constants - public static final int UNSPECIFIED_CHANNEL = -1; - public static final int UNSPECIFIED_PANID = 0xFFFFFFFF; - // Builder - - /** @hide */ - // @SystemApi - public static class Builder { - private static final StringPrep stringPrep = - StringPrep.getInstance(StringPrep.RFC3920_RESOURCEPREP); - - final LowpanIdentity mIdentity = new LowpanIdentity(); - - private static String escape(@NonNull byte[] bytes) { - StringBuffer sb = new StringBuffer(); - for (byte b : bytes) { - if (b >= 32 && b <= 126) { - sb.append((char) b); - } else { - sb.append(String.format("\\0x%02x", b & 0xFF)); - } - } - return sb.toString(); - } - - public Builder setLowpanIdentity(@NonNull LowpanIdentity x) { - Objects.requireNonNull(x); - setRawName(x.getRawName()); - setXpanid(x.getXpanid()); - setPanid(x.getPanid()); - setChannel(x.getChannel()); - setType(x.getType()); - return this; - } - - public Builder setName(@NonNull String name) { - Objects.requireNonNull(name); - try { - mIdentity.mName = stringPrep.prepare(name, StringPrep.DEFAULT); - mIdentity.mRawName = mIdentity.mName.getBytes(StandardCharsets.UTF_8); - mIdentity.mIsNameValid = true; - } catch (StringPrepParseException x) { - Log.w(TAG, x.toString()); - setRawName(name.getBytes(StandardCharsets.UTF_8)); - } - return this; - } - - public Builder setRawName(@NonNull byte[] name) { - Objects.requireNonNull(name); - mIdentity.mRawName = name.clone(); - mIdentity.mName = new String(name, StandardCharsets.UTF_8); - try { - String nameCheck = stringPrep.prepare(mIdentity.mName, StringPrep.DEFAULT); - mIdentity.mIsNameValid = - Arrays.equals(nameCheck.getBytes(StandardCharsets.UTF_8), name); - } catch (StringPrepParseException x) { - Log.w(TAG, x.toString()); - mIdentity.mIsNameValid = false; - } - - // Non-normal names must be rendered differently to avoid confusion. - if (!mIdentity.mIsNameValid) { - mIdentity.mName = "«" + escape(name) + "»"; - } - - return this; - } - - public Builder setXpanid(byte x[]) { - mIdentity.mXpanid = (x != null ? x.clone() : null); - return this; - } - - public Builder setPanid(int x) { - mIdentity.mPanid = x; - return this; - } - - public Builder setType(@NonNull String x) { - mIdentity.mType = x; - return this; - } - - public Builder setChannel(int x) { - mIdentity.mChannel = x; - return this; - } - - public LowpanIdentity build() { - return mIdentity; - } - } - - LowpanIdentity() {} - - // Instance Variables - - private String mName = ""; - private boolean mIsNameValid = true; - private byte[] mRawName = new byte[0]; - private String mType = ""; - private byte[] mXpanid = new byte[0]; - private int mPanid = UNSPECIFIED_PANID; - private int mChannel = UNSPECIFIED_CHANNEL; - - // Public Getters - - public String getName() { - return mName; - } - - public boolean isNameValid() { - return mIsNameValid; - } - - public byte[] getRawName() { - return mRawName.clone(); - } - - public byte[] getXpanid() { - return mXpanid.clone(); - } - - public int getPanid() { - return mPanid; - } - - public String getType() { - return mType; - } - - public int getChannel() { - return mChannel; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - - sb.append("Name:").append(getName()); - - if (mType.length() > 0) { - sb.append(", Type:").append(mType); - } - - if (mXpanid.length > 0) { - sb.append(", XPANID:").append(HexDump.toHexString(mXpanid)); - } - - if (mPanid != UNSPECIFIED_PANID) { - sb.append(", PANID:").append(String.format("0x%04X", mPanid)); - } - - if (mChannel != UNSPECIFIED_CHANNEL) { - sb.append(", Channel:").append(mChannel); - } - - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof LowpanIdentity)) { - return false; - } - LowpanIdentity rhs = (LowpanIdentity) obj; - return Arrays.equals(mRawName, rhs.mRawName) - && Arrays.equals(mXpanid, rhs.mXpanid) - && mType.equals(rhs.mType) - && mPanid == rhs.mPanid - && mChannel == rhs.mChannel; - } - - @Override - public int hashCode() { - return Objects.hash( - Arrays.hashCode(mRawName), mType, Arrays.hashCode(mXpanid), mPanid, mChannel); - } - - /** Implement the Parcelable interface. */ - @Override - public int describeContents() { - return 0; - } - - /** Implement the Parcelable interface. */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeByteArray(mRawName); - dest.writeString(mType); - dest.writeByteArray(mXpanid); - dest.writeInt(mPanid); - dest.writeInt(mChannel); - } - - /** Implement the Parcelable interface. */ - public static final @android.annotation.NonNull Creator<LowpanIdentity> CREATOR = - new Creator<LowpanIdentity>() { - - public LowpanIdentity createFromParcel(Parcel in) { - Builder builder = new Builder(); - - builder.setRawName(in.createByteArray()); - builder.setType(in.readString()); - builder.setXpanid(in.createByteArray()); - builder.setPanid(in.readInt()); - builder.setChannel(in.readInt()); - - return builder.build(); - } - - public LowpanIdentity[] newArray(int size) { - return new LowpanIdentity[size]; - } - }; -} diff --git a/lowpan/java/android/net/lowpan/LowpanInterface.java b/lowpan/java/android/net/lowpan/LowpanInterface.java deleted file mode 100644 index 57e91357b237..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanInterface.java +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.os.DeadObjectException; -import android.os.Handler; -import android.os.Looper; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.util.Log; -import java.util.HashMap; - -/** - * Class for managing a specific Low-power Wireless Personal Area Network (LoWPAN) interface. - * - * @hide - */ -// @SystemApi -public class LowpanInterface { - private static final String TAG = LowpanInterface.class.getSimpleName(); - - /** Detached role. The interface is not currently attached to a network. */ - public static final String ROLE_DETACHED = ILowpanInterface.ROLE_DETACHED; - - /** End-device role. End devices do not route traffic for other nodes. */ - public static final String ROLE_END_DEVICE = ILowpanInterface.ROLE_END_DEVICE; - - /** Router role. Routers help route traffic around the mesh network. */ - public static final String ROLE_ROUTER = ILowpanInterface.ROLE_ROUTER; - - /** - * Sleepy End-Device role. - * - * <p>End devices with this role are nominally asleep, waking up periodically to check in with - * their parent to see if there are packets destined for them. Such devices are capable of - * extraordinarilly low power consumption, but packet latency can be on the order of dozens of - * seconds(depending on how the node is configured). - */ - public static final String ROLE_SLEEPY_END_DEVICE = ILowpanInterface.ROLE_SLEEPY_END_DEVICE; - - /** - * Sleepy-router role. - * - * <p>Routers with this role are nominally asleep, waking up periodically to check in with other - * routers and their children. - */ - public static final String ROLE_SLEEPY_ROUTER = ILowpanInterface.ROLE_SLEEPY_ROUTER; - - /** TODO: doc */ - public static final String ROLE_LEADER = ILowpanInterface.ROLE_LEADER; - - /** TODO: doc */ - public static final String ROLE_COORDINATOR = ILowpanInterface.ROLE_COORDINATOR; - - /** - * Offline state. - * - * <p>This is the initial state of the LoWPAN interface when the underlying driver starts. In - * this state the NCP is idle and not connected to any network. - * - * <p>This state can be explicitly entered by calling {@link #reset()}, {@link #leave()}, or - * <code>setUp(false)</code>, with the later two only working if we were not previously in the - * {@link #STATE_FAULT} state. - * - * @see #getState() - * @see #STATE_FAULT - */ - public static final String STATE_OFFLINE = ILowpanInterface.STATE_OFFLINE; - - /** - * Commissioning state. - * - * <p>The interface enters this state after a call to {@link #startCommissioningSession()}. This - * state may only be entered directly from the {@link #STATE_OFFLINE} state. - * - * @see #startCommissioningSession() - * @see #getState() - * @hide - */ - public static final String STATE_COMMISSIONING = ILowpanInterface.STATE_COMMISSIONING; - - /** - * Attaching state. - * - * <p>The interface enters this state when it starts the process of trying to find other nodes - * so that it can attach to any pre-existing network fragment, or when it is in the process of - * calculating the optimal values for unspecified parameters when forming a new network. - * - * <p>The interface may stay in this state for a prolonged period of time (or may spontaneously - * enter this state from {@link #STATE_ATTACHED}) if the underlying network technology is - * heirarchical (like ZigBeeIP) or if the device role is that of an "end-device" ({@link - * #ROLE_END_DEVICE} or {@link #ROLE_SLEEPY_END_DEVICE}). This is because such roles cannot - * create their own network fragments. - * - * @see #STATE_ATTACHED - * @see #getState() - */ - public static final String STATE_ATTACHING = ILowpanInterface.STATE_ATTACHING; - - /** - * Attached state. - * - * <p>The interface enters this state from {@link #STATE_ATTACHING} once it is actively - * participating on a network fragment. - * - * @see #STATE_ATTACHING - * @see #getState() - */ - public static final String STATE_ATTACHED = ILowpanInterface.STATE_ATTACHED; - - /** - * Fault state. - * - * <p>The interface will enter this state when the driver has detected some sort of problem from - * which it was not immediately able to recover. - * - * <p>This state can be entered spontaneously from any other state. Calling {@link #reset} will - * cause the device to return to the {@link #STATE_OFFLINE} state. - * - * @see #getState - * @see #STATE_OFFLINE - */ - public static final String STATE_FAULT = ILowpanInterface.STATE_FAULT; - - /** - * Network type for Thread 1.x networks. - * - * @see android.net.lowpan.LowpanIdentity#getType - * @see #getLowpanIdentity - * @hide - */ - public static final String NETWORK_TYPE_THREAD_V1 = ILowpanInterface.NETWORK_TYPE_THREAD_V1; - - public static final String EMPTY_PARTITION_ID = ""; - - /** - * Callback base class for LowpanInterface - * - * @hide - */ - // @SystemApi - public abstract static class Callback { - public void onConnectedChanged(boolean value) {} - - public void onEnabledChanged(boolean value) {} - - public void onUpChanged(boolean value) {} - - public void onRoleChanged(@NonNull String value) {} - - public void onStateChanged(@NonNull String state) {} - - public void onLowpanIdentityChanged(@NonNull LowpanIdentity value) {} - - public void onLinkNetworkAdded(IpPrefix prefix) {} - - public void onLinkNetworkRemoved(IpPrefix prefix) {} - - public void onLinkAddressAdded(LinkAddress address) {} - - public void onLinkAddressRemoved(LinkAddress address) {} - } - - private final ILowpanInterface mBinder; - private final Looper mLooper; - private final HashMap<Integer, ILowpanInterfaceListener> mListenerMap = new HashMap<>(); - - /** - * Create a new LowpanInterface instance. Applications will almost always want to use {@link - * LowpanManager#getInterface LowpanManager.getInterface()} instead of this. - * - * @param context the application context - * @param service the Binder interface - * @param looper the Binder interface - * @hide - */ - public LowpanInterface(Context context, ILowpanInterface service, Looper looper) { - /* We aren't currently using the context, but if we need - * it later on we can easily add it to the class. - */ - - mBinder = service; - mLooper = looper; - } - - /** - * Returns the ILowpanInterface object associated with this interface. - * - * @hide - */ - public ILowpanInterface getService() { - return mBinder; - } - - // Public Actions - - /** - * Form a new network with the given network information optional credential. Unspecified fields - * in the network information will be filled in with reasonable values. If the network - * credential is unspecified, one will be generated automatically. - * - * <p>This method will block until either the network was successfully formed or an error - * prevents the network form being formed. - * - * <p>Upon success, the interface will be up and attached to the newly formed network. - * - * @see #join(LowpanProvision) - */ - public void form(@NonNull LowpanProvision provision) throws LowpanException { - try { - mBinder.form(provision); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Attempts to join a new network with the given network information. This method will block - * until either the network was successfully joined or an error prevented the network from being - * formed. Upon success, the interface will be up and attached to the newly joined network. - * - * <p>Note that “joining” is distinct from “attaching”: Joining requires at least one other peer - * device to be present in order for the operation to complete successfully. - */ - public void join(@NonNull LowpanProvision provision) throws LowpanException { - try { - mBinder.join(provision); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Attaches to the network described by identity and credential. This is similar to {@link - * #join}, except that (assuming the identity and credential are valid) it will always succeed - * and provision the interface, even if there are no peers nearby. - * - * <p>This method will block execution until the operation has completed. - */ - public void attach(@NonNull LowpanProvision provision) throws LowpanException { - try { - mBinder.attach(provision); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Bring down the network interface and forget all non-volatile details about the current - * network. - * - * <p>This method will block execution until the operation has completed. - */ - public void leave() throws LowpanException { - try { - mBinder.leave(); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Start a new commissioning session. Will fail if the interface is attached to a network or if - * the interface is disabled. - */ - public @NonNull LowpanCommissioningSession startCommissioningSession( - @NonNull LowpanBeaconInfo beaconInfo) throws LowpanException { - try { - mBinder.startCommissioningSession(beaconInfo); - - return new LowpanCommissioningSession(mBinder, beaconInfo, mLooper); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Reset this network interface as if it has been power cycled. Will bring the network interface - * down if it was previously up. Will not erase any non-volatile settings. - * - * <p>This method will block execution until the operation has completed. - * - * @hide - */ - public void reset() throws LowpanException { - try { - mBinder.reset(); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - // Public Getters and Setters - - /** Returns the name of this network interface. */ - @NonNull - public String getName() { - try { - return mBinder.getName(); - - } catch (DeadObjectException x) { - return ""; - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** - * Indicates if the interface is enabled or disabled. - * - * @see #setEnabled - * @see android.net.lowpan.LowpanException#LOWPAN_DISABLED - */ - public boolean isEnabled() { - try { - return mBinder.isEnabled(); - - } catch (DeadObjectException x) { - return false; - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** - * Enables or disables the LoWPAN interface. When disabled, the interface is put into a - * low-power state and all commands that require the NCP to be queried will fail with {@link - * android.net.lowpan.LowpanException#LOWPAN_DISABLED}. - * - * @see #isEnabled - * @see android.net.lowpan.LowpanException#LOWPAN_DISABLED - * @hide - */ - public void setEnabled(boolean enabled) throws LowpanException { - try { - mBinder.setEnabled(enabled); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Indicates if the network interface is up or down. - * - * @hide - */ - public boolean isUp() { - try { - return mBinder.isUp(); - - } catch (DeadObjectException x) { - return false; - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** - * Indicates if there is at least one peer in range. - * - * @return <code>true</code> if we have at least one other peer in range, <code>false</code> - * otherwise. - */ - public boolean isConnected() { - try { - return mBinder.isConnected(); - - } catch (DeadObjectException x) { - return false; - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** - * Indicates if this interface is currently commissioned onto an existing network. If the - * interface is commissioned, the interface may be brought up using setUp(). - */ - public boolean isCommissioned() { - try { - return mBinder.isCommissioned(); - - } catch (DeadObjectException x) { - return false; - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** - * Get interface state - * - * <h3>State Diagram</h3> - * - * <img src="LowpanInterface-1.png" /> - * - * @return The current state of the interface. - * @see #STATE_OFFLINE - * @see #STATE_COMMISSIONING - * @see #STATE_ATTACHING - * @see #STATE_ATTACHED - * @see #STATE_FAULT - */ - public String getState() { - try { - return mBinder.getState(); - - } catch (DeadObjectException x) { - return STATE_FAULT; - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** Get network partition/fragment identifier. */ - public String getPartitionId() { - try { - return mBinder.getPartitionId(); - - } catch (DeadObjectException x) { - return EMPTY_PARTITION_ID; - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** TODO: doc */ - public LowpanIdentity getLowpanIdentity() { - try { - return mBinder.getLowpanIdentity(); - - } catch (DeadObjectException x) { - return new LowpanIdentity(); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** TODO: doc */ - @NonNull - public String getRole() { - try { - return mBinder.getRole(); - - } catch (DeadObjectException x) { - return ROLE_DETACHED; - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** TODO: doc */ - @Nullable - public LowpanCredential getLowpanCredential() { - try { - return mBinder.getLowpanCredential(); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - public @NonNull String[] getSupportedNetworkTypes() throws LowpanException { - try { - return mBinder.getSupportedNetworkTypes(); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - public @NonNull LowpanChannelInfo[] getSupportedChannels() throws LowpanException { - try { - return mBinder.getSupportedChannels(); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - // Listener Support - - /** - * Registers a subclass of {@link LowpanInterface.Callback} to receive events. - * - * @param cb Subclass of {@link LowpanInterface.Callback} which will receive events. - * @param handler If not <code>null</code>, events will be dispatched via the given handler - * object. If <code>null</code>, the thread upon which events will be dispatched is - * unspecified. - * @see #registerCallback(Callback) - * @see #unregisterCallback(Callback) - */ - public void registerCallback(@NonNull Callback cb, @Nullable Handler handler) { - ILowpanInterfaceListener.Stub listenerBinder = - new ILowpanInterfaceListener.Stub() { - private Handler mHandler; - - { - if (handler != null) { - mHandler = handler; - } else if (mLooper != null) { - mHandler = new Handler(mLooper); - } else { - mHandler = new Handler(); - } - } - - @Override - public void onEnabledChanged(boolean value) { - mHandler.post(() -> cb.onEnabledChanged(value)); - } - - @Override - public void onConnectedChanged(boolean value) { - mHandler.post(() -> cb.onConnectedChanged(value)); - } - - @Override - public void onUpChanged(boolean value) { - mHandler.post(() -> cb.onUpChanged(value)); - } - - @Override - public void onRoleChanged(String value) { - mHandler.post(() -> cb.onRoleChanged(value)); - } - - @Override - public void onStateChanged(String value) { - mHandler.post(() -> cb.onStateChanged(value)); - } - - @Override - public void onLowpanIdentityChanged(LowpanIdentity value) { - mHandler.post(() -> cb.onLowpanIdentityChanged(value)); - } - - @Override - public void onLinkNetworkAdded(IpPrefix value) { - mHandler.post(() -> cb.onLinkNetworkAdded(value)); - } - - @Override - public void onLinkNetworkRemoved(IpPrefix value) { - mHandler.post(() -> cb.onLinkNetworkRemoved(value)); - } - - @Override - public void onLinkAddressAdded(String value) { - LinkAddress la; - try { - la = new LinkAddress(value); - } catch (IllegalArgumentException x) { - Log.e( - TAG, - "onLinkAddressAdded: Bad LinkAddress \"" + value + "\", " + x); - return; - } - mHandler.post(() -> cb.onLinkAddressAdded(la)); - } - - @Override - public void onLinkAddressRemoved(String value) { - LinkAddress la; - try { - la = new LinkAddress(value); - } catch (IllegalArgumentException x) { - Log.e( - TAG, - "onLinkAddressRemoved: Bad LinkAddress \"" - + value - + "\", " - + x); - return; - } - mHandler.post(() -> cb.onLinkAddressRemoved(la)); - } - - @Override - public void onReceiveFromCommissioner(byte[] packet) { - // This is only used by the LowpanCommissioningSession. - } - }; - try { - mBinder.addListener(listenerBinder); - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - - synchronized (mListenerMap) { - mListenerMap.put(System.identityHashCode(cb), listenerBinder); - } - } - - /** - * Registers a subclass of {@link LowpanInterface.Callback} to receive events. - * - * <p>The thread upon which events will be dispatched is unspecified. - * - * @param cb Subclass of {@link LowpanInterface.Callback} which will receive events. - * @see #registerCallback(Callback, Handler) - * @see #unregisterCallback(Callback) - */ - public void registerCallback(Callback cb) { - registerCallback(cb, null); - } - - /** - * Unregisters a previously registered callback class. - * - * @param cb Subclass of {@link LowpanInterface.Callback} which was previously registered to - * receive events. - * @see #registerCallback(Callback, Handler) - * @see #registerCallback(Callback) - */ - public void unregisterCallback(Callback cb) { - int hashCode = System.identityHashCode(cb); - synchronized (mListenerMap) { - ILowpanInterfaceListener listenerBinder = mListenerMap.get(hashCode); - - if (listenerBinder != null) { - mListenerMap.remove(hashCode); - - try { - mBinder.removeListener(listenerBinder); - } catch (DeadObjectException x) { - // We ignore a dead object exception because that - // pretty clearly means our callback isn't registered. - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - } - } - - // Active and Passive Scanning - - /** - * Creates a new {@link android.net.lowpan.LowpanScanner} object for this interface. - * - * <p>This method allocates a new unique object for each call. - * - * @see android.net.lowpan.LowpanScanner - */ - public @NonNull LowpanScanner createScanner() { - return new LowpanScanner(mBinder); - } - - // Route Management - - /** - * Makes a copy of the internal list of LinkAddresses. - * - * @hide - */ - public LinkAddress[] getLinkAddresses() throws LowpanException { - try { - String[] linkAddressStrings = mBinder.getLinkAddresses(); - LinkAddress[] ret = new LinkAddress[linkAddressStrings.length]; - int i = 0; - for (String str : linkAddressStrings) { - ret[i++] = new LinkAddress(str); - } - return ret; - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Makes a copy of the internal list of networks reachable on via this link. - * - * @hide - */ - public IpPrefix[] getLinkNetworks() throws LowpanException { - try { - return mBinder.getLinkNetworks(); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Advertise the given IP prefix as an on-mesh prefix. - * - * @hide - */ - public void addOnMeshPrefix(IpPrefix prefix, int flags) throws LowpanException { - try { - mBinder.addOnMeshPrefix(prefix, flags); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Remove an IP prefix previously advertised by this device from the list of advertised on-mesh - * prefixes. - * - * @hide - */ - public void removeOnMeshPrefix(IpPrefix prefix) { - try { - mBinder.removeOnMeshPrefix(prefix); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - // Catch and ignore all service exceptions - Log.e(TAG, x.toString()); - } - } - - /** - * Advertise this device to other devices on the mesh network as having a specific route to the - * given network. This device will then receive forwarded traffic for that network. - * - * @hide - */ - public void addExternalRoute(IpPrefix prefix, int flags) throws LowpanException { - try { - mBinder.addExternalRoute(prefix, flags); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Revoke a previously advertised specific route to the given network. - * - * @hide - */ - public void removeExternalRoute(IpPrefix prefix) { - try { - mBinder.removeExternalRoute(prefix); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - // Catch and ignore all service exceptions - Log.e(TAG, x.toString()); - } - } -} diff --git a/lowpan/java/android/net/lowpan/LowpanManager.java b/lowpan/java/android/net/lowpan/LowpanManager.java deleted file mode 100644 index 33b35e6af7af..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanManager.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.RemoteException; -import android.os.ServiceManager; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.os.BackgroundThread; - -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.Map; -import java.util.WeakHashMap; - -/** - * Manager object for looking up LoWPAN interfaces. - * - * @hide - */ -// @SystemApi -public class LowpanManager { - private static final String TAG = LowpanManager.class.getSimpleName(); - - /** @hide */ - // @SystemApi - public abstract static class Callback { - public void onInterfaceAdded(LowpanInterface lowpanInterface) {} - - public void onInterfaceRemoved(LowpanInterface lowpanInterface) {} - } - - private final Map<Integer, ILowpanManagerListener> mListenerMap = new HashMap<>(); - private final Map<String, LowpanInterface> mInterfaceCache = new HashMap<>(); - - /* This is a WeakHashMap because we don't want to hold onto - * a strong reference to ILowpanInterface, so that it can be - * garbage collected if it isn't being used anymore. Since - * the value class holds onto this specific ILowpanInterface, - * we also need to have a weak reference to the value. - * This design pattern allows us to skip removal of items - * from this Map without leaking memory. - */ - private final Map<IBinder, WeakReference<LowpanInterface>> mBinderCache = - new WeakHashMap<>(); - - private final ILowpanManager mService; - private final Context mContext; - private final Looper mLooper; - - // Static Methods - - public static LowpanManager from(Context context) { - return (LowpanManager) context.getSystemService(Context.LOWPAN_SERVICE); - } - - /** @hide */ - public static LowpanManager getManager() { - IBinder binder = ServiceManager.getService(Context.LOWPAN_SERVICE); - - if (binder != null) { - ILowpanManager service = ILowpanManager.Stub.asInterface(binder); - return new LowpanManager(service); - } - - return null; - } - - // Constructors - - LowpanManager(ILowpanManager service) { - mService = service; - mContext = null; - mLooper = null; - } - - /** - * Create a new LowpanManager instance. Applications will almost always want to use {@link - * android.content.Context#getSystemService Context.getSystemService()} to retrieve the standard - * {@link android.content.Context#LOWPAN_SERVICE Context.LOWPAN_SERVICE}. - * - * @param context the application context - * @param service the Binder interface - * @hide - hide this because it takes in a parameter of type ILowpanManager, which is a system - * private class. - */ - public LowpanManager(Context context, ILowpanManager service) { - this(context, service, BackgroundThread.get().getLooper()); - } - - @VisibleForTesting - public LowpanManager(Context context, ILowpanManager service, Looper looper) { - mContext = context; - mService = service; - mLooper = looper; - } - - /** @hide */ - @Nullable - public LowpanInterface getInterfaceNoCreate(@NonNull ILowpanInterface ifaceService) { - LowpanInterface iface = null; - - synchronized (mBinderCache) { - if (mBinderCache.containsKey(ifaceService.asBinder())) { - iface = mBinderCache.get(ifaceService.asBinder()).get(); - } - } - - return iface; - } - - /** @hide */ - @Nullable - public LowpanInterface getInterface(@NonNull ILowpanInterface ifaceService) { - LowpanInterface iface = null; - - try { - synchronized (mBinderCache) { - if (mBinderCache.containsKey(ifaceService.asBinder())) { - iface = mBinderCache.get(ifaceService.asBinder()).get(); - } - - if (iface == null) { - String ifaceName = ifaceService.getName(); - - iface = new LowpanInterface(mContext, ifaceService, mLooper); - - synchronized (mInterfaceCache) { - mInterfaceCache.put(iface.getName(), iface); - } - - mBinderCache.put(ifaceService.asBinder(), new WeakReference(iface)); - - /* Make sure we remove the object from the - * interface cache if the associated service - * dies. - */ - ifaceService - .asBinder() - .linkToDeath( - new IBinder.DeathRecipient() { - @Override - public void binderDied() { - synchronized (mInterfaceCache) { - LowpanInterface iface = - mInterfaceCache.get(ifaceName); - - if ((iface != null) - && (iface.getService() == ifaceService)) { - mInterfaceCache.remove(ifaceName); - } - } - } - }, - 0); - } - } - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - - return iface; - } - - /** - * Returns a reference to the requested LowpanInterface object. If the given interface doesn't - * exist, or it is not a LoWPAN interface, returns null. - */ - @Nullable - public LowpanInterface getInterface(@NonNull String name) { - LowpanInterface iface = null; - - try { - /* This synchronized block covers both branches of the enclosed - * if() statement in order to avoid a race condition. Two threads - * calling getInterface() with the same name would race to create - * the associated LowpanInterface object, creating two of them. - * Having the whole block be synchronized avoids that race. - */ - synchronized (mInterfaceCache) { - if (mInterfaceCache.containsKey(name)) { - iface = mInterfaceCache.get(name); - - } else { - ILowpanInterface ifaceService = mService.getInterface(name); - - if (ifaceService != null) { - iface = getInterface(ifaceService); - } - } - } - } catch (RemoteException x) { - throw x.rethrowFromSystemServer(); - } - - return iface; - } - - /** - * Returns a reference to the first registered LowpanInterface object. If there are no LoWPAN - * interfaces registered, returns null. - */ - @Nullable - public LowpanInterface getInterface() { - String[] ifaceList = getInterfaceList(); - if (ifaceList.length > 0) { - return getInterface(ifaceList[0]); - } - return null; - } - - /** - * Returns a string array containing the names of LoWPAN interfaces. This list may contain fewer - * interfaces if the calling process does not have permissions to see individual interfaces. - */ - @NonNull - public String[] getInterfaceList() { - try { - return mService.getInterfaceList(); - } catch (RemoteException x) { - throw x.rethrowFromSystemServer(); - } - } - - /** - * Registers a callback object to receive notifications when LoWPAN interfaces are added or - * removed. - * - * @hide - */ - public void registerCallback(@NonNull Callback cb, @Nullable Handler handler) - throws LowpanException { - ILowpanManagerListener.Stub listenerBinder = - new ILowpanManagerListener.Stub() { - private Handler mHandler; - - { - if (handler != null) { - mHandler = handler; - } else if (mLooper != null) { - mHandler = new Handler(mLooper); - } else { - mHandler = new Handler(); - } - } - - @Override - public void onInterfaceAdded(ILowpanInterface ifaceService) { - Runnable runnable = - () -> { - LowpanInterface iface = getInterface(ifaceService); - - if (iface != null) { - cb.onInterfaceAdded(iface); - } - }; - - mHandler.post(runnable); - } - - @Override - public void onInterfaceRemoved(ILowpanInterface ifaceService) { - Runnable runnable = - () -> { - LowpanInterface iface = getInterfaceNoCreate(ifaceService); - - if (iface != null) { - cb.onInterfaceRemoved(iface); - } - }; - - mHandler.post(runnable); - } - }; - try { - mService.addListener(listenerBinder); - } catch (RemoteException x) { - throw x.rethrowFromSystemServer(); - } - - synchronized (mListenerMap) { - mListenerMap.put(Integer.valueOf(System.identityHashCode(cb)), listenerBinder); - } - } - - /** @hide */ - public void registerCallback(@NonNull Callback cb) throws LowpanException { - registerCallback(cb, null); - } - - /** - * Unregisters a previously registered {@link LowpanManager.Callback} object. - * - * @hide - */ - public void unregisterCallback(@NonNull Callback cb) { - Integer hashCode = Integer.valueOf(System.identityHashCode(cb)); - ILowpanManagerListener listenerBinder = null; - - synchronized (mListenerMap) { - listenerBinder = mListenerMap.get(hashCode); - mListenerMap.remove(hashCode); - } - - if (listenerBinder != null) { - try { - mService.removeListener(listenerBinder); - } catch (RemoteException x) { - throw x.rethrowFromSystemServer(); - } - } else { - throw new RuntimeException("Attempt to unregister an unknown callback"); - } - } -} diff --git a/lowpan/java/android/net/lowpan/LowpanProperties.java b/lowpan/java/android/net/lowpan/LowpanProperties.java deleted file mode 100644 index cc45ff85f723..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanProperties.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -/** {@hide} */ -public final class LowpanProperties { - - public static final LowpanProperty<int[]> KEY_CHANNEL_MASK = - new LowpanStandardProperty("android.net.lowpan.property.CHANNEL_MASK", int[].class); - - public static final LowpanProperty<Integer> KEY_MAX_TX_POWER = - new LowpanStandardProperty("android.net.lowpan.property.MAX_TX_POWER", Integer.class); - - /** @hide */ - private LowpanProperties() {} - - /** @hide */ - static final class LowpanStandardProperty<T> extends LowpanProperty<T> { - private final String mName; - private final Class<T> mType; - - LowpanStandardProperty(String name, Class<T> type) { - mName = name; - mType = type; - } - - @Override - public String getName() { - return mName; - } - - @Override - public Class<T> getType() { - return mType; - } - - @Override - public String toString() { - return getName(); - } - } -} diff --git a/lowpan/java/android/net/lowpan/LowpanProperty.java b/lowpan/java/android/net/lowpan/LowpanProperty.java deleted file mode 100644 index 7f26986e9da0..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanProperty.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import java.util.Map; - -/** {@hide} */ -public abstract class LowpanProperty<T> { - public abstract String getName(); - - public abstract Class<T> getType(); - - public void putInMap(Map map, T value) { - map.put(getName(), value); - } - - public T getFromMap(Map map) { - return (T) map.get(getName()); - } -} diff --git a/lowpan/java/android/net/lowpan/LowpanProvision.aidl b/lowpan/java/android/net/lowpan/LowpanProvision.aidl deleted file mode 100644 index 100e9dc8cc4a..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanProvision.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -parcelable LowpanProvision cpp_header "android/net/lowpan/LowpanProvision.h"; diff --git a/lowpan/java/android/net/lowpan/LowpanProvision.java b/lowpan/java/android/net/lowpan/LowpanProvision.java deleted file mode 100644 index 68c87092fbed..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanProvision.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.Parcel; -import android.os.Parcelable; -import java.util.Objects; - -/** - * Describes the information needed to describe a network - * - * @hide - */ -// @SystemApi -public class LowpanProvision implements Parcelable { - - // Builder - - /** @hide */ - // @SystemApi - public static class Builder { - private final LowpanProvision provision = new LowpanProvision(); - - public Builder setLowpanIdentity(@NonNull LowpanIdentity identity) { - provision.mIdentity = identity; - return this; - } - - public Builder setLowpanCredential(@NonNull LowpanCredential credential) { - provision.mCredential = credential; - return this; - } - - public LowpanProvision build() { - return provision; - } - } - - private LowpanProvision() {} - - // Instance Variables - - private LowpanIdentity mIdentity = new LowpanIdentity(); - private LowpanCredential mCredential = null; - - // Public Getters and Setters - - @NonNull - public LowpanIdentity getLowpanIdentity() { - return mIdentity; - } - - @Nullable - public LowpanCredential getLowpanCredential() { - return mCredential; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - - sb.append("LowpanProvision { identity => ").append(mIdentity.toString()); - - if (mCredential != null) { - sb.append(", credential => ").append(mCredential.toString()); - } - - sb.append("}"); - - return sb.toString(); - } - - @Override - public int hashCode() { - return Objects.hash(mIdentity, mCredential); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof LowpanProvision)) { - return false; - } - LowpanProvision rhs = (LowpanProvision) obj; - - if (!mIdentity.equals(rhs.mIdentity)) { - return false; - } - - if (!Objects.equals(mCredential, rhs.mCredential)) { - return false; - } - - return true; - } - - /** Implement the Parcelable interface. */ - @Override - public int describeContents() { - return 0; - } - - /** Implement the Parcelable interface. */ - @Override - public void writeToParcel(Parcel dest, int flags) { - mIdentity.writeToParcel(dest, flags); - if (mCredential == null) { - dest.writeBoolean(false); - } else { - dest.writeBoolean(true); - mCredential.writeToParcel(dest, flags); - } - } - - /** Implement the Parcelable interface. */ - public static final @android.annotation.NonNull Creator<LowpanProvision> CREATOR = - new Creator<LowpanProvision>() { - public LowpanProvision createFromParcel(Parcel in) { - Builder builder = new Builder(); - - builder.setLowpanIdentity(LowpanIdentity.CREATOR.createFromParcel(in)); - - if (in.readBoolean()) { - builder.setLowpanCredential(LowpanCredential.CREATOR.createFromParcel(in)); - } - - return builder.build(); - } - - public LowpanProvision[] newArray(int size) { - return new LowpanProvision[size]; - } - }; -}; diff --git a/lowpan/java/android/net/lowpan/LowpanRuntimeException.java b/lowpan/java/android/net/lowpan/LowpanRuntimeException.java deleted file mode 100644 index 71a5a1397a4e..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanRuntimeException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.util.AndroidRuntimeException; - -/** - * Generic runtime exception for LoWPAN operations. - * - * @hide - */ -// @SystemApi -public class LowpanRuntimeException extends AndroidRuntimeException { - - public LowpanRuntimeException() {} - - public LowpanRuntimeException(String message) { - super(message); - } - - public LowpanRuntimeException(String message, Throwable cause) { - super(message, cause); - } - - public LowpanRuntimeException(Exception cause) { - super(cause); - } -} diff --git a/lowpan/java/android/net/lowpan/LowpanScanner.java b/lowpan/java/android/net/lowpan/LowpanScanner.java deleted file mode 100644 index 59156c429010..000000000000 --- a/lowpan/java/android/net/lowpan/LowpanScanner.java +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.Handler; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * LoWPAN Scanner - * - * <p>This class allows performing network (active) scans and energy (passive) scans. - * - * @see LowpanInterface - * @hide - */ -// @SystemApi -public class LowpanScanner { - private static final String TAG = LowpanScanner.class.getSimpleName(); - - // Public Classes - - /** - * Callback base class for LowpanScanner - * - * @hide - */ - // @SystemApi - public abstract static class Callback { - public void onNetScanBeacon(LowpanBeaconInfo beacon) {} - - public void onEnergyScanResult(LowpanEnergyScanResult result) {} - - public void onScanFinished() {} - } - - // Instance Variables - - private ILowpanInterface mBinder; - private Callback mCallback = null; - private Handler mHandler = null; - private ArrayList<Integer> mChannelMask = null; - private int mTxPower = Integer.MAX_VALUE; - - // Constructors/Accessors and Exception Glue - - LowpanScanner(@NonNull ILowpanInterface binder) { - mBinder = binder; - } - - /** Sets an instance of {@link LowpanScanner.Callback} to receive events. */ - public synchronized void setCallback(@Nullable Callback cb, @Nullable Handler handler) { - mCallback = cb; - mHandler = handler; - } - - /** Sets an instance of {@link LowpanScanner.Callback} to receive events. */ - public void setCallback(@Nullable Callback cb) { - setCallback(cb, null); - } - - /** - * Sets the channel mask to use when scanning. - * - * @param mask The channel mask to use when scanning. If <code>null</code>, any previously set - * channel mask will be cleared and all channels not masked by the current regulatory zone - * will be scanned. - */ - public void setChannelMask(@Nullable Collection<Integer> mask) { - if (mask == null) { - mChannelMask = null; - } else { - if (mChannelMask == null) { - mChannelMask = new ArrayList<>(); - } else { - mChannelMask.clear(); - } - mChannelMask.addAll(mask); - } - } - - /** - * Gets the current channel mask. - * - * @return the current channel mask, or <code>null</code> if no channel mask is currently set. - */ - public @Nullable Collection<Integer> getChannelMask() { - return (Collection<Integer>) mChannelMask.clone(); - } - - /** - * Adds a channel to the channel mask used for scanning. - * - * <p>If a channel mask was previously <code>null</code>, a new one is created containing only - * this channel. May be called multiple times to add additional channels ot the channel mask. - * - * @see #setChannelMask - * @see #getChannelMask - * @see #getTxPower - */ - public void addChannel(int channel) { - if (mChannelMask == null) { - mChannelMask = new ArrayList<>(); - } - mChannelMask.add(Integer.valueOf(channel)); - } - - /** - * Sets the maximum transmit power to be used for active scanning. - * - * <p>The actual transmit power used is the lesser of this value and the currently configured - * maximum transmit power for the interface. - * - * @see #getTxPower - */ - public void setTxPower(int txPower) { - mTxPower = txPower; - } - - /** - * Gets the maximum transmit power used for active scanning. - * - * @see #setTxPower - */ - public int getTxPower() { - return mTxPower; - } - - private Map<String, Object> createScanOptionMap() { - Map<String, Object> map = new HashMap(); - - if (mChannelMask != null) { - LowpanProperties.KEY_CHANNEL_MASK.putInMap( - map, mChannelMask.stream().mapToInt(i -> i).toArray()); - } - - if (mTxPower != Integer.MAX_VALUE) { - LowpanProperties.KEY_MAX_TX_POWER.putInMap(map, Integer.valueOf(mTxPower)); - } - - return map; - } - - /** - * Start a network scan. - * - * <p>This method will return once the scan has started. - * - * @see #stopNetScan - */ - public void startNetScan() throws LowpanException { - Map<String, Object> map = createScanOptionMap(); - - ILowpanNetScanCallback binderListener = - new ILowpanNetScanCallback.Stub() { - public void onNetScanBeacon(LowpanBeaconInfo beaconInfo) { - Callback callback; - Handler handler; - - synchronized (LowpanScanner.this) { - callback = mCallback; - handler = mHandler; - } - - if (callback == null) { - return; - } - - Runnable runnable = () -> callback.onNetScanBeacon(beaconInfo); - - if (handler != null) { - handler.post(runnable); - } else { - runnable.run(); - } - } - - public void onNetScanFinished() { - Callback callback; - Handler handler; - - synchronized (LowpanScanner.this) { - callback = mCallback; - handler = mHandler; - } - - if (callback == null) { - return; - } - - Runnable runnable = () -> callback.onScanFinished(); - - if (handler != null) { - handler.post(runnable); - } else { - runnable.run(); - } - } - }; - - try { - mBinder.startNetScan(map, binderListener); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Stop a network scan currently in progress. - * - * @see #startNetScan - */ - public void stopNetScan() { - try { - mBinder.stopNetScan(); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } - - /** - * Start an energy scan. - * - * <p>This method will return once the scan has started. - * - * @see #stopEnergyScan - */ - public void startEnergyScan() throws LowpanException { - Map<String, Object> map = createScanOptionMap(); - - ILowpanEnergyScanCallback binderListener = - new ILowpanEnergyScanCallback.Stub() { - public void onEnergyScanResult(int channel, int rssi) { - Callback callback = mCallback; - Handler handler = mHandler; - - if (callback == null) { - return; - } - - Runnable runnable = - () -> { - if (callback != null) { - LowpanEnergyScanResult result = - new LowpanEnergyScanResult(); - result.setChannel(channel); - result.setMaxRssi(rssi); - callback.onEnergyScanResult(result); - } - }; - - if (handler != null) { - handler.post(runnable); - } else { - runnable.run(); - } - } - - public void onEnergyScanFinished() { - Callback callback = mCallback; - Handler handler = mHandler; - - if (callback == null) { - return; - } - - Runnable runnable = () -> callback.onScanFinished(); - - if (handler != null) { - handler.post(runnable); - } else { - runnable.run(); - } - } - }; - - try { - mBinder.startEnergyScan(map, binderListener); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - - } catch (ServiceSpecificException x) { - throw LowpanException.rethrowFromServiceSpecificException(x); - } - } - - /** - * Stop an energy scan currently in progress. - * - * @see #startEnergyScan - */ - public void stopEnergyScan() { - try { - mBinder.stopEnergyScan(); - - } catch (RemoteException x) { - throw x.rethrowAsRuntimeException(); - } - } -} diff --git a/lowpan/java/android/net/lowpan/NetworkAlreadyExistsException.java b/lowpan/java/android/net/lowpan/NetworkAlreadyExistsException.java deleted file mode 100644 index 90ef498baaba..000000000000 --- a/lowpan/java/android/net/lowpan/NetworkAlreadyExistsException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -/** - * Exception indicating the form operation found a network nearby with the same identity. - * - * @see LowpanInterface - * @hide - */ -// @SystemApi -public class NetworkAlreadyExistsException extends LowpanException { - - public NetworkAlreadyExistsException() {} - - public NetworkAlreadyExistsException(String message) { - super(message, null); - } - - public NetworkAlreadyExistsException(String message, Throwable cause) { - super(message, cause); - } - - public NetworkAlreadyExistsException(Exception cause) { - super(cause); - } -} diff --git a/lowpan/java/android/net/lowpan/OperationCanceledException.java b/lowpan/java/android/net/lowpan/OperationCanceledException.java deleted file mode 100644 index fcafe3ae9b8f..000000000000 --- a/lowpan/java/android/net/lowpan/OperationCanceledException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -/** - * Exception indicating this operation was canceled by the driver before it could finish. - * - * @see LowpanInterface - * @hide - */ -// @SystemApi -public class OperationCanceledException extends LowpanException { - - public OperationCanceledException() {} - - public OperationCanceledException(String message) { - super(message); - } - - public OperationCanceledException(String message, Throwable cause) { - super(message, cause); - } - - protected OperationCanceledException(Exception cause) { - super(cause); - } -} diff --git a/lowpan/java/android/net/lowpan/WrongStateException.java b/lowpan/java/android/net/lowpan/WrongStateException.java deleted file mode 100644 index 35654194e32b..000000000000 --- a/lowpan/java/android/net/lowpan/WrongStateException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -/** - * Exception indicating the interface is the wrong state for an operation. - * - * @see LowpanInterface - * @hide - */ -// @SystemApi -public class WrongStateException extends LowpanException { - - public WrongStateException() {} - - public WrongStateException(String message) { - super(message); - } - - public WrongStateException(String message, Throwable cause) { - super(message, cause); - } - - protected WrongStateException(Exception cause) { - super(cause); - } -} diff --git a/lowpan/java/android/net/lowpan/package.html b/lowpan/java/android/net/lowpan/package.html deleted file mode 100644 index 342e32eefc1e..000000000000 --- a/lowpan/java/android/net/lowpan/package.html +++ /dev/null @@ -1,29 +0,0 @@ -<HTML> -<BODY> -<p>@SystemApi</p> -<!-- @hide --> -<p>Provides classes to manage Low-power Wireless Personal Area Network (LoWPAN) functionality on the device. -Examples of such network technologies include <a href="http://threadgroup.org/">Thread</a> and -<a href="http://www.zigbee.org/zigbee-for-developers/network-specifications/zigbeeip/">ZigBee IP</a>.</p> -<p>The LoWPAN APIs provide a means by which applications can communicate -with the lower-level wireless stack that provides LoWPAN network access.</p> - -<p>Some APIs may require the following user permissions:</p> -<ul> - <li>{@link android.Manifest.permission#ACCESS_LOWPAN_STATE}</li> - <li>{@link android.Manifest.permission#CHANGE_LOWPAN_STATE}</li> - <li>TBD</li> -</ul> - -<p class="note"><strong>Note:</strong> Not all Android-powered devices provide LoWPAN functionality. -If your application uses these APIs, declare so with a <a -href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}</a> -element in the manifest file:</p> -<pre> -<manifest ...> - <uses-feature android:name="android.hardware.lowpan" /> - ... -</manifest> -</pre> -</BODY> -</HTML> diff --git a/lowpan/tests/Android.bp b/lowpan/tests/Android.bp deleted file mode 100644 index 590892926ec1..000000000000 --- a/lowpan/tests/Android.bp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2017 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. - -// Make test APK -// ============================================================ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -android_test { - name: "FrameworksLowpanApiTests", - srcs: ["**/*.java"], - // Filter all src files to just java files - jacoco: { - include_filter: ["android.net.lowpan.*"], - exclude_filter: [ - "android.net.lowpan.LowpanInterfaceTest*", - "android.net.lowpan.LowpanManagerTest*", - ], - }, - static_libs: [ - "androidx.test.rules", - "guava", - "mockito-target-minus-junit4", - "frameworks-base-testutils", - ], - libs: [ - "android.test.runner", - "android.test.base", - ], - platform_apis: true, - test_suites: ["device-tests"], - certificate: "platform", -} diff --git a/lowpan/tests/AndroidManifest.xml b/lowpan/tests/AndroidManifest.xml deleted file mode 100644 index 8e68fc74561e..000000000000 --- a/lowpan/tests/AndroidManifest.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<!-- - ~ Copyright (C) 2017 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 - --> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="android.net.lowpan.test"> - - <application> - <uses-library android:name="android.test.runner" /> - <activity android:label="LowpanTestDummyLabel" - android:name="LowpanTestDummyName" - android:exported="true"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER"/> - </intent-filter> - </activity> - </application> - - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.net.lowpan.test" - android:label="Frameworks LoWPAN API Tests"> - </instrumentation> - -</manifest> diff --git a/lowpan/tests/AndroidTest.xml b/lowpan/tests/AndroidTest.xml deleted file mode 100644 index 978cc02d2f57..000000000000 --- a/lowpan/tests/AndroidTest.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2017 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. ---> -<configuration description="Runs Frameworks LoWPAN API Tests."> - <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> - <option name="test-file-name" value="FrameworksLowpanApiTests.apk" /> - </target_preparer> - - <option name="test-suite-tag" value="apct" /> - <option name="test-tag" value="FrameworksLowpanApiTests" /> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="android.net.lowpan.test" /> - <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> - </test> -</configuration> diff --git a/lowpan/tests/README.md b/lowpan/tests/README.md deleted file mode 100644 index cb5772ee48ab..000000000000 --- a/lowpan/tests/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# LoWPAN Unit Tests -This package contains unit tests for the android LoWPAN framework System APIs based on the -[Android Testing Support Library](http://developer.android.com/tools/testing-support-library/index.html). -The test cases are built using the [JUnit](http://junit.org/) and [Mockito](http://mockito.org/) -libraries. - -## Running Tests -The easiest way to run tests is simply run - -``` -frameworks/base/lowpan/tests/runtests.sh -``` - -`runtests.sh` will build the test project and all of its dependencies and push the APK to the -connected device. It will then run the tests on the device. - -To pick up changes in framework/base, you will need to: -1. rebuild the framework library 'make -j32' -2. sync over the updated library to the device 'adb sync' -3. restart framework on the device 'adb shell stop' then 'adb shell start' - -To enable syncing data to the device for first time after clean reflash: -1. adb disable-verity -2. adb reboot -3. adb remount - -See below for a few example of options to limit which tests are run. -See the -[AndroidJUnitRunner Documentation](https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html) -for more details on the supported options. - -``` -runtests.sh -e package android.net.lowpan -runtests.sh -e class android.net.lowpan.LowpanManagerTest -``` - -If you manually build and push the test APK to the device you can run tests using - -``` -adb shell am instrument -w 'android.net.wifi.test/androidx.test.runner.AndroidJUnitRunner' -``` - -## Adding Tests -Tests can be added by adding classes to the src directory. JUnit4 style test cases can -be written by simply annotating test methods with `org.junit.Test`. - -## Debugging Tests -If you are trying to debug why tests are not doing what you expected, you can add android log -statements and use logcat to view them. The beginning and end of every tests is automatically logged -with the tag `TestRunner`. diff --git a/lowpan/tests/runtests.sh b/lowpan/tests/runtests.sh deleted file mode 100755 index 8267a7975c42..000000000000 --- a/lowpan/tests/runtests.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -if [ -z $ANDROID_BUILD_TOP ]; then - echo "You need to source and lunch before you can use this script" - exit 1 -fi - -echo "Running tests" - -set -e # fail early - -echo "+ mmma -j32 $ANDROID_BUILD_TOP/frameworks/base/lowpan/tests" -# NOTE Don't actually run the command above since this shell doesn't inherit functions from the -# caller. -make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk MODULES-IN-frameworks-base-lowpan-tests - -set -x # print commands - -adb root -adb wait-for-device - -adb install -r -g "$OUT/data/app/FrameworksLowpanApiTests/FrameworksLowpanApiTests.apk" - -adb shell am instrument -w "$@" 'android.net.lowpan.test/androidx.test.runner.AndroidJUnitRunner' diff --git a/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java b/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java deleted file mode 100644 index 86f9d0e3ca69..000000000000 --- a/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.os.Handler; -import android.os.IBinder; -import android.os.test.TestLooper; -import android.test.suitebuilder.annotation.SmallTest; - -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.Map; - -/** Unit tests for android.net.lowpan.LowpanInterface. */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class LowpanInterfaceTest { - private static final String TEST_PACKAGE_NAME = "TestPackage"; - - @Mock Context mContext; - @Mock ILowpanInterface mLowpanInterfaceService; - @Mock IBinder mLowpanInterfaceBinder; - @Mock ApplicationInfo mApplicationInfo; - @Mock IBinder mAppBinder; - @Mock LowpanInterface.Callback mLowpanInterfaceCallback; - - private Handler mHandler; - private final TestLooper mTestLooper = new TestLooper(); - private ILowpanInterfaceListener mInterfaceListener; - private LowpanInterface mLowpanInterface; - private Map<String, Object> mPropertyMap; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo); - when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME); - when(mLowpanInterfaceService.getName()).thenReturn("wpan0"); - when(mLowpanInterfaceService.asBinder()).thenReturn(mLowpanInterfaceBinder); - - mLowpanInterface = - new LowpanInterface(mContext, mLowpanInterfaceService, mTestLooper.getLooper()); - } - - @Test - public void testStateChangedCallback() throws Exception { - // Register our callback - mLowpanInterface.registerCallback(mLowpanInterfaceCallback); - - // Verify a listener was added - verify(mLowpanInterfaceService) - .addListener( - argThat( - listener -> { - mInterfaceListener = listener; - return listener instanceof ILowpanInterfaceListener; - })); - - // Change some properties - mInterfaceListener.onStateChanged(LowpanInterface.STATE_OFFLINE); - mTestLooper.dispatchAll(); - - // Verify that the property was changed - verify(mLowpanInterfaceCallback) - .onStateChanged( - argThat(stateString -> stateString.equals(LowpanInterface.STATE_OFFLINE))); - } -} diff --git a/lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java b/lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java deleted file mode 100644 index 998e8a549540..000000000000 --- a/lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.lowpan; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.*; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.os.Handler; -import android.os.IBinder; -import android.os.test.TestLooper; -import android.test.suitebuilder.annotation.SmallTest; - -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Unit tests for android.net.lowpan.LowpanManager. */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class LowpanManagerTest { - private static final String TEST_PACKAGE_NAME = "TestPackage"; - - @Mock Context mContext; - @Mock ILowpanManager mLowpanService; - @Mock ILowpanInterface mLowpanInterfaceService; - @Mock IBinder mLowpanInterfaceBinder; - @Mock ApplicationInfo mApplicationInfo; - @Mock IBinder mAppBinder; - @Mock LowpanManager.Callback mLowpanManagerCallback; - - private Handler mHandler; - private final TestLooper mTestLooper = new TestLooper(); - private LowpanManager mLowpanManager; - - private ILowpanManagerListener mManagerListener; - private LowpanInterface mLowpanInterface; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo); - when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME); - - mLowpanManager = new LowpanManager(mContext, mLowpanService, mTestLooper.getLooper()); - } - - @Test - public void testGetEmptyInterfaceList() throws Exception { - when(mLowpanService.getInterfaceList()).thenReturn(new String[0]); - assertTrue(mLowpanManager.getInterfaceList().length == 0); - assertTrue(mLowpanManager.getInterface() == null); - } - - @Test - public void testGetInterfaceList() throws Exception { - when(mLowpanService.getInterfaceList()).thenReturn(new String[] {"wpan0"}); - when(mLowpanService.getInterface("wpan0")).thenReturn(mLowpanInterfaceService); - when(mLowpanInterfaceService.getName()).thenReturn("wpan0"); - when(mLowpanInterfaceService.asBinder()).thenReturn(mLowpanInterfaceBinder); - assertEquals(mLowpanManager.getInterfaceList().length, 1); - - LowpanInterface iface = mLowpanManager.getInterface(); - assertNotNull(iface); - assertEquals(iface.getName(), "wpan0"); - } - - @Test - public void testRegisterCallback() throws Exception { - when(mLowpanInterfaceService.getName()).thenReturn("wpan0"); - when(mLowpanInterfaceService.asBinder()).thenReturn(mLowpanInterfaceBinder); - - // Register our callback - mLowpanManager.registerCallback(mLowpanManagerCallback); - - // Verify a listener was added - verify(mLowpanService) - .addListener( - argThat( - listener -> { - mManagerListener = listener; - return listener instanceof ILowpanManagerListener; - })); - - // Add an interface - mManagerListener.onInterfaceAdded(mLowpanInterfaceService); - mTestLooper.dispatchAll(); - - // Verify that the interface was added - verify(mLowpanManagerCallback) - .onInterfaceAdded( - argThat( - iface -> { - mLowpanInterface = iface; - return iface instanceof LowpanInterface; - })); - verifyNoMoreInteractions(mLowpanManagerCallback); - - // This check causes the test to fail with a weird error, but I'm not sure why. - assertEquals(mLowpanInterface.getService(), mLowpanInterfaceService); - - // Verify that calling getInterface on the LowpanManager object will yield the same - // LowpanInterface object. - when(mLowpanService.getInterfaceList()).thenReturn(new String[] {"wpan0"}); - when(mLowpanService.getInterface("wpan0")).thenReturn(mLowpanInterfaceService); - assertEquals(mLowpanManager.getInterface(), mLowpanInterface); - - // Remove the service - mManagerListener.onInterfaceRemoved(mLowpanInterfaceService); - mTestLooper.dispatchAll(); - - // Verify that the interface was removed - verify(mLowpanManagerCallback).onInterfaceRemoved(mLowpanInterface); - } - - @Test - public void testUnregisterCallback() throws Exception { - when(mLowpanInterfaceService.getName()).thenReturn("wpan0"); - when(mLowpanInterfaceService.asBinder()).thenReturn(mLowpanInterfaceBinder); - - // Register our callback - mLowpanManager.registerCallback(mLowpanManagerCallback); - - // Verify a listener was added - verify(mLowpanService) - .addListener( - argThat( - listener -> { - mManagerListener = listener; - return listener instanceof ILowpanManagerListener; - })); - - // Add an interface - mManagerListener.onInterfaceAdded(mLowpanInterfaceService); - mTestLooper.dispatchAll(); - - // Verify that the interface was added - verify(mLowpanManagerCallback) - .onInterfaceAdded( - argThat( - iface -> { - mLowpanInterface = iface; - return iface instanceof LowpanInterface; - })); - verifyNoMoreInteractions(mLowpanManagerCallback); - - // Unregister our callback - mLowpanManager.unregisterCallback(mLowpanManagerCallback); - - // Verify the listener was removed - verify(mLowpanService).removeListener(mManagerListener); - - // Verify that the callback wasn't invoked. - verifyNoMoreInteractions(mLowpanManagerCallback); - } -} diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java index 98438cde7c68..b6b88375a0a2 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java @@ -189,7 +189,8 @@ public class InstallStaging extends AlertActivity { out.write(buffer, 0, bytesRead); } } - } catch (IOException | SecurityException | IllegalStateException e) { + } catch (IOException | SecurityException | IllegalStateException + | IllegalArgumentException e) { Log.w(LOG_TAG, "Error staging apk from content URI", e); return false; } diff --git a/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_bg.xml b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_bg.xml new file mode 100644 index 000000000000..4da47af665f2 --- /dev/null +++ b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_bg.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@color/accessibility_magnifier_bg" />
+ <corners android:radius="24dp" />
+ <stroke
+ android:color="@color/accessibility_magnifier_bg_stroke"
+ android:width="1dp" />
+ </shape>
+ </item>
+</layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_btn_bg.xml b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_btn_bg.xml new file mode 100644 index 000000000000..5c9dd569b9d7 --- /dev/null +++ b/packages/SystemUI/res/drawable/accessibility_magnification_setting_view_btn_bg.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+android:color="?android:attr/colorControlHighlight">
+<item android:id="@android:id/mask">
+ <shape android:shape="oval">
+ <solid android:color="@color/accessibility_magnifier_bg" />
+ <size
+ android:width="56dp"
+ android:height="56dp"/>
+ <corners android:radius="2dp"/>
+ </shape>
+</item>
+</ripple>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/accessibility_magnifier_btn_bg.xml b/packages/SystemUI/res/drawable/accessibility_magnifier_btn_bg.xml new file mode 100644 index 000000000000..f633b3e3702d --- /dev/null +++ b/packages/SystemUI/res/drawable/accessibility_magnifier_btn_bg.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="@color/accessibility_magnifier_bg" />
+ <size
+ android:width="56dp"
+ android:height="56dp"/>
+ <corners android:radius="2dp"/>
+ <stroke
+ android:color="@color/accessibility_magnifier_bg_stroke"
+ android:width="1dp" />
+ </shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml deleted file mode 100644 index 5084ca48e608..000000000000 --- a/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_fp.xml +++ /dev/null @@ -1 +0,0 @@ -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="80dp" android:width="80dp" android:viewportHeight="80" android:viewportWidth="80"><group android:name="_R_G"><group android:name="_R_G_L_3_G" android:translateX="-0.25" android:translateY="-0.25"><path android:name="_R_G_L_3_G_D_0_P_0" android:fillColor="#474747" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M40.21 0.25 C18.13,0.25 0.25,18.17 0.25,40.25 C0.25,62.33 18.13,80.25 40.21,80.25 C62.33,80.25 80.25,62.33 80.25,40.25 C80.25,18.17 62.33,0.25 40.21,0.25c "/></group><group android:name="_R_G_L_2_G" android:translateX="-0.25" android:translateY="-0.25" android:pivotX="40.25" android:pivotY="40.25" android:scaleX="0.975" android:scaleY="0.975"><path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#f2b8b5" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M40.21 0.25 C18.13,0.25 0.25,18.17 0.25,40.25 C0.25,62.33 18.13,80.25 40.21,80.25 C62.33,80.25 80.25,62.33 80.25,40.25 C80.25,18.17 62.33,0.25 40.21,0.25c "/></group><group android:name="_R_G_L_1_G" android:translateX="9.950000000000003" android:translateY="10" android:pivotX="30" android:pivotY="30" android:scaleX="1.2" android:scaleY="1.2"><group android:name="_R_G_L_1_G_D_0_P_0_G_0_T_0" android:translateX="30" android:translateY="38.75" android:scaleX="1" android:scaleY="1"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#f2b8b5" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1.2 -1.25 C-1.2,-1.25 1.2,-1.25 1.2,-1.25 C1.2,-1.25 1.2,1.25 1.2,1.25 C1.2,1.25 -1.2,1.25 -1.2,1.25 C-1.2,1.25 -1.2,-1.25 -1.2,-1.25c "/></group><group android:name="_R_G_L_1_G_D_1_P_0_G_0_T_0" android:translateX="30" android:translateY="25" android:pivotX="0.002" android:pivotY="7.488" android:scaleX="1" android:scaleY="1"><path android:name="_R_G_L_1_G_D_1_P_0" android:fillColor="#f2b8b5" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1.2 -7.5 C-1.2,-7.5 1.2,-7.5 1.2,-7.5 C1.2,-7.5 1.2,7.5 1.2,7.5 C1.2,7.5 -1.2,7.5 -1.2,7.5 C-1.2,7.5 -1.2,-7.5 -1.2,-7.5c "/></group></group><group android:name="_R_G_L_0_G" android:translateX="20.659" android:translateY="15.75"><path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 "/><path android:name="_R_G_L_0_G_D_1_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 "/><path android:name="_R_G_L_0_G_D_2_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 "/><path android:name="_R_G_L_0_G_D_3_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="0" android:trimPathOffset="0" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_3_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="167" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_2_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeWidth" android:duration="167" android:startOffset="0" android:valueFrom="2.5" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_2_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeAlpha" android:duration="83" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="strokeAlpha" android:duration="83" android:startOffset="83" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_2_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="0.975" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_2_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="167" android:valueFrom="0.975" android:valueTo="0" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_0_P_0_G_0_T_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="1" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.853,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="1" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.853,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="100" android:startOffset="67" android:valueFrom="1.1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.92,1.06 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="100" android:startOffset="67" android:valueFrom="1.1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.92,1.06 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_1_P_0_G_0_T_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.659,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="1" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="100" android:startOffset="67" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="100" android:startOffset="67" android:valueFrom="1.1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.92,1.096 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="83" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.543,0 0.299,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathEnd" android:duration="250" android:startOffset="83" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.543,0 0.299,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="83" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.543,0 0.299,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathEnd" android:duration="250" android:startOffset="83" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.543,0 0.299,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_2_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="83" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.543,0 0.299,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathEnd" android:duration="250" android:startOffset="83" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.543,0 0.299,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_3_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathEnd" android:duration="83" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.543,0 0.299,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="trimPathEnd" android:duration="250" android:startOffset="83" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.543,0 0.299,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="417" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_unlock.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_unlock.xml deleted file mode 100644 index c4f818146011..000000000000 --- a/packages/SystemUI/res/drawable/fingerprint_dialog_error_to_unlock.xml +++ /dev/null @@ -1 +0,0 @@ -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="80dp" android:width="80dp" android:viewportHeight="80" android:viewportWidth="80"><group android:name="_R_G"><group android:name="_R_G_L_3_G" android:translateX="-0.25" android:translateY="-0.25"><path android:name="_R_G_L_3_G_D_0_P_0" android:fillColor="#474747" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M40.21 0.25 C18.13,0.25 0.25,18.17 0.25,40.25 C0.25,62.33 18.13,80.25 40.21,80.25 C62.33,80.25 80.25,62.33 80.25,40.25 C80.25,18.17 62.33,0.25 40.21,0.25c "/></group><group android:name="_R_G_L_2_G" android:translateX="-0.25" android:translateY="-0.25" android:pivotX="40.25" android:pivotY="40.25" android:scaleX="0.975" android:scaleY="0.975"><path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#f2b8b5" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2.5" android:strokeAlpha="1" android:pathData=" M40.21 0.25 C18.13,0.25 0.25,18.17 0.25,40.25 C0.25,62.33 18.13,80.25 40.21,80.25 C62.33,80.25 80.25,62.33 80.25,40.25 C80.25,18.17 62.33,0.25 40.21,0.25c "/></group><group android:name="_R_G_L_1_G" android:translateX="9.950000000000003" android:translateY="10" android:pivotX="30" android:pivotY="30" android:scaleX="1.2" android:scaleY="1.2"><group android:name="_R_G_L_1_G_D_0_P_0_G_0_T_0" android:translateX="30" android:translateY="38.75" android:scaleX="1" android:scaleY="1"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#f2b8b5" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1.2 -1.25 C-1.2,-1.25 1.2,-1.25 1.2,-1.25 C1.2,-1.25 1.2,1.25 1.2,1.25 C1.2,1.25 -1.2,1.25 -1.2,1.25 C-1.2,1.25 -1.2,-1.25 -1.2,-1.25c "/></group><group android:name="_R_G_L_1_G_D_1_P_0_G_0_T_0" android:translateX="30" android:translateY="25" android:pivotX="0.002" android:pivotY="7.488" android:scaleX="1" android:scaleY="1"><path android:name="_R_G_L_1_G_D_1_P_0" android:fillColor="#f2b8b5" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1.2 -7.5 C-1.2,-7.5 1.2,-7.5 1.2,-7.5 C1.2,-7.5 1.2,7.5 1.2,7.5 C1.2,7.5 -1.2,7.5 -1.2,7.5 C-1.2,7.5 -1.2,-7.5 -1.2,-7.5c "/></group></group><group android:name="_R_G_L_0_G" android:translateX="20.75" android:translateY="15.75" android:pivotX="19.341" android:pivotY="24.25" android:scaleX="0.5" android:scaleY="0"><path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M30.64 30.14 C30.64,30.14 30.64,38.14 30.64,38.14 C30.64,38.77 30.36,39.32 29.91,39.69 C29.57,39.97 29.12,40.14 28.64,40.14 C28.64,40.14 10.14,40.14 10.14,40.14 C9.04,40.14 8.14,39.25 8.14,38.14 C8.14,38.14 8.14,30.14 8.14,30.14 "/><path android:name="_R_G_L_0_G_D_1_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M19.42 31.53 C18.15,31.52 18.11,30.33 18.11,30.33 C18.11,29.59 18.66,28.98 19.4,28.98 C20.13,28.98 20.69,29.59 20.69,30.33 C20.69,30.33 20.69,30.37 20.69,30.37 C20.69,30.64 20.49,30.87 20.25,30.87 C20.07,30.87 19.91,30.74 19.84,30.55 C19.84,30.55 19.69,30.14 19.69,30.14 C19.63,29.94 19.46,29.82 19.28,29.82 C19.04,29.82 18.61,30.02 18.61,30.29 C18.61,30.43 18.6,30.75 18.76,31.03 C18.87,31.21 19.21,31.77 19.96,31.41 C20.69,31.01 20.69,30.34 20.69,30.34 "/><path android:name="_R_G_L_0_G_D_2_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M8.14 30.22 C8.14,30.22 8.14,22.22 8.14,22.22 C8.14,21.71 8.33,21.25 8.64,20.9 C9,20.48 9.54,20.22 10.14,20.22 C10.14,20.22 28.64,20.22 28.64,20.22 C29.75,20.22 30.64,21.11 30.64,22.22 C30.64,22.22 30.64,30.14 30.64,30.14 "/><path android:name="_R_G_L_0_G_D_3_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M13.12 20.04 C13.12,20.04 13.11,14.15 13.11,14.15 C13.11,10.77 15.91,8.04 19.36,8.04 C22.81,8.04 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_3_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="167" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_2_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeWidth" android:duration="167" android:startOffset="0" android:valueFrom="2.5" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_2_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeAlpha" android:duration="83" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="strokeAlpha" android:duration="83" android:startOffset="83" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_2_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="0.975" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_2_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="167" android:valueFrom="0.975" android:valueTo="0" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_0_P_0_G_0_T_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="1" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.853,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="1" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.853,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="100" android:startOffset="67" android:valueFrom="1.1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.92,1.06 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="100" android:startOffset="67" android:valueFrom="1.1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.92,1.06 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_1_P_0_G_0_T_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.659,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="1" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="100" android:startOffset="67" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="100" android:startOffset="67" android:valueFrom="1.1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.8,0 0.92,1.096 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_3_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="233" android:startOffset="0" android:valueFrom="M13.12 20.04 C13.12,20.04 13.11,14.15 13.11,14.15 C13.11,10.77 15.91,8.04 19.36,8.04 C22.81,8.04 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueTo="M13.12 20.04 C13.12,20.04 13.11,14.15 13.11,14.15 C13.11,10.77 15.91,8.04 19.36,8.04 C22.81,8.04 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="267" android:startOffset="233" android:valueFrom="M13.12 20.04 C13.12,20.04 13.11,14.15 13.11,14.15 C13.11,10.77 15.91,8.04 19.36,8.04 C22.81,8.04 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueTo="M37.91 20.05 C37.91,20.05 37.89,14.16 37.89,14.16 C37.89,10.79 35.15,8.05 31.86,8.03 C28.46,8.01 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="167" android:startOffset="0" android:valueFrom="0.5" android:valueTo="0.5" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.05,1.4 0.1,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="167" android:startOffset="0" android:valueFrom="0.5" android:valueTo="0.5" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.05,1.4 0.1,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="333" android:startOffset="167" android:valueFrom="0.5" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.05,1.4 0.1,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="333" android:startOffset="167" android:valueFrom="0.5" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.05,1.4 0.1,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="167" android:valueFrom="0" android:valueTo="0.5" android:valueType="floatType"/></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="683" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml deleted file mode 100644 index c05a8d55c16c..000000000000 --- a/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_error.xml +++ /dev/null @@ -1 +0,0 @@ -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="80dp" android:width="80dp" android:viewportHeight="80" android:viewportWidth="80"><group android:name="_R_G"><group android:name="_R_G_L_3_G" android:translateX="-0.25" android:translateY="-0.25"><path android:name="_R_G_L_3_G_D_0_P_0" android:fillColor="#474747" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40.21 0.25 C18.13,0.25 0.25,18.17 0.25,40.25 C0.25,62.33 18.13,80.25 40.21,80.25 C62.33,80.25 80.25,62.33 80.25,40.25 C80.25,18.17 62.33,0.25 40.21,0.25c "/></group><group android:name="_R_G_L_2_G" android:translateX="-0.25" android:translateY="-0.25" android:pivotX="40.25" android:pivotY="40.25" android:scaleX="0.975" android:scaleY="0"><path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#f2b8b5" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="0" android:strokeAlpha="0" android:pathData=" M40.21 0.25 C18.13,0.25 0.25,18.17 0.25,40.25 C0.25,62.33 18.13,80.25 40.21,80.25 C62.33,80.25 80.25,62.33 80.25,40.25 C80.25,18.17 62.33,0.25 40.21,0.25c "/></group><group android:name="_R_G_L_1_G" android:translateX="9.950000000000003" android:translateY="10" android:pivotX="30" android:pivotY="30" android:scaleX="1.2" android:scaleY="1.2"><group android:name="_R_G_L_1_G_D_0_P_0_G_0_T_0" android:translateX="30" android:translateY="38.75" android:scaleX="0" android:scaleY="0"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#f2b8b5" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1.2 -1.25 C-1.2,-1.25 1.2,-1.25 1.2,-1.25 C1.2,-1.25 1.2,1.25 1.2,1.25 C1.2,1.25 -1.2,1.25 -1.2,1.25 C-1.2,1.25 -1.2,-1.25 -1.2,-1.25c "/></group><group android:name="_R_G_L_1_G_D_1_P_0_G_0_T_0" android:translateX="30" android:translateY="25" android:pivotX="0.002" android:pivotY="7.488" android:scaleX="1" android:scaleY="0"><path android:name="_R_G_L_1_G_D_1_P_0" android:fillColor="#f2b8b5" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-1.2 -7.5 C-1.2,-7.5 1.2,-7.5 1.2,-7.5 C1.2,-7.5 1.2,7.5 1.2,7.5 C1.2,7.5 -1.2,7.5 -1.2,7.5 C-1.2,7.5 -1.2,-7.5 -1.2,-7.5c "/></group></group><group android:name="_R_G_L_0_G" android:translateX="20.659" android:translateY="15.75"><path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="1" android:trimPathOffset="0" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 "/><path android:name="_R_G_L_0_G_D_1_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="1" android:trimPathOffset="0" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 "/><path android:name="_R_G_L_0_G_D_2_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="1" android:trimPathOffset="0" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 "/><path android:name="_R_G_L_0_G_D_3_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:trimPathStart="0" android:trimPathEnd="1" android:trimPathOffset="0" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_3_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="83" android:startOffset="0" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_2_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeWidth" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="strokeWidth" android:duration="233" android:startOffset="67" android:valueFrom="0" android:valueTo="2.5" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_2_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeAlpha" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="strokeAlpha" android:duration="83" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_2_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="0.975" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_0_P_0_G_0_T_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="167" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.08,0.06 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="167" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.08,0.06 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="100" android:startOffset="167" android:valueFrom="0" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.08,0.06 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="100" android:startOffset="167" android:valueFrom="0" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.08,0.06 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="267" android:valueFrom="1.1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.147,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="267" android:valueFrom="1.1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.147,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_1_P_0_G_0_T_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="167" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="167" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.08,0.096 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="100" android:startOffset="167" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="100" android:startOffset="167" android:valueFrom="0" android:valueTo="1.1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.08,0.096 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="267" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.341,0 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="267" android:valueFrom="1.1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathStart" android:duration="167" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathStart" android:duration="167" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_2_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathStart" android:duration="167" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_3_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="trimPathStart" android:duration="167" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.2,0 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="350" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_unlock.xml b/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_unlock.xml deleted file mode 100644 index 16944294a94e..000000000000 --- a/packages/SystemUI/res/drawable/fingerprint_dialog_fp_to_unlock.xml +++ /dev/null @@ -1 +0,0 @@ -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="80dp" android:width="80dp" android:viewportHeight="80" android:viewportWidth="80"><group android:name="_R_G"><group android:name="_R_G_L_2_G" android:translateX="-0.25" android:translateY="-0.25"><path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#474747" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M40.21 0.25 C18.13,0.25 0.25,18.17 0.25,40.25 C0.25,62.33 18.13,80.25 40.21,80.25 C62.33,80.25 80.25,62.33 80.25,40.25 C80.25,18.17 62.33,0.25 40.21,0.25c "/></group><group android:name="_R_G_L_1_G" android:translateX="20.75" android:translateY="15.75"><path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 "/><path android:name="_R_G_L_1_G_D_1_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 "/><path android:name="_R_G_L_1_G_D_2_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 "/><path android:name="_R_G_L_1_G_D_3_P_0" android:strokeColor="#d3e3fd" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 "/></group><group android:name="_R_G_L_0_G" android:translateX="37.357" android:translateY="43.25" android:pivotX="2.75" android:pivotY="2.75" android:scaleX="1.41866" android:scaleY="1.41866"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#d3e3fd" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M2.75 5.25 C4.13,5.25 5.25,4.13 5.25,2.75 C5.25,1.37 4.13,0.25 2.75,0.25 C1.37,0.25 0.25,1.37 0.25,2.75 C0.25,4.13 1.37,5.25 2.75,5.25c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="107" android:startOffset="0" android:valueFrom="M27.52 38.98 C26.49,39.95 25.29,40.73 23.98,41.29 C23.17,41.65 22.31,41.91 21.41,42.07 C20.74,42.19 20.05,42.25 19.34,42.25 C18.44,42.25 17.56,42.15 16.72,41.96 C15.93,41.77 15.16,41.51 14.43,41.18 C13.23,40.63 12.13,39.88 11.16,38.98 " android:valueTo="M30.81 32.26 C30.56,32.49 30.27,38.76 29.96,38.9 C29.77,39.46 29.13,39.94 28.57,40.26 C28.15,40.51 26.93,40.65 26.4,40.65 C26.18,40.65 11.91,40.62 11.71,40.58 C10.68,40.53 9.06,39.79 8.89,38.88 C8.6,38.74 8.34,32.48 8.1,32.27 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.541,0 0.833,0.767 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="143" android:startOffset="107" android:valueFrom="M30.81 32.26 C30.56,32.49 30.27,38.76 29.96,38.9 C29.77,39.46 29.13,39.94 28.57,40.26 C28.15,40.51 26.93,40.65 26.4,40.65 C26.18,40.65 11.91,40.62 11.71,40.58 C10.68,40.53 9.06,39.79 8.89,38.88 C8.6,38.74 8.34,32.48 8.1,32.27 " android:valueTo="M30.64 30.14 C30.64,30.14 30.64,38.14 30.64,38.14 C30.64,38.77 30.36,39.32 29.91,39.69 C29.57,39.97 29.12,40.14 28.64,40.14 C28.64,40.14 10.14,40.14 10.14,40.14 C9.04,40.14 8.14,39.25 8.14,38.14 C8.14,38.14 8.14,30.14 8.14,30.14 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.233 0.331,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeAlpha" android:duration="140" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="strokeAlpha" android:duration="50" android:startOffset="140" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="107" android:startOffset="0" android:valueFrom="M8.64 34.07 C7.89,31.97 7.89,29.85 7.89,29.85 C7.89,24.05 12.81,19.34 19.34,19.34 C25.87,19.34 30.8,24.05 30.8,29.85 C30.8,29.85 30.8,30.16 30.8,30.16 C30.8,32.32 29.04,34.07 26.89,34.07 C25.28,34.07 23.86,33.1 23.27,31.61 C23.27,31.61 21.96,28.34 21.96,28.34 C21.37,26.85 19.93,25.89 18.34,25.89 C16.18,25.89 14.43,27.64 14.43,29.8 C14.43,31.42 14.87,32.99 15.68,34.36 C16.22,35.26 16.93,36.08 17.77,36.75 C17.77,36.75 18.52,37.34 18.52,37.34 " android:valueTo="M18.93 32.18 C17.11,32.68 16.62,30.26 16.62,30.26 C16.62,28.78 17.81,27.59 19.39,27.59 C20.96,27.59 22.15,28.78 22.15,30.26 C22.15,30.26 22.15,30.34 22.15,30.34 C22.15,30.89 21.11,32.54 19.57,32.19 C19.19,32.1 20.48,31.09 20.34,30.71 C20.34,30.71 20.02,29.88 20.02,29.88 C19.88,29.5 19.53,29.25 19.15,29.25 C18.63,29.25 18,29.67 18,30.22 C18,30.57 18.06,31.08 18.32,31.51 C18.49,31.8 19.02,32.25 19.79,32.04 C20.41,31.7 20.38,31.36 20.38,31.36 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.541,0 0.833,0.767 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="107" android:startOffset="107" android:valueFrom="M18.93 32.18 C17.11,32.68 16.62,30.26 16.62,30.26 C16.62,28.78 17.81,27.59 19.39,27.59 C20.96,27.59 22.15,28.78 22.15,30.26 C22.15,30.26 22.15,30.34 22.15,30.34 C22.15,30.89 21.11,32.54 19.57,32.19 C19.19,32.1 20.48,31.09 20.34,30.71 C20.34,30.71 20.02,29.88 20.02,29.88 C19.88,29.5 19.53,29.25 19.15,29.25 C18.63,29.25 18,29.67 18,30.22 C18,30.57 18.06,31.08 18.32,31.51 C18.49,31.8 19.02,32.25 19.79,32.04 C20.41,31.7 20.38,31.36 20.38,31.36 " android:valueTo="M19.42 31.53 C18.15,31.52 18.11,30.33 18.11,30.33 C18.11,29.59 18.66,28.98 19.4,28.98 C20.13,28.98 20.69,29.59 20.69,30.33 C20.69,30.33 20.69,30.37 20.69,30.37 C20.69,30.64 20.49,30.87 20.25,30.87 C20.07,30.87 19.91,30.74 19.84,30.55 C19.84,30.55 19.69,30.14 19.69,30.14 C19.63,29.94 19.46,29.82 19.28,29.82 C19.04,29.82 18.61,30.02 18.61,30.29 C18.61,30.43 18.6,30.75 18.76,31.03 C18.87,31.21 19.21,31.77 19.96,31.41 C20.69,31.01 20.69,30.34 20.69,30.34 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.233 0,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_2_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="250" android:startOffset="0" android:valueFrom="M6.25 19.34 C7.48,17.3 9.46,15.58 11.9,14.42 C12.93,13.94 14.03,13.55 15.2,13.27 C16.51,12.96 17.9,12.8 19.34,12.8 C20.77,12.8 22.14,12.96 23.45,13.26 C24.9,13.6 26.26,14.12 27.48,14.78 C29.6,15.92 31.32,17.5 32.43,19.34 " android:valueTo="M8.14 30.22 C8.14,30.22 8.14,22.22 8.14,22.22 C8.14,21.71 8.33,21.25 8.64,20.9 C9,20.48 9.54,20.22 10.14,20.22 C10.14,20.22 28.64,20.22 28.64,20.22 C29.75,20.22 30.64,21.11 30.64,22.22 C30.64,22.22 30.64,30.14 30.64,30.14 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.541,0 0.189,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G_D_3_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="95" android:startOffset="0" android:valueFrom="M9.52 8.7 C10.98,7.91 12.58,7.28 14.28,6.86 C15.89,6.46 17.58,6.25 19.34,6.25 C21.06,6.25 22.72,6.45 24.3,6.83 C26.04,7.25 27.67,7.89 29.16,8.7 " android:valueTo="M11.47 14.84 C11.47,14.84 12.21,11.43 13.54,9.84 C14.84,8.28 16.68,7.22 19.35,7.22 C22.01,7.22 23.98,8.4 25.19,10.18 C26.39,11.96 27.25,14.84 27.25,14.84 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.541,0 0.833,0.767 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="24" android:startOffset="95" android:valueFrom="M11.47 14.84 C11.47,14.84 12.21,11.43 13.54,9.84 C14.84,8.28 16.68,7.22 19.35,7.22 C22.01,7.22 23.98,8.4 25.19,10.18 C26.39,11.96 27.25,14.84 27.25,14.84 " android:valueTo="M12.11 16.85 C12.11,16.85 12.82,12.71 13.37,11.5 C14.17,9.24 16.38,7.53 19.35,7.53 C22.32,7.53 24.61,9.32 25.35,11.72 C25.61,12.64 26.62,16.85 26.62,16.85 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.233 0.833,0.767 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="81" android:startOffset="119" android:valueFrom="M12.11 16.85 C12.11,16.85 12.82,12.71 13.37,11.5 C14.17,9.24 16.38,7.53 19.35,7.53 C22.32,7.53 24.61,9.32 25.35,11.72 C25.61,12.64 26.62,16.85 26.62,16.85 " android:valueTo="M13.12 20.04 C13.12,20.04 13.11,14.15 13.11,14.15 C13.11,10.77 15.91,8.04 19.36,8.04 C22.81,8.04 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.233 0.261,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="233" android:startOffset="200" android:valueFrom="M13.12 20.04 C13.12,20.04 13.11,14.15 13.11,14.15 C13.11,10.77 15.91,8.04 19.36,8.04 C22.81,8.04 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueTo="M37.91 20.05 C37.91,20.05 37.89,14.16 37.89,14.16 C37.89,10.79 35.15,8.05 31.86,8.03 C28.46,8.01 25.61,10.77 25.61,14.15 C25.61,14.15 25.62,20.04 25.62,20.04 " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.123,0 0.23,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="120" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="20" android:startOffset="120" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="120" android:startOffset="0" android:valueFrom="1.4186600000000003" android:valueTo="1.4186600000000003" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.43,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="120" android:startOffset="0" android:valueFrom="1.4186600000000003" android:valueTo="1.4186600000000003" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.43,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="130" android:startOffset="120" android:valueFrom="1.4186600000000003" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.43,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="130" android:startOffset="120" android:valueFrom="1.4186600000000003" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.43,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="517" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_magnification_menu_close.xml b/packages/SystemUI/res/drawable/ic_magnification_menu_close.xml new file mode 100644 index 000000000000..a44a484d6e39 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_magnification_menu_close.xml @@ -0,0 +1,29 @@ +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportWidth="32" + android:viewportHeight="32"> + <path + android:pathData="M7.3334,24.6667L24.6674,7.3334M7.3334,7.3334L24.6674,24.6667" + android:strokeLineJoin="round" + android:strokeWidth="1.5" + android:fillColor="#00000000" + android:strokeColor="#000000" + android:fillType="evenOdd" + android:strokeLineCap="round"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_magnification_menu_large.xml b/packages/SystemUI/res/drawable/ic_magnification_menu_large.xml new file mode 100644 index 000000000000..1ab0d4d3bf12 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_magnification_menu_large.xml @@ -0,0 +1,25 @@ +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="24" + android:viewportHeight="24" + android:width="24dp" + android:height="24dp"> + <path + android:pathData="M3 21L21 21C22.1 21 23 20.1 23 19L23 5C23 3.9 22.1 3 21 3L3 3C1.9 3 1 3.9 1 5L1 19C1 20.1 1.9 21 3 21ZM3 5L21 5L21 19L3 19L3 5ZM4 15L16.75 15L16.75 6L4 6L4 15Z" + android:fillType="evenOdd" + android:fillColor="#000000" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_magnification_menu_medium.xml b/packages/SystemUI/res/drawable/ic_magnification_menu_medium.xml new file mode 100644 index 000000000000..6fc89a69f36e --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_magnification_menu_medium.xml @@ -0,0 +1,25 @@ +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="24" + android:viewportHeight="24" + android:width="24dp" + android:height="24dp"> + <path + android:pathData="M3 21L21 21C22.1 21 23 20.1 23 19L23 5C23 3.9 22.1 3 21 3L3 3C1.9 3 1 3.9 1 5L1 19C1 20.1 1.9 21 3 21ZM3 5L21 5L21 19L3 19L3 5ZM4 12.75L13.75 12.75L13.75 6L4 6L4 12.75Z" + android:fillType="evenOdd" + android:fillColor="#000000" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_magnification_menu_small.xml b/packages/SystemUI/res/drawable/ic_magnification_menu_small.xml new file mode 100644 index 000000000000..fd7357424f32 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_magnification_menu_small.xml @@ -0,0 +1,25 @@ +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:viewportWidth="24" + android:viewportHeight="24" + android:width="24dp" + android:height="24dp"> + <path + android:pathData="M3 21L21 21C22.1 21 23 20.1 23 19L23 5C23 3.9 22.1 3 21 3L3 3C1.9 3 1 3.9 1 5L1 19C1 20.1 1.9 21 3 21ZM3 5L21 5L21 19L3 19L3 5ZM4 10.5L8.5 10.5L8.5 6L4 6L4 10.5Z" + android:fillType="evenOdd" + android:fillColor="#000000" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_move_magnification.xml b/packages/SystemUI/res/drawable/ic_move_magnification.xml index 96db3651ac25..1bff559ff3df 100644 --- a/packages/SystemUI/res/drawable/ic_move_magnification.xml +++ b/packages/SystemUI/res/drawable/ic_move_magnification.xml @@ -23,18 +23,21 @@ <size android:height="@dimen/magnification_drag_view_size" android:width="@dimen/magnification_drag_view_size"/> + <corners android:topLeftRadius="12dp"/> + </shape> </item> <item android:gravity="center"> + <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="30dp" - android:height="30dp" android:viewportWidth="24" - android:viewportHeight="24"> + android:viewportHeight="24" + android:width="24dp" + android:height="24dp"> <path - android:pathData="M18.19,12.44l-3.24,-1.62c1.29,-1 2.12,-2.56 2.12,-4.32c0,-3.03 -2.47,-5.5 -5.5,-5.5s-5.5,2.47 -5.5,5.5c0,2.13 1.22,3.98 3,4.89v3.26c-2.11,-0.45 -2.01,-0.44 -2.26,-0.44c-0.53,0 -1.03,0.21 -1.41,0.59L4,16.22l5.09,5.09C9.52,21.75 10.12,22 10.74,22h6.3c0.98,0 1.81,-0.7 1.97,-1.67l0.8,-4.71C20.03,14.32 19.38,13.04 18.19,12.44zM17.84,15.29L17.04,20h-6.3c-0.09,0 -0.17,-0.04 -0.24,-0.1l-3.68,-3.68l4.25,0.89V6.5c0,-0.28 0.22,-0.5 0.5,-0.5c0.28,0 0.5,0.22 0.5,0.5v6h1.76l3.46,1.73C17.69,14.43 17.91,14.86 17.84,15.29zM8.07,6.5c0,-1.93 1.57,-3.5 3.5,-3.5s3.5,1.57 3.5,3.5c0,0.95 -0.38,1.81 -1,2.44V6.5c0,-1.38 -1.12,-2.5 -2.5,-2.5c-1.38,0 -2.5,1.12 -2.5,2.5v2.44C8.45,8.31 8.07,7.45 8.07,6.5z" - android:fillColor="#FFFFFF"/> + android:pathData="M13.2217 21.7734C12.8857 22.1094 12.288 22.712 12 23C12 23 11.1143 22.1094 10.7783 21.7734L8.33494 19.3301L9.55662 18.1084L12 20.5518L14.4434 18.1084L15.665 19.3301L13.2217 21.7734ZM19.3301 15.665L18.1084 14.4433L20.5518 12L18.1084 9.5566L19.3301 8.33492L21.7735 10.7783C22.1094 11.1142 22.4241 11.4241 23 12C22.4241 12.5759 22.3963 12.5988 21.7735 13.2217L19.3301 15.665ZM14.4434 14.4433C13.7714 15.1153 12.957 15.4512 12 15.4512C11.043 15.4512 10.2285 15.1153 9.55662 14.4433C8.88469 13.7714 8.54873 12.957 8.54873 12C8.54873 11.043 8.88469 10.2285 9.55662 9.5566C10.2285 8.88468 11.043 8.54871 12 8.54871C12.957 8.54871 13.7714 8.88467 14.4434 9.5566C15.1153 10.2285 15.4512 11.043 15.4512 12C15.4512 12.957 15.1153 13.7714 14.4434 14.4433ZM4.66988 15.665L2.22651 13.2217C1.89055 12.8857 1.28791 12.288 1 12C1.28791 11.712 1.89055 11.1143 2.22651 10.7783L4.66988 8.33492L5.89157 9.5566L3.4482 12L5.89157 14.4433L4.66988 15.665ZM14.4434 5.89155L12 3.44818L9.55662 5.89155L8.33494 4.66987L10.7783 2.2265C11.1389 1.86592 11.2963 1.70369 12 1C12.5758 1.57585 12.8857 1.89053 13.2217 2.2265L15.665 4.66986L14.4434 5.89155Z" + android:fillColor="#ffffff" /> </vector> </item> </layer-list> diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml index 36a1224a78c9..c7434f5e46fd 100644 --- a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml +++ b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml @@ -13,35 +13,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> -<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - - <item> - <shape android:shape="rectangle"> - <solid android:color="@color/magnification_switch_button_color" /> - <size - android:width="48dp" - android:height="48dp" /> - </shape> - </item> - - <item - android:gravity="center"> - <vector - android:width="36dp" - android:height="36dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <group> - <clip-path - android:pathData="M0,0h24v24h-24z"/> - <path - android:pathData="M11,6.05V8.05H14.59L8,14.64V11.05H6V18.05H13V16.05H9.41L16,9.46V13.05H18V6.05H11Z" - android:fillColor="#ffffff"/> - <path - android:pathData="M20,4.05V20.05H4V4.05H20ZM22,2.05H2V22.05H22V2.05Z" - android:fillColor="#ffffff"/> - </group> - </vector> - </item> - -</layer-list> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="36dp" + android:height="36dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <group> + <clip-path + android:pathData="M0,0h24v24h-24z"/> + <path + android:pathData="M11,6.05V8.05H14.59L8,14.64V11.05H6V18.05H13V16.05H9.41L16,9.46V13.05H18V6.05H11Z" + android:fillColor="#000000"/> + <path + android:pathData="M20,4.05V20.05H4V4.05H20ZM22,2.05H2V22.05H22V2.05Z" + android:fillColor="#000000"/> + </group> +</vector> diff --git a/packages/SystemUI/res/layout/auth_biometric_contents.xml b/packages/SystemUI/res/layout/auth_biometric_contents.xml index e1b294f2d757..d633803c920b 100644 --- a/packages/SystemUI/res/layout/auth_biometric_contents.xml +++ b/packages/SystemUI/res/layout/auth_biometric_contents.xml @@ -49,11 +49,11 @@ <FrameLayout android:id="@+id/biometric_icon_frame" - android:layout_width="match_parent" + android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"> - <ImageView + <com.airbnb.lottie.LottieAnimationView android:id="@+id/biometric_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/layout/auth_biometric_fingerprint_view.xml b/packages/SystemUI/res/layout/auth_biometric_fingerprint_view.xml index ce53e278302a..01ea31f8bdd2 100644 --- a/packages/SystemUI/res/layout/auth_biometric_fingerprint_view.xml +++ b/packages/SystemUI/res/layout/auth_biometric_fingerprint_view.xml @@ -17,7 +17,7 @@ <com.android.systemui.biometrics.AuthBiometricFingerprintView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/contents" - android:layout_width="match_parent" + android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> diff --git a/packages/SystemUI/res/layout/window_magnification_settings_view.xml b/packages/SystemUI/res/layout/window_magnification_settings_view.xml new file mode 100644 index 000000000000..6d8847cce644 --- /dev/null +++ b/packages/SystemUI/res/layout/window_magnification_settings_view.xml @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/magnifier_panel_view" + android:layout_width="@dimen/magnification_max_size" + android:layout_height="match_parent" + android:background="@drawable/accessibility_magnification_setting_view_bg" + android:orientation="vertical"> + <LinearLayout + android:layout_width="@dimen/magnification_max_size" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <TextView + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/accessibility_magnifier_size" + android:textAppearance="?android:attr/textAppearanceListItem" + android:textColor="?android:attr/textColorAlertDialogListItem" + android:focusable="true" + android:layout_gravity="center_vertical|left" + android:layout_marginStart="20dp"/> + + <Button + android:id="@+id/magnifier_edit_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/accessibility_magnifier_edit" + android:textAppearance="?android:attr/textAppearanceListItem" + android:textColor="?android:attr/textColorAlertDialogListItem" + android:focusable="true" + android:layout_gravity="right" + android:layout_marginEnd="20dp"/> + </LinearLayout> + + <LinearLayout + android:layout_width="@dimen/magnification_max_size" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <ImageButton + android:id="@+id/magnifier_small_button" + android:layout_width="0dp" + android:layout_height="56dp" + android:scaleType="center" + android:layout_weight="1" + android:layout_marginStart="12dp"/> + + <ImageButton + android:id="@+id/magnifier_medium_button" + android:layout_width="0dp" + android:layout_height="56dp" + android:scaleType="center" + android:layout_weight="1"/> + + <ImageButton + android:id="@+id/magnifier_large_button" + android:layout_width="0dp" + android:layout_height="56dp" + android:scaleType="center" + android:layout_weight="1"/> + + <ImageButton + android:id="@+id/magnifier_full_button" + android:layout_width="0dp" + android:layout_height="56dp" + android:scaleType="center" + android:layout_weight="1" + android:layout_marginEnd="12dp"/> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:paddingTop="8dp" + android:paddingEnd="20dp" + android:paddingStart="20dp" + android:focusable="true"> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:background="?android:attr/selectableItemBackground" + android:ellipsize="marquee" + android:gravity="center_vertical" + android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:orientation="vertical"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:text="@string/accessibility_allow_diagonal_scrolling" + android:textAppearance="?android:attr/textAppearanceListItem" + android:textColor="?android:attr/textColorAlertDialogListItem" /> + </LinearLayout> + + <Switch + android:id="@+id/magnifier_horizontal_lock_switch" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="right|center" + android:theme="@android:style/Theme.DeviceDefault.DayNight"/> + </LinearLayout> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/accessibility_magnification_zoom" + android:textAppearance="?android:attr/textAppearanceListItem" + android:textColor="?android:attr/textColorAlertDialogListItem" + android:focusable="true" + android:layout_marginStart="20dp" + android:paddingTop="2dp" + android:paddingBottom="10dp"/> + + <SeekBar + android:id="@+id/magnifier_zoom_seekbar" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:progress="0" + android:max="6" + android:layout_marginEnd="20dp" + android:theme="@android:style/Theme.DeviceDefault.DayNight"/> + + + <Button + android:id="@+id/magnifier_close_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/accessibility_magnification_close" + android:textAppearance="?android:attr/textAppearanceListItem" + android:textColor="?android:attr/textColorAlertDialogListItem" + android:focusable="true" + android:layout_gravity="center_horizontal" + android:paddingBottom="24dp"/> +</LinearLayout> diff --git a/packages/SystemUI/res/layout/window_magnifier_view.xml b/packages/SystemUI/res/layout/window_magnifier_view.xml index 7c755e546589..0bff47ccf722 100644 --- a/packages/SystemUI/res/layout/window_magnifier_view.xml +++ b/packages/SystemUI/res/layout/window_magnifier_view.xml @@ -16,33 +16,25 @@ --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:screenReaderFocusable="true"> - <View - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_margin="@dimen/magnification_outer_border_margin" - android:importantForAccessibility="no" - android:background="@android:color/black"/> + android:layout_width="wrap_content" + android:layout_height="wrap_content"> <View + android:id="@+id/magnification_inner_border" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_margin="@dimen/magnification_inner_border_margin" - android:importantForAccessibility="no" + android:layout_margin="@dimen/magnification_outer_border_margin" android:background="@color/magnification_border_color"/> <RelativeLayout android:layout_width="match_parent" - android:layout_height="match_parent" - android:importantForAccessibility="noHideDescendants"> + android:layout_height="match_parent"> <View android:id="@+id/left_handle" android:layout_width="@dimen/magnification_border_drag_size" android:layout_height="match_parent" - android:layout_above="@+id/bottom_handle"/> + android:layout_alignParentStart="true"/> <View android:id="@+id/top_handle" @@ -54,7 +46,6 @@ android:id="@+id/right_handle" android:layout_width="@dimen/magnification_border_drag_size" android:layout_height="match_parent" - android:layout_above="@+id/bottom_handle" android:layout_alignParentEnd="true"/> <View @@ -68,7 +59,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="@dimen/magnification_mirror_surface_margin"/> - </RelativeLayout> <ImageView @@ -79,7 +69,17 @@ android:layout_gravity="right|bottom" android:padding="@dimen/magnifier_drag_handle_padding" android:scaleType="center" - android:importantForAccessibility="no" android:src="@drawable/ic_move_magnification"/> -</FrameLayout>
\ No newline at end of file + <ImageView + android:id="@+id/close_button" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_margin="30dp" + android:padding="@dimen/magnification_switch_button_padding" + android:layout_gravity="right|bottom" + android:scaleType="center" + android:visibility="gone" + android:background="@drawable/accessibility_magnifier_btn_bg" + android:src="@drawable/ic_magnification_menu_close" /> +</FrameLayout> diff --git a/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_fingerprint_lottie.json b/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_fingerprint_lottie.json new file mode 100644 index 000000000000..cc68a83c0653 --- /dev/null +++ b/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_fingerprint_lottie.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":25,"w":80,"h":80,"nm":"error_to_fingerprint","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".colorAccentPrimary","cl":"colorAccentPrimary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450990677,0.890196084976,0.992156863213,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.299],"y":[1]},"o":{"x":[0.543],"y":[0]},"t":5,"s":[0]},{"t":20,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":5,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[39.95,40,0],"ix":2,"l":2},"a":{"a":0,"k":[30,30,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.2,-7.5],[1.2,-7.5],[1.2,7.5],[-1.2,7.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30.002,32.488],"ix":2},"a":{"a":0,"k":[0.002,7.488],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.659,0.6],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.6,0.92],"y":[1,1.096]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":4,"s":[100,110]},{"t":10,"s":[100,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top!","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.2,-1.25],[1.2,-1.25],[1.2,1.25],[-1.2,1.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30,38.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.6,0.6],"y":[1,1]},"o":{"x":[0.853,0.853],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.92,0.92],"y":[1.06,1.06]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":4,"s":[110,110]},{"t":10,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom!","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":25,"st":-30,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[97.5,97.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[2.5]},{"t":10,"s":[0]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":10,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey700","cl":"grey700","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.278431385756,0.278431385756,0.278431385756,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[0]},{"t":14,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_unlock_lottie.json b/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_unlock_lottie.json new file mode 100644 index 000000000000..aaf7e587eb6b --- /dev/null +++ b/packages/SystemUI/res/raw/fingerprint_dialogue_error_to_unlock_lottie.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":41,"w":80,"h":80,"nm":"error_to_unlock","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".colorAccentPrimary","cl":"colorAccentPrimary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40.091,40,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[1.4,1.4,0]},"t":10,"s":[50,50,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":14,"s":[{"i":[[0,0],[0,0],[-3.452,0],[0,-3.375],[0,0]],"o":[[0,0],[0,-3.375],[3.452,0],[0,0],[0,0]],"v":[[-6.217,12.558],[-6.234,6.669],[0.016,0.558],[6.266,6.669],[6.283,12.558]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0],[3.292,0.021],[0,-3.375],[0,0]],"o":[[0,0],[0,-3.375],[-3.393,-0.022],[0,0],[0,0]],"v":[[18.568,12.573],[18.552,6.684],[12.516,0.553],[6.266,6.669],[6.283,12.558]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450990677,0.890196084976,0.992156863213,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.307,0.352],[-0.601,0],[0,0],[0,-1.104],[0,0]],"o":[[0,0],[0,-0.503],[0.367,-0.42],[0,0],[1.104,0],[0,0],[0,0]],"v":[[-11.2,14.15],[-11.198,6.146],[-10.705,4.831],[-9.198,4.146],[9.302,4.146],[11.302,6.146],[11.3,14.07]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.736,0],[0,-0.741],[0,0],[0.243,0],[0.066,0.191],[0,0],[0.179,0],[0,-0.276],[-0.162,-0.273],[-0.755,0.357],[0,0]],"o":[[-1.273,-0.008],[0,-0.741],[0.736,0],[0,0],[0,0.276],[-0.181,0],[0,0],[-0.066,-0.191],[-0.243,0],[-0.002,0.139],[0.109,0.182],[0.727,-0.402],[0,0]],"v":[[0.082,3.187],[-1.235,1.986],[0.055,0.642],[1.346,1.986],[1.346,2.026],[0.905,2.527],[0.498,2.212],[0.35,1.794],[-0.057,1.479],[-0.733,1.951],[-0.58,2.686],[0.619,3.071],[1.351,2]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.446,-0.367],[0.481,0],[0,0],[0,1.104],[0,0]],"o":[[0,0],[0,0.623],[-0.345,0.284],[0,0],[-1.104,0],[0,0],[0,0]],"v":[[11.302,-10.469],[11.302,-2.469],[10.57,-0.923],[9.302,-0.469],[-9.198,-0.469],[-11.198,-2.469],[-11.198,-10.469]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":10,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[39.95,40,0],"ix":2,"l":2},"a":{"a":0,"k":[30,30,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.2,-7.5],[1.2,-7.5],[1.2,7.5],[-1.2,7.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30.002,32.488],"ix":2},"a":{"a":0,"k":[0.002,7.488],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.659,0.6],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.6,0.92],"y":[1,1.096]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":4,"s":[100,110]},{"t":10,"s":[100,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top!","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.2,-1.25],[1.2,-1.25],[1.2,1.25],[-1.2,1.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30,38.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.6,0.6],"y":[1,1]},"o":{"x":[0.853,0.853],"y":[0,0]},"t":0,"s":[100,100]},{"i":{"x":[0.92,0.92],"y":[1.06,1.06]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":4,"s":[110,110]},{"t":10,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom!","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":86,"st":-30,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[97.5,97.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[100]},{"t":10,"s":[0]}],"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[2.5]},{"t":10,"s":[0]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":10,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey700","cl":"grey700","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.278431385756,0.278431385756,0.278431385756,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[0]},{"t":14,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_error_lottie.json b/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_error_lottie.json new file mode 100644 index 000000000000..78bccba83ecb --- /dev/null +++ b/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_error_lottie.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":80,"h":80,"nm":"fingerprint_to_error","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".colorAccentPrimary","cl":"colorAccentPrimary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450990677,0.890196084976,0.992156863213,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[100]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":5,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[39.95,40,0],"ix":2,"l":2},"a":{"a":0,"k":[30,30,0],"ix":1,"l":2},"s":{"a":0,"k":[120,120,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.2,-7.5],[1.2,-7.5],[1.2,7.5],[-1.2,7.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019610882,0.721568644047,0.709803938866,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30.002,32.488],"ix":2},"a":{"a":0,"k":[0.002,7.488],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.4,0.08],"y":[0,0.096]},"t":10,"s":[100,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.341,0.4],"y":[0,0]},"t":16,"s":[100,110]},{"t":20,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top!","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-1.2,-1.25],[1.2,-1.25],[1.2,1.25],[-1.2,1.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.949019610882,0.721568644047,0.709803938866,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30,38.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.08,0.08],"y":[0.06,0.06]},"t":10,"s":[0,0]},{"i":{"x":[0.147,0.147],"y":[1,1]},"o":{"x":[0.4,0.4],"y":[0,0]},"t":16,"s":[110,110]},{"t":20,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom!","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":21,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".red200","cl":"red200","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[0]},{"t":9,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[97.5,97.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[0]},{"t":9,"s":[100]}],"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.949019607843,0.721568627451,0.709803921569,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[0]},{"t":9,"s":[100]}],"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[0]},{"t":18,"s":[2.5]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":4,"op":600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey700","cl":"grey700","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.278431385756,0.278431385756,0.278431385756,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"t":5,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_unlock_lottie.json b/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_unlock_lottie.json new file mode 100644 index 000000000000..313c6c59539c --- /dev/null +++ b/packages/SystemUI/res/raw/fingerprint_dialogue_fingerprint_to_unlock_lottie.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":31,"w":80,"h":80,"nm":"fingerprint_to_unlock","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":".colorAccentPrimary","cl":"colorAccentPrimary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40.107,46,0],"ix":2,"l":2},"a":{"a":0,"k":[2.75,2.75,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.43,0.43,0.2],"y":[1,1,1]},"o":{"x":[0.001,0.001,0.001],"y":[0,0,0]},"t":7.199,"s":[141.866,141.866,100]},{"t":15,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.381,0],[0,1.381],[1.381,0],[0,-1.381]],"o":[[1.381,0],[0,-1.381],[-1.381,0],[0,1.381]],"v":[[0,2.5],[2.5,0],[0,-2.5],[-2.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7.199,"s":[0]},{"t":8.400390625,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[2.75,2.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".colorAccentPrimary","cl":"colorAccentPrimary","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40.091,40,0],"ix":2,"l":2},"a":{"a":0,"k":[19.341,24.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.767},"o":{"x":0.541,"y":0},"t":0,"s":[{"i":[[0,0],[-1.701,0.42],[-1.757,0],[-1.577,-0.381],[-1.485,-0.816]],"o":[[1.455,-0.799],[1.608,-0.397],[1.719,0],[1.739,0.42],[0,0]],"v":[[-9.818,1.227],[-5.064,-0.618],[0,-1.227],[4.96,-0.643],[9.818,1.227]],"c":false}]},{"i":{"x":0.833,"y":0.767},"o":{"x":0.167,"y":0.233},"t":5.715,"s":[{"i":[[0,0],[-1.323,1.591],[-2.674,0],[-1.207,-1.781],[0,0]],"o":[[0,0],[1.298,-1.562],[2.657,0],[1.206,1.781],[0,0]],"v":[[-7.87,7.358],[-5.804,2.36],[0.009,-0.261],[5.845,2.706],[7.905,7.358]],"c":false}]},{"i":{"x":0.261,"y":1},"o":{"x":0.167,"y":0.233},"t":7.143,"s":[{"i":[[0,0],[-0.549,1.21],[-2.975,0],[-0.74,-2.398],[0,0]],"o":[[0,0],[0.796,-2.263],[2.964,0],[0.258,0.927],[0,0]],"v":[[-7.231,9.37],[-5.97,4.027],[0.012,0.056],[6.008,4.239],[7.277,9.37]],"c":false}]},{"i":{"x":0.23,"y":1},"o":{"x":0.123,"y":0},"t":12,"s":[{"i":[[0,0],[0,0],[-3.452,0],[0,-3.375],[0,0]],"o":[[0,0],[0,-3.375],[3.452,0],[0,0],[0,0]],"v":[[-6.217,12.558],[-6.234,6.669],[0.016,0.558],[6.266,6.669],[6.283,12.558]],"c":false}]},{"t":26,"s":[{"i":[[0,0],[0,0],[3.292,0.021],[0,-3.375],[0,0]],"o":[[0,0],[0,-3.375],[-3.393,-0.022],[0,0],[0,0]],"v":[[18.568,12.573],[18.552,6.684],[12.516,0.553],[6.266,6.669],[6.283,12.558]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,7.477],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Top","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.189,"y":1},"o":{"x":0.541,"y":0},"t":0,"s":[{"i":[[0,0],[-2.446,1.161],[-1.168,0.275],[-1.439,0],[-1.301,-0.304],[-1.225,-0.66],[-1.11,-1.844]],"o":[[1.23,-2.044],[1.024,-0.486],[1.312,-0.31],[1.425,0],[1.454,0.34],[2.122,1.143],[0,0]],"v":[[-13.091,3.273],[-7.438,-1.646],[-4.14,-2.797],[0,-3.273],[4.104,-2.805],[8.141,-1.29],[13.091,3.273]],"c":false}]},{"t":15,"s":[{"i":[[0,0],[0,0],[-0.307,0.352],[-0.601,0],[0,0],[0,-1.104],[0,0]],"o":[[0,0],[0,-0.503],[0.367,-0.42],[0,0],[1.104,0],[0,0],[0,0]],"v":[[-11.2,14.15],[-11.198,6.146],[-10.705,4.831],[-9.198,4.146],[9.302,4.146],[11.302,6.146],[11.3,14.07]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,16.069],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Mid Top","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.767},"o":{"x":0.541,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[-6.53,0],[0,-5.793],[0,0],[2.159,0],[0.59,1.489],[0,0],[1.587,0],[0,-2.16],[-0.81,-1.363],[-0.844,-0.674],[0,0]],"o":[[-0.753,-2.095],[0,-5.793],[6.529,0],[0,0],[0,2.16],[-1.604,0],[0,0],[-0.589,-1.489],[-2.161,0],[0,1.62],[0.54,0.909],[0,0],[0,0]],"v":[[-10.702,5.728],[-11.454,1.506],[0.001,-9],[11.454,1.506],[11.454,1.817],[7.544,5.728],[3.926,3.273],[2.618,0],[-0.997,-2.454],[-4.91,1.457],[-3.657,6.014],[-1.57,8.412],[-0.818,9]],"c":false}]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.233},"t":6.428,"s":[{"i":[[0,0],[0,0],[-1.576,0],[0,-1.474],[0,0],[1.541,0.347],[0.142,0.379],[0,0],[0.383,0],[0,-0.549],[-0.256,-0.431],[-0.768,0.207],[0,0]],"o":[[-1.823,0.497],[0,-1.474],[1.576,0],[0,0],[0,0.549],[-0.378,-0.085],[0,0],[-0.142,-0.379],[-0.521,0],[-0.002,0.353],[0.171,0.288],[0.622,-0.344],[0,0]],"v":[[-0.41,3.841],[-2.717,1.917],[0.047,-0.756],[2.811,1.917],[2.811,1.996],[0.225,3.848],[0.995,2.366],[0.679,1.534],[-0.193,0.909],[-1.338,1.879],[-1.026,3.169],[0.445,3.702],[1.036,3.015]],"c":false}]},{"t":12.857421875,"s":[{"i":[[0,0],[0,0],[-0.736,0],[0,-0.741],[0,0],[0.243,0],[0.066,0.191],[0,0],[0.179,0],[0,-0.276],[-0.162,-0.273],[-0.755,0.357],[0,0]],"o":[[-1.273,-0.008],[0,-0.741],[0.736,0],[0,0],[0,0.276],[-0.181,0],[0,0],[-0.066,-0.191],[-0.243,0],[-0.002,0.139],[0.109,0.182],[0.727,-0.402],[0,0]],"v":[[0.082,3.187],[-1.235,1.986],[0.055,0.642],[1.346,1.986],[1.346,2.026],[0.905,2.527],[0.498,2.212],[0.35,1.794],[-0.057,1.479],[-0.733,1.951],[-0.58,2.686],[0.619,3.071],[1.351,2]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":8.4,"s":[100]},{"t":11.3984375,"s":[0]}],"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,28.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Inside to dot ","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.767},"o":{"x":0.541,"y":0},"t":0,"s":[{"i":[[0,0],[1.307,-0.561],[0.894,-0.16],[0.706,0],[0.844,0.193],[0.728,0.334],[0.967,0.901]],"o":[[-1.038,0.967],[-0.817,0.351],[-0.673,0.12],[-0.9,0],[-0.794,-0.182],[-1.203,-0.551],[0,0]],"v":[[8.182,-1.636],[4.642,0.681],[2.07,1.453],[-0.001,1.636],[-2.621,1.341],[-4.909,0.563],[-8.182,-1.636]],"c":false}]},{"i":{"x":0.331,"y":1},"o":{"x":0.167,"y":0.233},"t":6.428,"s":[{"i":[[0,0],[0.313,-0.134],[0.554,-0.317],[0.535,0],[0.203,0.046],[0.175,0.919],[0.232,0.216]],"o":[[-0.249,0.232],[-0.196,0.557],[-0.424,0.245],[-0.216,0],[-1.03,-0.044],[-0.288,-0.132],[0,0]],"v":[[11.468,-8.353],[10.62,-1.716],[9.232,-0.353],[7.057,0.034],[-7.634,-0.037],[-10.453,-1.739],[-11.238,-8.347]],"c":false}]},{"t":15,"s":[{"i":[[0,0],[0,0],[0.446,-0.367],[0.481,0],[0,0],[0,1.104],[0,0]],"o":[[0,0],[0,0.623],[-0.345,0.284],[0,0],[-1.104,0],[0,0],[0,0]],"v":[[11.302,-10.469],[11.302,-2.469],[10.57,-0.923],[9.302,-0.469],[-9.198,-0.469],[-11.198,-2.469],[-11.198,-10.469]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.827450980392,0.890196078431,0.992156862745,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[19.341,40.614],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Bottom","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".grey700","cl":"grey700","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[40,40,0],"ix":2,"l":2},"a":{"a":0,"k":[40.25,40.25,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.12,0],[0,-22.08],[-22.08,0],[0,22.08]],"o":[[-22.08,0],[0,22.08],[22.12,0],[0,-22.08]],"v":[[-0.04,-40],[-40,0],[-0.04,40],[40,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.278431385756,0.278431385756,0.278431385756,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[40.25,40.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[{"tm":30,"cm":"1","dr":0},{"tm":51,"cm":"350ms\r","dr":0},{"tm":69,"cm":"650ms\r","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 1eece4cee179..26bf1034df11 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -166,8 +166,12 @@ <!-- Window magnification colors --> <color name="magnification_border_color">#FF9900</color> + <color name="magnification_border_color_change">#0000FF</color> <color name="magnification_switch_button_color">#7F000000</color> <color name="magnification_drag_handle_color">#B3000000</color> + <color name="accessibility_magnifier_bg">#FCFCFC</color> + <color name="accessibility_magnifier_bg_stroke">#E0E0E0</color> + <color name="accessibility_magnifier_icon_color">#252525</color> <!-- Volume dialog colors --> <color name="volume_dialog_background_color">@android:color/transparent</color> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 786b6b884605..1168378fb14f 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -926,7 +926,8 @@ <!-- Biometric Dialog values --> <dimen name="biometric_dialog_face_icon_size">64dp</dimen> - <dimen name="biometric_dialog_fingerprint_icon_size">80dp</dimen> + <dimen name="biometric_dialog_fingerprint_icon_width">80dp</dimen> + <dimen name="biometric_dialog_fingerprint_icon_height">80dp</dimen> <dimen name="biometric_dialog_button_negative_max_width">160dp</dimen> <dimen name="biometric_dialog_button_positive_max_width">136dp</dimen> <dimen name="biometric_dialog_corner_size">4dp</dimen> @@ -1065,8 +1066,10 @@ <dimen name="magnification_frame_move_long">25dp</dimen> <dimen name="magnification_drag_view_size">36dp</dimen> <dimen name="magnification_controls_size">90dp</dimen> - <dimen name="magnification_switch_button_size">48dp</dimen> + <dimen name="magnification_switch_button_size">56dp</dimen> + <dimen name="magnification_switch_button_padding">6dp</dimen> <dimen name="magnification_switch_button_margin">16dp</dimen> + <dimen name="magnification_close_button_padding">15dp</dimen> <dimen name="magnifier_left_right_controls_width">35dp</dimen> <dimen name="magnifier_left_right_controls_height">45dp</dimen> <dimen name="magnifier_up_down_controls_width">45dp</dimen> @@ -1074,10 +1077,15 @@ <!-- The extra padding to show the whole outer border --> <dimen name="magnifier_drag_handle_padding">3dp</dimen> <dimen name="magnification_max_frame_size">300dp</dimen> + <!-- How far from the right edge of the screen you need to drag the window before the button repositions to the other side. --> <dimen name="magnification_button_reposition_threshold_from_edge">32dp</dimen> + <dimen name="magnification_drag_size">15dp</dimen> + <dimen name="magnification_max_size">360dp</dimen> + <dimen name="magnifier_panel_size">265dp</dimen> + <!-- Home Controls --> <dimen name="controls_header_menu_size">48dp</dimen> <dimen name="controls_header_bottom_margin">24dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 7f3caeca5a62..b844f11d0015 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2109,6 +2109,41 @@ <!-- Click action label for magnification switch. [CHAR LIMIT=NONE] --> <string name="magnification_mode_switch_click_label">Switch</string> + <!-- Title of the magnification option button allow diagonal scrolling [CHAR LIMIT=NONE]--> + <string name="accessibility_allow_diagonal_scrolling">Allow diagonal scrolling</string> + <!-- Title of the magnification option button Resize [CHAR LIMIT=NONE]--> + <string name="accessibility_resize">Resize</string> + <!-- Title of the magnification option button Change type [CHAR LIMIT=NONE]--> + <string name="accessibility_change_magnification_type">Change magnification type</string> + <!-- Title of the magnification option button End resizing [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_end_resizing">End resizing</string> + + <!-- Description of the window magnification Top handle [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_top_handle">Top handle</string> + <!-- Description of the window magnification Left handle [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_left_handle">Left handle</string> + <!-- Description of the window magnification Right handle [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_right_handle">Right handle</string> + <!-- Description of the window magnification Bottom handle [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_bottom_handle">Bottom handle</string> + + <!-- Title of the window magnification panel option Magnifier size [CHAR LIMIT=NONE]--> + <string name="accessibility_magnifier_size">Magnifier size</string> + <!-- Title of the window magnification panel option Zoom [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_zoom">Zoom</string> + <!-- Click action label for magnification panel medium size [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_medium">Medium</string> + <!-- Click action label for magnification panel small size [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_small">Small</string> + <!-- Click action label for magnification panel large size [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_large">Large</string> + <!-- Click action label for magnification panel Close [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_close">Close</string> + <!-- Click action label for edit magnification size [CHAR LIMIT=NONE]--> + <string name="accessibility_magnifier_edit">Edit</string> + <!-- Click action label for magnification panel settings [CHAR LIMIT=NONE]--> + <string name="accessibility_magnification_magnifier_window_settings">Magnifier window settings</string> + <!-- Accessibility floating menu strings --> <!-- Message for the accessibility floating button migration tooltip. It shows when the user use gestural navigation then upgrade their system. It will tell the user they could customize or replace the floating button in Settings. [CHAR LIMIT=100] --> <string name="accessibility_floating_button_migration_tooltip">Tap to open accessibility features. Customize or replace this button in Settings.\n\n<annotation id="link">View settings</annotation></string> diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationGestureDetector.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationGestureDetector.java index 4b30ec3e6f6f..c91082c618c5 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationGestureDetector.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationGestureDetector.java @@ -23,6 +23,7 @@ import android.graphics.PointF; import android.os.Handler; import android.view.Display; import android.view.MotionEvent; +import android.view.View; import android.view.ViewConfiguration; /** @@ -41,7 +42,7 @@ class MagnificationGestureDetector { * * @return {@code true} if this gesture is handled. */ - boolean onSingleTap(); + boolean onSingleTap(View view); /** * Called when the user is performing dragging gesture. It is started after the offset @@ -52,7 +53,7 @@ class MagnificationGestureDetector { * @param offsetY The Y offset in screen coordinate. * @return {@code true} if this gesture is handled. */ - boolean onDrag(float offsetX, float offsetY); + boolean onDrag(View view, float offsetX, float offsetY); /** * Notified when a tap occurs with the down {@link MotionEvent} that triggered it. This will @@ -109,7 +110,7 @@ class MagnificationGestureDetector { * @param event The current motion event. * @return {@code True} if the {@link OnGestureListener} consumes the event, else false. */ - boolean onTouch(MotionEvent event) { + boolean onTouch(View view, MotionEvent event) { final float rawX = event.getRawX(); final float rawY = event.getRawY(); boolean handled = false; @@ -125,12 +126,12 @@ class MagnificationGestureDetector { break; case MotionEvent.ACTION_MOVE: stopSingleTapDetectionIfNeeded(rawX, rawY); - handled |= notifyDraggingGestureIfNeeded(rawX, rawY); + handled |= notifyDraggingGestureIfNeeded(view, rawX, rawY); break; case MotionEvent.ACTION_UP: stopSingleTapDetectionIfNeeded(rawX, rawY); if (mDetectSingleTap) { - handled |= mOnGestureListener.onSingleTap(); + handled |= mOnGestureListener.onSingleTap(view); } // Fall through case MotionEvent.ACTION_CANCEL: @@ -163,7 +164,7 @@ class MagnificationGestureDetector { mDetectSingleTap = false; } - private boolean notifyDraggingGestureIfNeeded(float x, float y) { + private boolean notifyDraggingGestureIfNeeded(View view, float x, float y) { if (!mDraggingDetected) { return false; } @@ -173,7 +174,7 @@ class MagnificationGestureDetector { final float offsetX = x - mPointerLocation.x; final float offsetY = y - mPointerLocation.y; mPointerLocation.set(x, y); - return mOnGestureListener.onDrag(offsetX, offsetY); + return mOnGestureListener.onDrag(view, offsetX, offsetY); } private void reset() { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java index dbd215d9c713..59a5b1534990 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java @@ -213,18 +213,18 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL if (!mIsVisible) { return false; } - return mGestureDetector.onTouch(event); + return mGestureDetector.onTouch(v, event); } @Override - public boolean onSingleTap() { + public boolean onSingleTap(View v) { mSingleTapDetected = true; handleSingleTap(); return true; } @Override - public boolean onDrag(float offsetX, float offsetY) { + public boolean onDrag(View v, float offsetX, float offsetY) { moveButton(offsetX, offsetY); return true; } @@ -292,9 +292,12 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL * @param resetPosition if the button position needs be reset */ private void showButton(int mode, boolean resetPosition) { + if (mode != Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { + return; + } if (mMagnificationMode != mode) { mMagnificationMode = mode; - mImageView.setImageResource(getIconResId(mode)); + mImageView.setImageResource(getIconResId(mMagnificationMode)); } if (!mIsVisible) { onConfigurationChanged(mContext.getResources().getConfiguration()); @@ -408,6 +411,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL private static ImageView createView(Context context) { ImageView imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); imageView.setClickable(true); imageView.setFocusable(true); imageView.setAlpha(0f); @@ -415,10 +419,8 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL } @VisibleForTesting - static int getIconResId(int mode) { - return (mode == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) - ? R.drawable.ic_open_in_new_window - : R.drawable.ic_open_in_new_fullscreen; + static int getIconResId(int mode) { // TODO(b/242233514): delete non used param + return R.drawable.ic_open_in_new_window; } private static LayoutParams createLayoutParams(Context context) { @@ -461,4 +463,4 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL new Rect(0, 0, mImageView.getWidth(), mImageView.getHeight()))); }); } -} +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index d7fead16e269..f4701ed50ccc 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -233,6 +233,13 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie } @Override + public void onModeSwitch(int displayId, int newMode) { + if (mWindowMagnificationConnectionImpl != null) { + mWindowMagnificationConnectionImpl.onChangeMagnificationMode(displayId, newMode); + } + } + + @Override public void requestWindowMagnificationConnection(boolean connect) { if (connect) { setWindowMagnificationConnection(); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 1eedae6f01b0..813f4ddbab0b 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -19,8 +19,11 @@ package com.android.systemui.accessibility; import static android.view.WindowInsets.Type.systemGestures; import static android.view.WindowManager.LayoutParams; +import static com.android.systemui.accessibility.WindowMagnificationSettings.MagnificationSize; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP; +import static java.lang.Math.abs; + import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.annotation.NonNull; @@ -41,6 +44,8 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; +import android.os.UserHandle; +import android.provider.Settings; import android.util.Log; import android.util.Range; import android.util.Size; @@ -62,6 +67,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.IRemoteMagnificationAnimationCallback; import android.widget.FrameLayout; +import android.widget.ImageView; import androidx.core.math.MathUtils; @@ -93,6 +99,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(2.0f, 8.0f); private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f; private static final float ANIMATION_BOUNCE_EFFECT_SCALE = 1.05f; + private static final float[] MAGNIFICATION_SCALE_OPTIONS = {1.0f, 1.4f, 1.8f, 2.5f}; private final Context mContext; private final Resources mResources; @@ -145,7 +152,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold // The root of the mirrored content private SurfaceControl mMirrorSurface; - private View mDragView; + private ImageView mDragView; + private ImageView mCloseView; private View mLeftDrag; private View mTopDrag; private View mRightDrag; @@ -162,6 +170,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private final Runnable mWindowInsetChangeRunnable; // MirrorView is the mirror window which displays the magnified content. private View mMirrorView; + private View mMirrorBorderView; private SurfaceView mMirrorSurfaceView; private int mMirrorSurfaceMargin; private int mBorderDragSize; @@ -172,6 +181,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * repositions to the other side. */ private int mButtonRepositionThresholdFromEdge; + // The boundary of magnification frame. private final Rect mMagnificationFrameBoundary = new Rect(); // The top Y of the system gesture rect at the bottom. Set to -1 if it is invalid. @@ -192,6 +202,18 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private boolean mOverlapWithGestureInsets; private boolean mIsDragging; + // Window Magnification Setting view + private WindowMagnificationSettings mWindowMagnificationSettings; + + private static final int MAX_HORIZONTAL_MOVE_ANGLE = 50; + private static final int HORIZONTAL = 1; + private static final int VERTICAL = 0; + private static final double HORIZONTAL_LOCK_BASE = + Math.tan(Math.toRadians(MAX_HORIZONTAL_MOVE_ANGLE)); + + private boolean mAllowDiagonalScrolling = false; + private boolean mEditSizeEnable = false; + @Nullable private MirrorWindowControl mMirrorWindowControl; @@ -223,7 +245,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mWindowBounds = new Rect(mWm.getCurrentWindowMetrics().getBounds()); mResources = mContext.getResources(); - mScale = mResources.getInteger(R.integer.magnification_default_scale); + mScale = Settings.Secure.getFloatForUser(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, + mResources.getInteger(R.integer.magnification_default_scale), + UserHandle.USER_CURRENT); + + mBounceEffectDuration = mResources.getInteger( com.android.internal.R.integer.config_shortAnimTime); updateDimensions(); @@ -241,6 +268,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mGestureDetector = new MagnificationGestureDetector(mContext, handler, this); + mWindowMagnificationSettings = + new WindowMagnificationSettings(mContext, mWindowMagnificationSettingsCallback, + mSfVsyncFrameProvider); + // Initialize listeners. mMirrorViewRunnable = () -> { if (mMirrorView != null) { @@ -326,6 +357,26 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return false; } + private void changeMagnificationSize(@MagnificationSize int index) { + final int initSize = Math.min(mWindowBounds.width(), mWindowBounds.height()) / 3; + int size = (int) (initSize * MAGNIFICATION_SCALE_OPTIONS[index]); + setWindowSize(size, size); + } + + private void setEditMagnifierSizeMode(boolean enable) { + mEditSizeEnable = enable; + applyResourcesValues(); + + if (isWindowVisible()) { + updateDimensions(); + applyTapExcludeRegion(); + } + } + + private void setDiagonalScrolling(boolean enable) { + mAllowDiagonalScrolling = enable; + } + /** * Wraps {@link WindowMagnificationController#deleteWindowMagnification()}} with transition * animation. If the window magnification is enabling, it runs the animation in reverse. @@ -346,6 +397,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold if (!isWindowVisible()) { return; } + + closeMagnificationSettings(); + if (mMirrorSurface != null) { mTransaction.remove(mMirrorSurface).apply(); mMirrorSurface = null; @@ -368,6 +422,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorViewBounds.setEmpty(); mSourceBounds.setEmpty(); updateSystemUIStateIfNeeded(); + setEditMagnifierSizeMode(false); + mContext.unregisterComponentCallbacks(this); // Notify source bounds empty when magnification is deleted. mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, new Rect()); @@ -505,7 +561,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold /** Returns the rotation degree change of two {@link Surface.Rotation} */ private int getDegreeFromRotation(@Surface.Rotation int newRotation, - @Surface.Rotation int oldRotation) { + @Surface.Rotation int oldRotation) { final int rotationDiff = oldRotation - newRotation; final int degree = (rotationDiff + 4) % 4 * 90; return degree; @@ -534,6 +590,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorView = LayoutInflater.from(mContext).inflate(R.layout.window_magnifier_view, null); mMirrorSurfaceView = mMirrorView.findViewById(R.id.surface_view); + mMirrorBorderView = mMirrorView.findViewById(R.id.magnification_inner_border); + // Allow taps to go through to the mirror SurfaceView below. mMirrorSurfaceView.addOnLayoutChangeListener(mMirrorSurfaceViewLayoutChangeListener); @@ -600,6 +658,18 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } } + private void showMagnificationSettings() { + if (mWindowMagnificationSettings != null) { + mWindowMagnificationSettings.showSettingPanel(); + } + } + + private void closeMagnificationSettings() { + if (mWindowMagnificationSettings != null) { + mWindowMagnificationSettings.hideSettingPanel(); + } + } + /** * Sets the window size with given width and height in pixels without changing the * window center. The width or the height will be clamped in the range @@ -668,12 +738,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mTopDrag = mMirrorView.findViewById(R.id.top_handle); mRightDrag = mMirrorView.findViewById(R.id.right_handle); mBottomDrag = mMirrorView.findViewById(R.id.bottom_handle); + mCloseView = mMirrorView.findViewById(R.id.close_button); mDragView.setOnTouchListener(this); mLeftDrag.setOnTouchListener(this); mTopDrag.setOnTouchListener(this); mRightDrag.setOnTouchListener(this); mBottomDrag.setOnTouchListener(this); + mCloseView.setOnTouchListener(this); } /** @@ -743,8 +815,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold @Override public boolean onTouch(View v, MotionEvent event) { if (v == mDragView || v == mLeftDrag || v == mTopDrag || v == mRightDrag - || v == mBottomDrag) { - return mGestureDetector.onTouch(event); + || v == mBottomDrag || v == mCloseView) { + return mGestureDetector.onTouch(v, event); } return false; } @@ -768,6 +840,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold int right = displayFrame.right - (halfWidth - (int) (halfWidth / scale)); int top = displayFrame.top + (halfHeight - (int) (halfHeight / scale)); int bottom = displayFrame.bottom - (halfHeight - (int) (halfHeight / scale)); + mSourceBounds.set(left, top, right, bottom); // SourceBound's center is equal to center[X,Y] but calculated from MagnificationFrame's @@ -950,7 +1023,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * or {@link Float#NaN} to leave unchanged. */ void enableWindowMagnificationInternal(float scale, float centerX, float centerY, - float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY) { + float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY) { if (Float.compare(scale, 1.0f) <= 0) { deleteWindowMagnification(); return; @@ -983,6 +1056,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold if (!isWindowVisible()) { createMirrorWindow(); showControls(); + applyResourcesValues(); } else { modifyWindowMagnification(false); } @@ -997,6 +1071,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold if (mAnimationController.isAnimating() || !isWindowVisible() || mScale == scale) { return; } + enableWindowMagnificationInternal(scale, Float.NaN, Float.NaN); mHandler.removeCallbacks(mUpdateStateDescriptionRunnable); mHandler.postDelayed(mUpdateStateDescriptionRunnable, UPDATE_STATE_DESCRIPTION_DELAY_MS); @@ -1014,19 +1089,42 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold if (mAnimationController.isAnimating() || mMirrorSurfaceView == null) { return; } + + if (!mAllowDiagonalScrolling) { + int direction = selectDirectionForMove(abs(offsetX), abs(offsetY)); + + if (direction == HORIZONTAL) { + offsetY = 0; + } else { + offsetX = 0; + } + } + if (updateMagnificationFramePosition((int) offsetX, (int) offsetY)) { modifyWindowMagnification(false); } } void moveWindowMagnifierToPosition(float positionX, float positionY, - IRemoteMagnificationAnimationCallback callback) { + IRemoteMagnificationAnimationCallback callback) { if (mMirrorSurfaceView == null) { return; } mAnimationController.moveWindowMagnifierToPosition(positionX, positionY, callback); } + private int selectDirectionForMove(float diffX, float diffY) { + int direction = 0; + float result = diffY / diffX; + + if (result <= HORIZONTAL_LOCK_BASE) { + direction = HORIZONTAL; // horizontal move + } else { + direction = VERTICAL; // vertical move + } + return direction; + } + /** * Gets the scale. * @@ -1072,17 +1170,143 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } @Override - public boolean onSingleTap() { - animateBounceEffect(); + public boolean onSingleTap(View view) { + handleSingleTap(view); return true; } @Override - public boolean onDrag(float offsetX, float offsetY) { - move((int) offsetX, (int) offsetY); + public boolean onDrag(View view, float offsetX, float offsetY) { + if (mEditSizeEnable) { + changeWindowSize(view, offsetX, offsetY); + } else { + move((int) offsetX, (int) offsetY); + } + return true; + } + + private void handleSingleTap(View view) { + int id = view.getId(); + if (id == R.id.drag_handle) { + showMagnificationSettings(); + } else if (id == R.id.close_button) { + setEditMagnifierSizeMode(false); + } else { + animateBounceEffect(); + } + } + + private void applyResourcesValues() { + mMirrorBorderView.setBackgroundColor(mResources.getColor(mEditSizeEnable + ? R.color.magnification_border_color_change : R.color.magnification_border_color)); + + if (mEditSizeEnable) { + mDragView.setVisibility(View.GONE); + mCloseView.setVisibility(View.VISIBLE); + } else { + mDragView.setVisibility(View.VISIBLE); + mCloseView.setVisibility(View.GONE); + } + } + + public boolean changeWindowSize(View view, float offsetX, float offsetY) { + boolean bRTL = isRTL(mContext); + final int initSize = Math.min(mWindowBounds.width(), mWindowBounds.height()) / 3; + + final int maxHeightSize = mWindowBounds.height() - 2 * mMirrorSurfaceMargin; + final int maxWidthSize = mWindowBounds.width() - 2 * mMirrorSurfaceMargin; + + Rect tempRect = new Rect(); + tempRect.set(mMagnificationFrame); + + if (view == mLeftDrag) { + if (bRTL) { + tempRect.right += offsetX; + if (tempRect.right > mWindowBounds.width()) { + return false; + } + } else { + tempRect.left += offsetX; + if (tempRect.left < 0) { + return false; + } + } + } else if (view == mRightDrag) { + if (bRTL) { + tempRect.left += offsetX; + if (tempRect.left < 0) { + return false; + } + } else { + tempRect.right += offsetX; + if (tempRect.right > mWindowBounds.width()) { + return false; + } + } + } else if (view == mTopDrag) { + tempRect.top += offsetY; + if (tempRect.top < 0) { + return false; + } + } else if (view == mBottomDrag) { + tempRect.bottom += offsetY; + if (tempRect.bottom > mWindowBounds.height()) { + return false; + } + } + + if (tempRect.width() < initSize || tempRect.height() < initSize + || tempRect.width() > maxWidthSize || tempRect.height() > maxHeightSize) { + return false; + } + + mMagnificationFrame.set(tempRect); + + computeBounceAnimationScale(); + calculateMagnificationFrameBoundary(); + + modifyWindowMagnification(true); return true; } + private static boolean isRTL(Context context) { + Configuration config = context.getResources().getConfiguration(); + if (config == null) { + return false; + } + return (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) + == Configuration.SCREENLAYOUT_LAYOUTDIR_RTL; + } + + private WindowMagnificationSettingsCallback mWindowMagnificationSettingsCallback = + new WindowMagnificationSettingsCallback() { + @Override + public void onSetDiagonalScrolling(boolean enable) { + setDiagonalScrolling(enable); + } + + @Override + public void onModeSwitch(int newMode) { + mWindowMagnifierCallback.onModeSwitch(mDisplayId, newMode); + } + + @Override + public void onSetMagnifierSize(@MagnificationSize int index) { + changeMagnificationSize(index); + } + + @Override + public void onEditMagnifierSizeMode(boolean enable) { + setEditMagnifierSizeMode(enable); + } + + @Override + public void onMagnifierScale(float scale) { + mWindowMagnifierCallback.onPerformScaleAction(mDisplayId, + A11Y_ACTION_SCALE_RANGE.clamp(scale)); + } + }; + @Override public boolean onStart(float x, float y) { mIsDragging = true; @@ -1138,7 +1362,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold pw.println(" mMagnificationFrame:" + (isWindowVisible() ? mMagnificationFrame : "empty")); pw.println(" mSourceBounds:" - + (mSourceBounds.isEmpty() ? "empty" : mSourceBounds)); + + (mSourceBounds.isEmpty() ? "empty" : mSourceBounds)); pw.println(" mSystemGestureTop:" + mSystemGestureTop); pw.println(" mMagnificationFrameOffsetX:" + mMagnificationFrameOffsetX); pw.println(" mMagnificationFrameOffsetY:" + mMagnificationFrameOffsetY); @@ -1149,6 +1373,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); + final AccessibilityAction clickAction = new AccessibilityAction( + AccessibilityAction.ACTION_CLICK.getId(), mContext.getResources().getString( + R.string.magnification_mode_switch_click_label)); + info.addAction(clickAction); + info.setClickable(true); info.addAction( new AccessibilityAction(R.id.accessibility_action_zoom_in, mContext.getString(R.string.accessibility_control_zoom_in))); @@ -1176,7 +1405,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } private boolean performA11yAction(int action) { - if (action == R.id.accessibility_action_zoom_in) { + if (action == AccessibilityAction.ACTION_CLICK.getId()) { + // Simulate tapping the drag view so it opens the Settings. + handleSingleTap(mDragView); + } else if (action == R.id.accessibility_action_zoom_in) { final float scale = mScale + A11Y_CHANGE_SCALE_DIFFERENCE; mWindowMagnifierCallback.onPerformScaleAction(mDisplayId, A11Y_ACTION_SCALE_RANGE.clamp(scale)); @@ -1199,4 +1431,4 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return true; } } -} +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java new file mode 100644 index 000000000000..9cffd5d609a7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java @@ -0,0 +1,592 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility; + +import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + +import android.annotation.IntDef; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.graphics.Insets; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.MathUtils; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.AccessibilityDelegate; +import android.view.ViewGroup; +import android.view.WindowInsets; +import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; +import android.view.WindowMetrics; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.SeekBar; +import android.widget.Switch; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; +import com.android.systemui.R; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Collections; + +/** + * Class to set value about WindowManificationSettings. + */ +class WindowMagnificationSettings implements MagnificationGestureDetector.OnGestureListener { + private static final String TAG = "WindowMagnificationSettings"; + private final Context mContext; + private final AccessibilityManager mAccessibilityManager; + private final WindowManager mWindowManager; + + private final Runnable mWindowInsetChangeRunnable; + private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; + + private final LayoutParams mParams; + @VisibleForTesting + final Rect mDraggableWindowBounds = new Rect(); + private boolean mIsVisible = false; + private final MagnificationGestureDetector mGestureDetector; + private boolean mSingleTapDetected = false; + + private SeekBar mZoomSeekbar; + private Switch mAllowDiagonalScrollingSwitch; + private LinearLayout mPanelView; + private LinearLayout mSettingView; + private LinearLayout mButtonView; + private ImageButton mSmallButton; + private ImageButton mMediumButton; + private ImageButton mLargeButton; + private Button mCloseButton; + private Button mEditButton; + private ImageButton mChangeModeButton; + private boolean mAllowDiagonalScrolling = false; + private static final float A11Y_CHANGE_SCALE_DIFFERENCE = 1.0f; + private static final float A11Y_SCALE_MIN_VALUE = 2.0f; + private WindowMagnificationSettingsCallback mCallback; + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + MagnificationSize.NONE, + MagnificationSize.SMALL, + MagnificationSize.MEDIUM, + MagnificationSize.LARGE, + }) + /** Denotes the Magnification size type. */ + @interface MagnificationSize { + int NONE = 0; + int SMALL = 1; + int MEDIUM = 2; + int LARGE = 3; + } + + @VisibleForTesting + WindowMagnificationSettings(Context context, WindowMagnificationSettingsCallback callback, + SfVsyncFrameCallbackProvider sfVsyncFrameProvider) { + mContext = context; + mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class); + mWindowManager = mContext.getSystemService(WindowManager.class); + mSfVsyncFrameProvider = sfVsyncFrameProvider; + mCallback = callback; + + mAllowDiagonalScrolling = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, 0, + UserHandle.USER_CURRENT) == 1; + + float scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 0, + UserHandle.USER_CURRENT); + + mSettingView = (LinearLayout) View.inflate(context, + R.layout.window_magnification_settings_view, null); + + mSettingView.setClickable(true); + mSettingView.setFocusable(true); + mSettingView.setOnTouchListener(this::onTouch); + + mPanelView = mSettingView.findViewById(R.id.magnifier_panel_view); + mSmallButton = mSettingView.findViewById(R.id.magnifier_small_button); + mMediumButton = mSettingView.findViewById(R.id.magnifier_medium_button); + mLargeButton = mSettingView.findViewById(R.id.magnifier_large_button); + mCloseButton = mSettingView.findViewById(R.id.magnifier_close_button); + mEditButton = mSettingView.findViewById(R.id.magnifier_edit_button); + mChangeModeButton = mSettingView.findViewById(R.id.magnifier_full_button); + + mZoomSeekbar = mSettingView.findViewById(R.id.magnifier_zoom_seekbar); + mZoomSeekbar.setOnSeekBarChangeListener(new ZoomSeekbarChangeListener()); + setSeekbarProgress(scale); + mAllowDiagonalScrollingSwitch = + (Switch) mSettingView.findViewById(R.id.magnifier_horizontal_lock_switch); + mAllowDiagonalScrollingSwitch.setChecked(mAllowDiagonalScrolling); + mAllowDiagonalScrollingSwitch.setOnCheckedChangeListener((view, checked) -> { + toggleDiagonalScrolling(); + }); + + mParams = createLayoutParams(context); + applyResourcesValues(); + + mSmallButton.setAccessibilityDelegate(mButtonDelegate); + mSmallButton.setOnClickListener(mButtonClickListener); + + mMediumButton.setAccessibilityDelegate(mButtonDelegate); + mMediumButton.setOnClickListener(mButtonClickListener); + + mLargeButton.setAccessibilityDelegate(mButtonDelegate); + mLargeButton.setOnClickListener(mButtonClickListener); + + mCloseButton.setAccessibilityDelegate(mButtonDelegate); + mCloseButton.setOnClickListener(mButtonClickListener); + + mChangeModeButton.setAccessibilityDelegate(mButtonDelegate); + mChangeModeButton.setOnClickListener(mButtonClickListener); + + mEditButton.setAccessibilityDelegate(mButtonDelegate); + mEditButton.setOnClickListener(mButtonClickListener); + + mWindowInsetChangeRunnable = this::onWindowInsetChanged; + mSettingView.setOnApplyWindowInsetsListener((v, insets) -> { + // Adds a pending post check to avoiding redundant calculation because this callback + // is sent frequently when the switch icon window dragged by the users. + if (!mSettingView.getHandler().hasCallbacks(mWindowInsetChangeRunnable)) { + mSettingView.getHandler().post(mWindowInsetChangeRunnable); + } + return v.onApplyWindowInsets(insets); + }); + + mGestureDetector = new MagnificationGestureDetector(context, + context.getMainThreadHandler(), this); + } + + private class ZoomSeekbarChangeListener implements SeekBar.OnSeekBarChangeListener { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + float scale = progress * A11Y_CHANGE_SCALE_DIFFERENCE + A11Y_SCALE_MIN_VALUE; + Settings.Secure.putFloatForUser(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale, + UserHandle.USER_CURRENT); + mCallback.onMagnifierScale(scale); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // Do nothing + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // Do nothing + } + } + + private CharSequence formatContentDescription(int viewId) { + if (viewId == R.id.magnifier_small_button) { + return mContext.getResources().getString( + R.string.accessibility_magnification_small); + } else if (viewId == R.id.magnifier_medium_button) { + return mContext.getResources().getString( + R.string.accessibility_magnification_medium); + } else if (viewId == R.id.magnifier_large_button) { + return mContext.getResources().getString( + R.string.accessibility_magnification_large); + } else if (viewId == R.id.magnifier_close_button) { + return mContext.getResources().getString( + R.string.accessibility_magnification_close); + } else if (viewId == R.id.magnifier_edit_button) { + return mContext.getResources().getString( + R.string.accessibility_resize); + } else { + return mContext.getResources().getString( + R.string.magnification_mode_switch_description); + } + } + + private void applyResourcesValues() { + final int padding = mContext.getResources().getDimensionPixelSize( + R.dimen.magnification_switch_button_padding); + + PorterDuffColorFilter filter = new PorterDuffColorFilter(mContext.getColor( + R.color.accessibility_magnifier_icon_color), PorterDuff.Mode.SRC_ATOP); + + mSmallButton.setImageResource(R.drawable.ic_magnification_menu_small); + mSmallButton.setColorFilter(filter); + mSmallButton.setBackgroundResource( + R.drawable.accessibility_magnification_setting_view_btn_bg); + mSmallButton.setPadding(padding, padding, padding, padding); + + mMediumButton.setImageResource(R.drawable.ic_magnification_menu_medium); + mMediumButton.setColorFilter(filter); + mMediumButton.setBackgroundResource( + R.drawable.accessibility_magnification_setting_view_btn_bg); + mMediumButton.setPadding(padding, padding, padding, padding); + + mLargeButton.setImageResource(R.drawable.ic_magnification_menu_large); + mLargeButton.setColorFilter(filter); + mLargeButton.setBackgroundResource( + R.drawable.accessibility_magnification_setting_view_btn_bg); + mLargeButton.setPadding(padding, padding, padding, padding); + + mChangeModeButton.setImageResource(R.drawable.ic_open_in_new_fullscreen); + mChangeModeButton.setColorFilter(filter); + mChangeModeButton.setBackgroundResource( + R.drawable.accessibility_magnification_setting_view_btn_bg); + mChangeModeButton.setPadding(padding, padding, padding, padding); + + mCloseButton.setBackgroundResource( + R.drawable.accessibility_magnification_setting_view_btn_bg); + mEditButton.setBackgroundResource( + R.drawable.accessibility_magnification_setting_view_btn_bg); + } + + private final AccessibilityDelegate mButtonDelegate = new AccessibilityDelegate() { + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + + info.setContentDescription(formatContentDescription(host.getId())); + final AccessibilityAction clickAction = new AccessibilityAction( + AccessibilityAction.ACTION_CLICK.getId(), mContext.getResources().getString( + R.string.magnification_mode_switch_click_label)); + info.addAction(clickAction); + info.setClickable(true); + info.addAction(new AccessibilityAction(R.id.accessibility_action_move_up, + mContext.getString(R.string.accessibility_control_move_up))); + info.addAction(new AccessibilityAction(R.id.accessibility_action_move_down, + mContext.getString(R.string.accessibility_control_move_down))); + info.addAction(new AccessibilityAction(R.id.accessibility_action_move_left, + mContext.getString(R.string.accessibility_control_move_left))); + info.addAction(new AccessibilityAction(R.id.accessibility_action_move_right, + mContext.getString(R.string.accessibility_control_move_right))); + } + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (performA11yAction(host, action)) { + return true; + } + return super.performAccessibilityAction(host, action, args); + } + + private boolean performA11yAction(View view, int action) { + final Rect windowBounds = mWindowManager.getCurrentWindowMetrics().getBounds(); + if (action == AccessibilityAction.ACTION_CLICK.getId()) { + handleSingleTap(view); + } else if (action == R.id.accessibility_action_move_up) { + moveButton(0, -windowBounds.height()); + } else if (action == R.id.accessibility_action_move_down) { + moveButton(0, windowBounds.height()); + } else if (action == R.id.accessibility_action_move_left) { + moveButton(-windowBounds.width(), 0); + } else if (action == R.id.accessibility_action_move_right) { + moveButton(windowBounds.width(), 0); + } else { + return false; + } + return true; + } + }; + + private void applyResourcesValuesWithDensityChanged() { + if (mIsVisible) { + // Reset button to make its window layer always above the mirror window. + hideSettingPanel(); + showSettingPanel(false); + } + } + + private boolean onTouch(View v, MotionEvent event) { + if (!mIsVisible) { + return false; + } + return mGestureDetector.onTouch(v, event); + } + + private View.OnClickListener mButtonClickListener = new View.OnClickListener() { + @Override + public void onClick(View view) { + int id = view.getId(); + if (id == R.id.magnifier_small_button) { + setMagnifierSize(MagnificationSize.SMALL); + } else if (id == R.id.magnifier_medium_button) { + setMagnifierSize(MagnificationSize.MEDIUM); + } else if (id == R.id.magnifier_large_button) { + setMagnifierSize(MagnificationSize.LARGE); + } else if (id == R.id.magnifier_edit_button) { + editMagnifierSizeMode(true); + } else if (id == R.id.magnifier_close_button) { + hideSettingPanel(); + } else if (id == R.id.magnifier_full_button) { + hideSettingPanel(); + toggleMagnificationMode(); + } else { + hideSettingPanel(); + } + } + }; + + @Override + public boolean onSingleTap(View view) { + mSingleTapDetected = true; + handleSingleTap(view); + return true; + } + + @Override + public boolean onDrag(View v, float offsetX, float offsetY) { + moveButton(offsetX, offsetY); + return true; + } + + @Override + public boolean onStart(float x, float y) { + return true; + } + + @Override + public boolean onFinish(float xOffset, float yOffset) { + if (!mSingleTapDetected) { + showSettingPanel(); + } + mSingleTapDetected = false; + return true; + } + + @VisibleForTesting + public ViewGroup getSettingView() { + return mSettingView; + } + + private void moveButton(float offsetX, float offsetY) { + mSfVsyncFrameProvider.postFrameCallback(l -> { + mParams.x += offsetX; + mParams.y += offsetY; + updateButtonViewLayoutIfNeeded(); + }); + } + + public void hideSettingPanel() { + if (!mIsVisible) { + return; + } + + // Reset button status. + mWindowManager.removeView(mSettingView); + mIsVisible = false; + mParams.x = 0; + mParams.y = 0; + + mContext.unregisterReceiver(mScreenOffReceiver); + } + + public void showSettingPanel() { + showSettingPanel(true); + } + + public void setScaleSeekbar(float scale) { + setSeekbarProgress(scale); + } + + private void toggleMagnificationMode() { + mCallback.onModeSwitch(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + } + + /** + * Shows magnification panel for set window magnification. + * When the panel is going to be visible by calling this method, the layout position can be + * reset depending on the flag. + * + * @param resetPosition if the button position needs be reset + */ + private void showSettingPanel(boolean resetPosition) { + if (!mIsVisible) { + if (resetPosition) { + mDraggableWindowBounds.set(getDraggableWindowBounds()); + mParams.x = mDraggableWindowBounds.right; + mParams.y = mDraggableWindowBounds.bottom; + } + + mWindowManager.addView(mSettingView, mParams); + + // Exclude magnification switch button from system gesture area. + setSystemGestureExclusion(); + mIsVisible = true; + } + mContext.registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); + } + + private final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + hideSettingPanel(); + } + }; + + private void setSeekbarProgress(float scale) { + int index = (int) ((scale - A11Y_SCALE_MIN_VALUE) / A11Y_CHANGE_SCALE_DIFFERENCE); + if (index < 0) { + index = 0; + } + mZoomSeekbar.setProgress(index); + } + + void onConfigurationChanged(int configDiff) { + if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0) { + applyResourcesValues(); + return; + } + if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) { + final Rect previousDraggableBounds = new Rect(mDraggableWindowBounds); + mDraggableWindowBounds.set(getDraggableWindowBounds()); + // Keep the Y position with the same height ratio before the window bounds and + // draggable bounds are changed. + final float windowHeightFraction = (float) (mParams.y - previousDraggableBounds.top) + / previousDraggableBounds.height(); + mParams.y = (int) (windowHeightFraction * mDraggableWindowBounds.height()) + + mDraggableWindowBounds.top; + return; + } + if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) { + applyResourcesValuesWithDensityChanged(); + return; + } + if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) { + updateAccessibilityWindowTitle(); + return; + } + } + + private void onWindowInsetChanged() { + final Rect newBounds = getDraggableWindowBounds(); + if (mDraggableWindowBounds.equals(newBounds)) { + return; + } + mDraggableWindowBounds.set(newBounds); + } + + private void updateButtonViewLayoutIfNeeded() { + if (mIsVisible) { + mParams.x = MathUtils.constrain(mParams.x, mDraggableWindowBounds.left, + mDraggableWindowBounds.right); + mParams.y = MathUtils.constrain(mParams.y, mDraggableWindowBounds.top, + mDraggableWindowBounds.bottom); + mWindowManager.updateViewLayout(mSettingView, mParams); + } + } + + private void updateAccessibilityWindowTitle() { + mParams.accessibilityTitle = getAccessibilityWindowTitle(mContext); + if (mIsVisible) { + mWindowManager.updateViewLayout(mSettingView, mParams); + } + } + + private void handleSingleTap(View view) { + int id = view.getId(); + if (id == R.id.magnifier_small_button) { + setMagnifierSize(MagnificationSize.SMALL); + } else if (id == R.id.magnifier_medium_button) { + setMagnifierSize(MagnificationSize.MEDIUM); + } else if (id == R.id.magnifier_large_button) { + setMagnifierSize(MagnificationSize.LARGE); + } else if (id == R.id.magnifier_full_button) { + hideSettingPanel(); + toggleMagnificationMode(); + } else { + hideSettingPanel(); + } + } + + public void editMagnifierSizeMode(boolean enable) { + setEditMagnifierSizeMode(enable); + hideSettingPanel(); + } + + private void setMagnifierSize(@MagnificationSize int index) { + mCallback.onSetMagnifierSize(index); + } + + private void toggleDiagonalScrolling() { + boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, 0, + UserHandle.USER_CURRENT) == 1; + + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, enabled ? 0 : 1, + UserHandle.USER_CURRENT); + + mCallback.onSetDiagonalScrolling(!enabled); + } + + private void setEditMagnifierSizeMode(boolean enable) { + mCallback.onEditMagnifierSizeMode(enable); + } + + private static LayoutParams createLayoutParams(Context context) { + final LayoutParams params = new LayoutParams( + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT, + LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, + LayoutParams.FLAG_NOT_FOCUSABLE, + PixelFormat.TRANSPARENT); + params.gravity = Gravity.TOP | Gravity.START; + params.accessibilityTitle = getAccessibilityWindowTitle(context); + params.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + return params; + } + + private Rect getDraggableWindowBounds() { + final int layoutMargin = mContext.getResources().getDimensionPixelSize( + R.dimen.magnification_switch_button_margin); + final WindowMetrics windowMetrics = mWindowManager.getCurrentWindowMetrics(); + final Insets windowInsets = windowMetrics.getWindowInsets().getInsetsIgnoringVisibility( + WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout()); + final Rect boundRect = new Rect(windowMetrics.getBounds()); + boundRect.offsetTo(0, 0); + boundRect.inset(0, 0, mParams.width, mParams.height); + boundRect.inset(windowInsets); + boundRect.inset(layoutMargin, layoutMargin); + + return boundRect; + } + + private static String getAccessibilityWindowTitle(Context context) { + return context.getString(com.android.internal.R.string.android_system_label); + } + + private void setSystemGestureExclusion() { + mSettingView.post(() -> { + mSettingView.setSystemGestureExclusionRects( + Collections.singletonList( + new Rect(0, 0, mSettingView.getWidth(), mSettingView.getHeight()))); + }); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java new file mode 100644 index 000000000000..22ec65001101 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettingsCallback.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility; + +import static com.android.systemui.accessibility.WindowMagnificationSettings.MagnificationSize; + +/** + * A callback to inform WindowMagnificationController about + * the setting value change or the user interaction. + */ +public interface WindowMagnificationSettingsCallback { + + /** + * Called when change magnification size. + * + * @param index Magnification size index. + * 0 : MagnificationSize.NONE, 1 : MagnificationSize.SMALL, + * 2 : MagnificationSize.MEDIUM, 3: MagnificationSize.LARGE + */ + void onSetMagnifierSize(@MagnificationSize int index); + + /** + * Called when set allow diagonal scrolling. + * + * @param enable Allow diagonal scrolling enable value. + */ + void onSetDiagonalScrolling(boolean enable); + + /** + * Called when change magnification size on free mode. + * + * @param enable Free mode enable value. + */ + void onEditMagnifierSizeMode(boolean enable); + + /** + * Called when set magnification scale. + * + * @param scale Magnification scale value. + */ + void onMagnifierScale(float scale); + + /** + * Called when magnification mode changed. + * + * @param newMode Magnification mode + * 1 : ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, 2 : ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW + */ + void onModeSwitch(int newMode); +} diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java index c334ca664c46..19caaf431e0a 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java @@ -60,4 +60,12 @@ interface WindowMagnifierCallback { * @param displayId The logical display id. */ void onMove(int displayId); + + /** + * Called when magnification mode changed. + * + * @param displayId The logical display id. + * @param newMode Magnification mode. + */ + void onModeSwitch(int displayId, int newMode); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceIconController.kt index 55611f7d7ada..e60d4e10f957 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceIconController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceIconController.kt @@ -18,7 +18,7 @@ package com.android.systemui.biometrics import android.content.Context import android.graphics.drawable.Drawable import android.util.Log -import android.widget.ImageView +import com.airbnb.lottie.LottieAnimationView import com.android.systemui.R import com.android.systemui.biometrics.AuthBiometricView.BiometricState import com.android.systemui.biometrics.AuthBiometricView.STATE_AUTHENTICATED @@ -33,8 +33,8 @@ private const val TAG = "AuthBiometricFaceIconController" /** Face only icon animator for BiometricPrompt. */ class AuthBiometricFaceIconController( - context: Context, - iconView: ImageView + context: Context, + iconView: LottieAnimationView ) : AuthIconController(context, iconView) { // false = dark to light, true = light to dark @@ -76,44 +76,44 @@ class AuthBiometricFaceIconController( if (newState == STATE_AUTHENTICATING_ANIMATING_IN) { showStaticDrawable(R.drawable.face_dialog_pulse_dark_to_light) iconView.contentDescription = context.getString( - R.string.biometric_dialog_face_icon_description_authenticating + R.string.biometric_dialog_face_icon_description_authenticating ) } else if (newState == STATE_AUTHENTICATING) { startPulsing() iconView.contentDescription = context.getString( - R.string.biometric_dialog_face_icon_description_authenticating + R.string.biometric_dialog_face_icon_description_authenticating ) } else if (oldState == STATE_PENDING_CONFIRMATION && newState == STATE_AUTHENTICATED) { animateIconOnce(R.drawable.face_dialog_dark_to_checkmark) iconView.contentDescription = context.getString( - R.string.biometric_dialog_face_icon_description_confirmed + R.string.biometric_dialog_face_icon_description_confirmed ) } else if (lastStateIsErrorIcon && newState == STATE_IDLE) { animateIconOnce(R.drawable.face_dialog_error_to_idle) iconView.contentDescription = context.getString( - R.string.biometric_dialog_face_icon_description_idle + R.string.biometric_dialog_face_icon_description_idle ) } else if (lastStateIsErrorIcon && newState == STATE_AUTHENTICATED) { animateIconOnce(R.drawable.face_dialog_dark_to_checkmark) iconView.contentDescription = context.getString( - R.string.biometric_dialog_face_icon_description_authenticated + R.string.biometric_dialog_face_icon_description_authenticated ) } else if (newState == STATE_ERROR && oldState != STATE_ERROR) { animateIconOnce(R.drawable.face_dialog_dark_to_error) } else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) { animateIconOnce(R.drawable.face_dialog_dark_to_checkmark) iconView.contentDescription = context.getString( - R.string.biometric_dialog_face_icon_description_authenticated + R.string.biometric_dialog_face_icon_description_authenticated ) } else if (newState == STATE_PENDING_CONFIRMATION) { animateIconOnce(R.drawable.face_dialog_wink_from_dark) iconView.contentDescription = context.getString( - R.string.biometric_dialog_face_icon_description_authenticated + R.string.biometric_dialog_face_icon_description_authenticated ) } else if (newState == STATE_IDLE) { showStaticDrawable(R.drawable.face_dialog_idle_static) iconView.contentDescription = context.getString( - R.string.biometric_dialog_face_icon_description_idle + R.string.biometric_dialog_face_icon_description_idle ) } else { Log.w(TAG, "Unhandled state: $newState") diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt index 3e4e573c9531..40d1eff2a887 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt @@ -16,42 +16,43 @@ package com.android.systemui.biometrics +import android.annotation.RawRes import android.content.Context -import android.graphics.drawable.Drawable -import android.widget.ImageView +import com.airbnb.lottie.LottieAnimationView import com.android.systemui.R import com.android.systemui.biometrics.AuthBiometricView.BiometricState -import com.android.systemui.biometrics.AuthBiometricView.STATE_PENDING_CONFIRMATION import com.android.systemui.biometrics.AuthBiometricView.STATE_AUTHENTICATED import com.android.systemui.biometrics.AuthBiometricView.STATE_ERROR import com.android.systemui.biometrics.AuthBiometricView.STATE_HELP +import com.android.systemui.biometrics.AuthBiometricView.STATE_PENDING_CONFIRMATION /** Face/Fingerprint combined icon animator for BiometricPrompt. */ class AuthBiometricFingerprintAndFaceIconController( - context: Context, - iconView: ImageView + context: Context, + iconView: LottieAnimationView ) : AuthBiometricFingerprintIconController(context, iconView) { override val actsAsConfirmButton: Boolean = true override fun shouldAnimateForTransition( - @BiometricState oldState: Int, - @BiometricState newState: Int + @BiometricState oldState: Int, + @BiometricState newState: Int ): Boolean = when (newState) { STATE_PENDING_CONFIRMATION -> true STATE_AUTHENTICATED -> false else -> super.shouldAnimateForTransition(oldState, newState) } + @RawRes override fun getAnimationForTransition( - @BiometricState oldState: Int, - @BiometricState newState: Int - ): Drawable? = when (newState) { + @BiometricState oldState: Int, + @BiometricState newState: Int + ): Int? = when (newState) { STATE_PENDING_CONFIRMATION -> { if (oldState == STATE_ERROR || oldState == STATE_HELP) { - context.getDrawable(R.drawable.fingerprint_dialog_error_to_unlock) + R.raw.fingerprint_dialogue_error_to_unlock_lottie } else { - context.getDrawable(R.drawable.fingerprint_dialog_fp_to_unlock) + R.raw.fingerprint_dialogue_fingerprint_to_unlock_lottie } } STATE_AUTHENTICATED -> null diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt index 606a73a6ac38..589ec0e72b3b 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt @@ -16,10 +16,9 @@ package com.android.systemui.biometrics +import android.annotation.RawRes import android.content.Context -import android.graphics.drawable.AnimatedVectorDrawable -import android.graphics.drawable.Drawable -import android.widget.ImageView +import com.airbnb.lottie.LottieAnimationView import com.android.systemui.R import com.android.systemui.biometrics.AuthBiometricView.BiometricState import com.android.systemui.biometrics.AuthBiometricView.STATE_AUTHENTICATED @@ -32,42 +31,42 @@ import com.android.systemui.biometrics.AuthBiometricView.STATE_PENDING_CONFIRMAT /** Fingerprint only icon animator for BiometricPrompt. */ open class AuthBiometricFingerprintIconController( - context: Context, - iconView: ImageView + context: Context, + iconView: LottieAnimationView ) : AuthIconController(context, iconView) { - var iconLayoutParamsSize = 0 + var iconLayoutParamSize: Pair<Int, Int> = Pair(1, 1) set(value) { if (field == value) { return } - iconView.layoutParams.width = value - iconView.layoutParams.height = value + iconView.layoutParams.width = value.first + iconView.layoutParams.height = value.second field = value } init { - iconLayoutParamsSize = context.resources.getDimensionPixelSize( - R.dimen.biometric_dialog_fingerprint_icon_size - ) + iconLayoutParamSize = Pair(context.resources.getDimensionPixelSize( + R.dimen.biometric_dialog_fingerprint_icon_width), + context.resources.getDimensionPixelSize( + R.dimen.biometric_dialog_fingerprint_icon_height)) } override fun updateIcon(@BiometricState lastState: Int, @BiometricState newState: Int) { val icon = getAnimationForTransition(lastState, newState) ?: return - iconView.setImageDrawable(icon) + if (!(lastState == STATE_AUTHENTICATING_ANIMATING_IN && newState == STATE_AUTHENTICATING)) { + iconView.setAnimation(icon) + } val iconContentDescription = getIconContentDescription(newState) if (iconContentDescription != null) { iconView.contentDescription = iconContentDescription } - (icon as? AnimatedVectorDrawable)?.apply { - reset() - if (shouldAnimateForTransition(lastState, newState)) { - forceAnimationOnUI() - start() - } + iconView.frame = 0 + if (shouldAnimateForTransition(lastState, newState)) { + iconView.playAnimation() } } @@ -86,8 +85,8 @@ open class AuthBiometricFingerprintIconController( } protected open fun shouldAnimateForTransition( - @BiometricState oldState: Int, - @BiometricState newState: Int + @BiometricState oldState: Int, + @BiometricState newState: Int ) = when (newState) { STATE_HELP, STATE_ERROR -> true @@ -97,24 +96,27 @@ open class AuthBiometricFingerprintIconController( else -> false } + @RawRes protected open fun getAnimationForTransition( - @BiometricState oldState: Int, - @BiometricState newState: Int - ): Drawable? { + @BiometricState oldState: Int, + @BiometricState newState: Int + ): Int? { val id = when (newState) { STATE_HELP, - STATE_ERROR -> R.drawable.fingerprint_dialog_fp_to_error + STATE_ERROR -> { + R.raw.fingerprint_dialogue_fingerprint_to_error_lottie + } STATE_AUTHENTICATING_ANIMATING_IN, STATE_AUTHENTICATING -> { if (oldState == STATE_ERROR || oldState == STATE_HELP) { - R.drawable.fingerprint_dialog_error_to_fp + R.raw.fingerprint_dialogue_error_to_fingerprint_lottie } else { - R.drawable.fingerprint_dialog_fp_to_error + R.raw.fingerprint_dialogue_fingerprint_to_error_lottie } } - STATE_AUTHENTICATED -> R.drawable.fingerprint_dialog_fp_to_error + STATE_AUTHENTICATED -> R.raw.fingerprint_dialogue_fingerprint_to_error_lottie else -> return null } - return if (id != null) context.getDrawable(id) else null + return if (id != null) return id else null } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt index 24046f08e489..31baa0ff1154 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt @@ -90,8 +90,9 @@ open class AuthBiometricFingerprintView( fun updateOverrideIconLayoutParamsSize() { udfpsAdapter?.let { - (mIconController as? AuthBiometricFingerprintIconController)?.iconLayoutParamsSize = - it.getSensorDiameter(scaleFactorProvider?.provide() ?: 1.0f) + val sensorDiameter = it.getSensorDiameter(scaleFactorProvider?.provide() ?: 1.0f) + (mIconController as? AuthBiometricFingerprintIconController)?.iconLayoutParamSize = + Pair(sensorDiameter, sensorDiameter) } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt index ce5e600e6a77..15f487b05630 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt @@ -22,15 +22,15 @@ import android.graphics.drawable.Animatable2 import android.graphics.drawable.AnimatedVectorDrawable import android.graphics.drawable.Drawable import android.util.Log -import android.widget.ImageView +import com.airbnb.lottie.LottieAnimationView import com.android.systemui.biometrics.AuthBiometricView.BiometricState private const val TAG = "AuthIconController" /** Controller for animating the BiometricPrompt icon/affordance. */ abstract class AuthIconController( - protected val context: Context, - protected val iconView: ImageView + protected val context: Context, + protected val iconView: LottieAnimationView ) : Animatable2.AnimationCallback() { /** If this controller should ignore events and pause. */ diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index d7ae9ef841bf..e866b9c0bb25 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -41,14 +41,14 @@ import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityManager; import android.widget.Button; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.R; -import com.android.systemui.util.LargeScreenUtils; + +import com.airbnb.lottie.LottieAnimationView; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -133,7 +133,7 @@ public abstract class AuthBiometricView extends LinearLayout { private TextView mSubtitleView; private TextView mDescriptionView; private View mIconHolderView; - protected ImageView mIconView; + protected LottieAnimationView mIconView; protected TextView mIndicatorView; @VisibleForTesting @NonNull AuthIconController mIconController; @@ -824,25 +824,12 @@ public abstract class AuthBiometricView extends LinearLayout { return new AuthDialog.LayoutParams(width, totalHeight); } - private boolean isLargeDisplay() { - return LargeScreenUtils.shouldUseSplitNotificationShade(getResources()); - } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int width = MeasureSpec.getSize(widthMeasureSpec); final int height = MeasureSpec.getSize(heightMeasureSpec); - final boolean isLargeDisplay = isLargeDisplay(); - - final int newWidth; - if (isLargeDisplay) { - // TODO(b/201811580): Unless we can come up with a one-size-fits-all equation, we may - // want to consider moving this to an overlay. - newWidth = 2 * Math.min(width, height) / 3; - } else { - newWidth = Math.min(width, height); - } + final int newWidth = Math.min(width, height); // Use "newWidth" instead, so the landscape dialog width is the same as the portrait // width. diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationGestureDetectorTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationGestureDetectorTest.java index 6f4846a601d9..36ae3c0595ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationGestureDetectorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationGestureDetectorTest.java @@ -19,6 +19,7 @@ package com.android.systemui.accessibility; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -27,6 +28,7 @@ import android.os.Handler; import android.os.SystemClock; import android.testing.AndroidTestingRunner; import android.view.MotionEvent; +import android.view.View; import android.view.ViewConfiguration; import androidx.test.filters.SmallTest; @@ -52,6 +54,7 @@ public class MagnificationGestureDetectorTest extends SysuiTestCase { private int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); private MagnificationGestureDetector mGestureDetector; private MotionEventHelper mMotionEventHelper = new MotionEventHelper(); + private View mSpyView; @Mock private MagnificationGestureDetector.OnGestureListener mListener; @Mock @@ -66,6 +69,7 @@ public class MagnificationGestureDetectorTest extends SysuiTestCase { return null; }).when(mHandler).postAtTime(any(Runnable.class), anyLong()); mGestureDetector = new MagnificationGestureDetector(mContext, mHandler, mListener); + mSpyView = Mockito.spy(new View(mContext)); } @After @@ -79,7 +83,7 @@ public class MagnificationGestureDetectorTest extends SysuiTestCase { final MotionEvent downEvent = mMotionEventHelper.obtainMotionEvent(downTime, downTime, MotionEvent.ACTION_DOWN, ACTION_DOWN_X, ACTION_DOWN_Y); - mGestureDetector.onTouch(downEvent); + mGestureDetector.onTouch(mSpyView, downEvent); mListener.onStart(ACTION_DOWN_X, ACTION_DOWN_Y); } @@ -92,14 +96,14 @@ public class MagnificationGestureDetectorTest extends SysuiTestCase { final MotionEvent upEvent = mMotionEventHelper.obtainMotionEvent(downTime, downTime, MotionEvent.ACTION_UP, ACTION_DOWN_X, ACTION_DOWN_Y); - mGestureDetector.onTouch(downEvent); - mGestureDetector.onTouch(upEvent); + mGestureDetector.onTouch(mSpyView, downEvent); + mGestureDetector.onTouch(mSpyView, upEvent); InOrder inOrder = Mockito.inOrder(mListener); inOrder.verify(mListener).onStart(ACTION_DOWN_X, ACTION_DOWN_Y); - inOrder.verify(mListener).onSingleTap(); + inOrder.verify(mListener).onSingleTap(mSpyView); inOrder.verify(mListener).onFinish(ACTION_DOWN_X, ACTION_DOWN_Y); - verify(mListener, never()).onDrag(anyFloat(), anyFloat()); + verify(mListener, never()).onDrag(eq(mSpyView), anyFloat(), anyFloat()); } @Test @@ -110,10 +114,10 @@ public class MagnificationGestureDetectorTest extends SysuiTestCase { final MotionEvent cancelEvent = mMotionEventHelper.obtainMotionEvent(downTime, downTime, MotionEvent.ACTION_CANCEL, ACTION_DOWN_X, ACTION_DOWN_Y); - mGestureDetector.onTouch(downEvent); - mGestureDetector.onTouch(cancelEvent); + mGestureDetector.onTouch(mSpyView, downEvent); + mGestureDetector.onTouch(mSpyView, cancelEvent); - verify(mListener, never()).onSingleTap(); + verify(mListener, never()).onSingleTap(mSpyView); } @Test @@ -124,10 +128,10 @@ public class MagnificationGestureDetectorTest extends SysuiTestCase { final MotionEvent upEvent = mMotionEventHelper.obtainMotionEvent(downTime, downTime, MotionEvent.ACTION_POINTER_DOWN, ACTION_DOWN_X, ACTION_DOWN_Y); - mGestureDetector.onTouch(downEvent); - mGestureDetector.onTouch(upEvent); + mGestureDetector.onTouch(mSpyView, downEvent); + mGestureDetector.onTouch(mSpyView, upEvent); - verify(mListener, never()).onSingleTap(); + verify(mListener, never()).onSingleTap(mSpyView); } @Test @@ -138,15 +142,15 @@ public class MagnificationGestureDetectorTest extends SysuiTestCase { final MotionEvent upEvent = mMotionEventHelper.obtainMotionEvent(downTime, downTime, MotionEvent.ACTION_UP, ACTION_DOWN_X, ACTION_DOWN_Y); - mGestureDetector.onTouch(downEvent); + mGestureDetector.onTouch(mSpyView, downEvent); // Execute the pending message for stopping single-tap detection. mCancelSingleTapRunnable.run(); - mGestureDetector.onTouch(upEvent); + mGestureDetector.onTouch(mSpyView, upEvent); InOrder inOrder = Mockito.inOrder(mListener); inOrder.verify(mListener).onStart(ACTION_DOWN_X, ACTION_DOWN_Y); inOrder.verify(mListener).onFinish(ACTION_DOWN_X, ACTION_DOWN_Y); - verify(mListener, never()).onSingleTap(); + verify(mListener, never()).onSingleTap(mSpyView); } @Test @@ -160,14 +164,14 @@ public class MagnificationGestureDetectorTest extends SysuiTestCase { final MotionEvent upEvent = mMotionEventHelper.obtainMotionEvent(downTime, downTime, MotionEvent.ACTION_UP, ACTION_DOWN_X, ACTION_DOWN_Y); - mGestureDetector.onTouch(downEvent); - mGestureDetector.onTouch(moveEvent); - mGestureDetector.onTouch(upEvent); + mGestureDetector.onTouch(mSpyView, downEvent); + mGestureDetector.onTouch(mSpyView, moveEvent); + mGestureDetector.onTouch(mSpyView, upEvent); InOrder inOrder = Mockito.inOrder(mListener); inOrder.verify(mListener).onStart(ACTION_DOWN_X, ACTION_DOWN_Y); - inOrder.verify(mListener).onDrag(dragOffset, 0); + inOrder.verify(mListener).onDrag(mSpyView, dragOffset, 0); inOrder.verify(mListener).onFinish(ACTION_DOWN_X, ACTION_DOWN_Y); - verify(mListener, never()).onSingleTap(); + verify(mListener, never()).onSingleTap(mSpyView); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java index bc89da7d504c..00cb49169048 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java @@ -145,7 +145,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { @Test public void removeButton_buttonIsShowing_removeViewAndUnregisterComponentCallbacks() { - mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); mMagnificationModeSwitch.removeButton(); @@ -167,7 +167,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { @Test public void showButton_excludeSystemGestureArea() { - mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class)); } @@ -178,7 +178,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { when(mAccessibilityManager.getRecommendedTimeoutMillis(anyInt(), anyInt())).thenReturn( a11yTimeout); - mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); verify(mAccessibilityManager).getRecommendedTimeoutMillis( DEFAULT_FADE_OUT_ANIMATION_DELAY_MS, AccessibilityManager.FLAG_CONTENT_ICONS @@ -188,7 +188,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { @Test public void showMagnificationButton_windowModeAndFadingOut_verifyAnimationEndAction() { - mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); executeFadeOutAnimation(); // Verify the end action after fade-out. @@ -389,15 +389,15 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { @Test public void initializeA11yNode_showWindowModeButton_expectedValues() { - mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); final AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo(); mSpyImageView.onInitializeAccessibilityNodeInfo(nodeInfo); assertEquals(mContext.getString(R.string.magnification_mode_switch_description), nodeInfo.getContentDescription()); - assertEquals(mContext.getString(R.string.magnification_mode_switch_state_window), - nodeInfo.getStateDescription()); + assertEquals(mContext.getString(R.string.magnification_mode_switch_state_full_screen), + nodeInfo.getStateDescription().toString()); assertThat(nodeInfo.getActionList(), hasItems(new AccessibilityNodeInfo.AccessibilityAction( ACTION_CLICK.getId(), mContext.getResources().getString( @@ -422,18 +422,18 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { @Test public void performClickA11yActions_showWindowModeButton_verifyTapAction() { - mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); resetAndStubMockImageViewAndAnimator(); mSpyImageView.performAccessibilityAction( ACTION_CLICK.getId(), null); - verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); } @Test public void performMoveLeftA11yAction_showButtonAtRightEdge_moveToLeftEdge() { - mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); mSpyImageView.performAccessibilityAction( R.id.accessibility_action_move_left, null); @@ -456,7 +456,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { @Test public void showButton_hasAccessibilityWindowTitle() { - mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); final WindowManager.LayoutParams layoutPrams = mWindowManager.getLayoutParamsFromAttachedView(); @@ -468,7 +468,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { @Test public void showButton_registerComponentCallbacks() { - mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); verify(mContext).registerComponentCallbacks(mMagnificationModeSwitch); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java index a56218b08224..82ae6ff1e945 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java @@ -24,6 +24,7 @@ import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.Display; +import android.view.View; import androidx.test.filters.SmallTest; @@ -46,6 +47,7 @@ public class ModeSwitchesControllerTest extends SysuiTestCase { private FakeSwitchSupplier mSupplier; private MagnificationModeSwitch mModeSwitch; private ModeSwitchesController mModeSwitchesController; + private View mSpyView; @Mock private MagnificationModeSwitch.SwitchListener mListener; @@ -57,6 +59,7 @@ public class ModeSwitchesControllerTest extends SysuiTestCase { mModeSwitchesController = new ModeSwitchesController(mSupplier); mModeSwitchesController.setSwitchListenerDelegate(mListener); mModeSwitch = Mockito.spy(new MagnificationModeSwitch(mContext, mModeSwitchesController)); + mSpyView = Mockito.spy(new View(mContext)); } @After @@ -94,12 +97,12 @@ public class ModeSwitchesControllerTest extends SysuiTestCase { @Test public void testOnSwitchClick_showWindowModeButton_invokeListener() { mModeSwitchesController.showButton(Display.DEFAULT_DISPLAY, - Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); - mModeSwitch.onSingleTap(); + mModeSwitch.onSingleTap(mSpyView); verify(mListener).onSwitch(mContext.getDisplayId(), - Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); } private class FakeSwitchSupplier extends DisplayIdIndexSupplier<MagnificationModeSwitch> { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 3d77d64a7988..69ccc8b88bd8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -19,6 +19,8 @@ package com.android.systemui.accessibility; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.view.Choreographer.FrameCallback; +import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_UP; import static android.view.WindowInsets.Type.systemGestures; import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; @@ -46,6 +48,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.animation.ValueAnimator; +import android.annotation.IdRes; import android.app.Instrumentation; import android.content.Context; import android.content.pm.ActivityInfo; @@ -65,6 +68,7 @@ import android.testing.TestableResources; import android.text.TextUtils; import android.view.Display; import android.view.IWindowSession; +import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceControl; import android.view.View; @@ -126,8 +130,13 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { private WindowMagnificationController mWindowMagnificationController; private Instrumentation mInstrumentation; private final ValueAnimator mValueAnimator = ValueAnimator.ofFloat(0, 1.0f).setDuration(0); + private IWindowSession mWindowSessionSpy; + private View mSpyView; + private View.OnTouchListener mTouchListener; + private MotionEventHelper mMotionEventHelper = new MotionEventHelper(); + @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); @@ -165,6 +174,12 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { verify(mMirrorWindowControl).setWindowDelegate( any(MirrorWindowControl.MirrorWindowDelegate.class)); + mSpyView = Mockito.spy(new View(mContext)); + doAnswer((invocation) -> { + mTouchListener = invocation.getArgument(0); + return null; + }).when(mSpyView).setOnTouchListener( + any(View.OnTouchListener.class)); } @After @@ -702,7 +717,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { }); mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.onSingleTap(); + mWindowMagnificationController.onSingleTap(mSpyView); }); final View mirrorView = mWindowManager.getAttachedView(); @@ -910,6 +925,38 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { assertTrue(magnificationCenterY.get() < bounds.bottom); } + @Test + public void performSingleTap_DragHandle() { + final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds(); + mInstrumentation.runOnMainSync( + () -> { + mWindowMagnificationController.enableWindowMagnificationInternal( + 1.5f, bounds.centerX(), bounds.centerY()); + }); + View dragButton = getInternalView(R.id.drag_handle); + + // Perform a single-tap + final long downTime = SystemClock.uptimeMillis(); + dragButton.dispatchTouchEvent( + obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100)); + dragButton.dispatchTouchEvent( + obtainMotionEvent(downTime, downTime, ACTION_UP, 100, 100)); + + verify(mWindowManager).addView(any(View.class), any()); + } + + private <T extends View> T getInternalView(@IdRes int idRes) { + View mirrorView = mWindowManager.getAttachedView(); + T view = mirrorView.findViewById(idRes); + assertNotNull(view); + return view; + } + + private MotionEvent obtainMotionEvent(long downTime, long eventTime, int action, float x, + float y) { + return mMotionEventHelper.obtainMotionEvent(downTime, eventTime, action, x, y); + } + private CharSequence getAccessibilityWindowTitle() { final View mirrorView = mWindowManager.getAttachedView(); if (mirrorView == null) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java new file mode 100644 index 000000000000..2f94b69b8189 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.annotation.IdRes; +import android.content.Context; +import android.provider.Settings; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityManager; +import android.widget.CompoundButton; + +import androidx.test.filters.SmallTest; + +import com.android.internal.graphics.SfVsyncFrameCallbackProvider; +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +public class WindowMagnificationSettingsTest extends SysuiTestCase { + + private static final int MAGNIFICATION_SIZE_SMALL = 1; + private static final int MAGNIFICATION_SIZE_MEDIUM = 2; + private static final int MAGNIFICATION_SIZE_LARGE = 3; + + private ViewGroup mSettingView; + @Mock + private AccessibilityManager mAccessibilityManager; + @Mock + private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; + @Mock + private WindowMagnificationSettingsCallback mWindowMagnificationSettingsCallback; + private TestableWindowManager mWindowManager; + private WindowMagnificationSettings mWindowMagnificationSettings; + private MotionEventHelper mMotionEventHelper = new MotionEventHelper(); + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mContext = getContext(); + mContext.setTheme(android.R.style.Theme_DeviceDefault_DayNight); + final WindowManager wm = mContext.getSystemService(WindowManager.class); + mWindowManager = spy(new TestableWindowManager(wm)); + mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager); + mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager); + + mWindowMagnificationSettings = new WindowMagnificationSettings(mContext, + mWindowMagnificationSettingsCallback, mSfVsyncFrameProvider); + + mSettingView = mWindowMagnificationSettings.getSettingView(); + } + + @After + public void tearDown() { + mMotionEventHelper.recycleEvents(); + mWindowMagnificationSettings.hideSettingPanel(); + } + + @Test + public void showSettingPanel_hasAccessibilityWindowTitle() { + mWindowMagnificationSettings.showSettingPanel(); + + final WindowManager.LayoutParams layoutPrams = + mWindowManager.getLayoutParamsFromAttachedView(); + assertNotNull(layoutPrams); + assertEquals(getContext().getResources() + .getString(com.android.internal.R.string.android_system_label), + layoutPrams.accessibilityTitle.toString()); + } + + @Test + public void performClick_smallSizeButton_changeMagnifierSizeSmall() { + // Open view + mWindowMagnificationSettings.showSettingPanel(); + + verifyOnSetMagnifierSize(R.id.magnifier_small_button, MAGNIFICATION_SIZE_SMALL); + } + + @Test + public void performClick_mediumSizeButton_changeMagnifierSizeMedium() { + // Open view + mWindowMagnificationSettings.showSettingPanel(); + + verifyOnSetMagnifierSize(R.id.magnifier_medium_button, MAGNIFICATION_SIZE_MEDIUM); + } + + @Test + public void performClick_largeSizeButton_changeMagnifierSizeLarge() { + // Open view + mWindowMagnificationSettings.showSettingPanel(); + + verifyOnSetMagnifierSize(R.id.magnifier_large_button, MAGNIFICATION_SIZE_LARGE); + } + + private void verifyOnSetMagnifierSize(@IdRes int viewId, int expectedSizeIndex) { + View changeSizeButton = getInternalView(viewId); + + // Perform click + changeSizeButton.performClick(); + + verify(mWindowMagnificationSettingsCallback).onSetMagnifierSize(expectedSizeIndex); + } + + + @Test + public void performClick_fullScreenModeButton_setEditMagnifierSizeMode() { + View fullScreenModeButton = getInternalView(R.id.magnifier_full_button); + getInternalView(R.id.magnifier_panel_view); + + // Open view + mWindowMagnificationSettings.showSettingPanel(); + + // Perform click + fullScreenModeButton.performClick(); + + verify(mWindowManager).removeView(mSettingView); + verify(mWindowMagnificationSettingsCallback) + .onModeSwitch(Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + } + + @Test + public void performClick_editButton_setEditMagnifierSizeMode() { + View editButton = getInternalView(R.id.magnifier_edit_button); + + // Open view + mWindowMagnificationSettings.showSettingPanel(); + + // Perform click + editButton.performClick(); + + verify(mWindowMagnificationSettingsCallback).onEditMagnifierSizeMode(true); + verify(mWindowManager).removeView(mSettingView); + } + + @Test + public void performClick_setDiagonalScrollingSwitch_toggleDiagonalScrollingSwitchMode() { + CompoundButton diagonalScrollingSwitch = + getInternalView(R.id.magnifier_horizontal_lock_switch); + final boolean currentCheckedState = diagonalScrollingSwitch.isChecked(); + + // Open view + mWindowMagnificationSettings.showSettingPanel(); + + // Perform click + diagonalScrollingSwitch.performClick(); + + verify(mWindowMagnificationSettingsCallback).onSetDiagonalScrolling(!currentCheckedState); + } + + private <T extends View> T getInternalView(@IdRes int idRes) { + T view = mSettingView.findViewById(idRes); + assertNotNull(view); + return view; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java index ccf2f8b16f8a..e1bd25bd17e7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java @@ -158,6 +158,18 @@ public class WindowMagnificationTest extends SysuiTestCase { } @Test + public void onModeSwitch_enabled_notifyCallback() throws RemoteException { + final int magnificationModeFullScreen = 1; + mCommandQueue.requestWindowMagnificationConnection(true); + waitForIdleSync(); + + mWindowMagnification.onModeSwitch(TEST_DISPLAY, magnificationModeFullScreen); + + verify(mConnectionCallback).onChangeMagnificationMode(TEST_DISPLAY, + magnificationModeFullScreen); + } + + @Test public void overviewProxyIsConnected_noController_resetFlag() { mOverviewProxyListener.onConnectionChanged(true); diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java index 3324c526ecc2..b34482f0964f 100644 --- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java @@ -354,24 +354,16 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ if (supportsFlagForNotImportantViews(info)) { if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) { - mFetchFlags |= - AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS; + mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; } else { - mFetchFlags &= - ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS; + mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; } } if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) { - mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS; + mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; } else { - mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS; - } - - if (mAccessibilityServiceInfo.isAccessibilityTool()) { - mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL; - } else { - mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL; + mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; } mRequestTouchExplorationMode = (info.flags @@ -1530,16 +1522,9 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ return false; } - final boolean includeNotImportantViews = (mFetchFlags - & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0; if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) && !event.isImportantForAccessibility() - && !includeNotImportantViews) { - return false; - } - - if (event.isAccessibilityDataPrivate() - && (mFetchFlags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) == 0) { + && (mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) { return false; } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 6a6d2bb44d48..6eabc981e9fe 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -3693,7 +3693,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; - info.setAccessibilityTool(true); final AccessibilityUserState userState; synchronized (mLock) { userState = getCurrentUserStateLocked(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index e46639b83996..54a7811b6302 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -17507,7 +17507,8 @@ public class ActivityManagerService extends IActivityManager.Stub // sends to the activity. After this race issue between WM/ATMS and AMS is solved, this // workaround can be removed. (b/213288355) if (isNewPending) { - mOomAdjuster.mCachedAppOptimizer.unfreezeProcess(pid); + mOomAdjuster.mCachedAppOptimizer.unfreezeProcess(pid, + OomAdjuster.OOM_ADJ_REASON_ACTIVITY); } // We need to update the network rules for the app coming to the top state so that // it can access network when the device or the app is in a restricted state diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index aaaacef33696..9028eef12aa6 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -36,6 +36,8 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU; +import static com.android.server.am.OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER; +import static com.android.server.am.OomAdjuster.OOM_ADJ_REASON_START_RECEIVER; import android.annotation.NonNull; @@ -348,7 +350,7 @@ public final class BroadcastQueue { // Force an update, even if there are other pending requests, overall it still saves time, // because time(updateOomAdj(N apps)) <= N * time(updateOomAdj(1 app)). mService.enqueueOomAdjTargetLocked(app); - mService.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER); + mService.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_START_RECEIVER); // Tell the application to launch this receiver. maybeReportBroadcastDispatchedEventLocked(r, r.curReceiver.applicationInfo.uid); @@ -976,10 +978,11 @@ public final class BroadcastQueue { filter.receiverList.app.mReceivers.addCurReceiver(r); mService.enqueueOomAdjTargetLocked(r.curApp); mService.updateOomAdjPendingTargetsLocked( - OomAdjuster.OOM_ADJ_REASON_START_RECEIVER); + OOM_ADJ_REASON_START_RECEIVER); } } else if (filter.receiverList.app != null) { - mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(filter.receiverList.app); + mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(filter.receiverList.app, + OOM_ADJ_REASON_START_RECEIVER); } try { @@ -1263,7 +1266,7 @@ public final class BroadcastQueue { // make sure all processes have correct oom and sched // adjustments. mService.updateOomAdjPendingTargetsLocked( - OomAdjuster.OOM_ADJ_REASON_START_RECEIVER); + OOM_ADJ_REASON_START_RECEIVER); } // when we have no more ordered broadcast on this queue, stop logging @@ -1345,7 +1348,7 @@ public final class BroadcastQueue { if (sendResult) { if (r.callerApp != null) { mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily( - r.callerApp); + r.callerApp, OOM_ADJ_REASON_FINISH_RECEIVER); } try { if (DEBUG_BROADCAST) { diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index 363c9d0a963a..653b6026944b 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -37,6 +37,7 @@ import android.provider.DeviceConfig.Properties; import android.provider.Settings; import android.text.TextUtils; import android.util.EventLog; +import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; @@ -904,7 +905,7 @@ public final class CachedAppOptimizer { } if (!enable && opt.isFrozen()) { - unfreezeAppLSP(process); + unfreezeAppLSP(process, OomAdjuster.OOM_ADJ_REASON_NONE); // Set freezerOverride *after* calling unfreezeAppLSP (it resets the flag) opt.setFreezerOverride(true); @@ -1214,11 +1215,11 @@ public final class CachedAppOptimizer { // This will ensure app will be out of the freezer for at least mFreezerDebounceTimeout. @GuardedBy("mAm") - void unfreezeTemporarily(ProcessRecord app) { + void unfreezeTemporarily(ProcessRecord app, @OomAdjuster.OomAdjReason int reason) { if (mUseFreezer) { synchronized (mProcLock) { if (app.mOptRecord.isFrozen() || app.mOptRecord.isPendingFreeze()) { - unfreezeAppLSP(app); + unfreezeAppLSP(app, reason); freezeAppAsyncLSP(app); } } @@ -1244,7 +1245,7 @@ public final class CachedAppOptimizer { } @GuardedBy({"mAm", "mProcLock", "mFreezerLock"}) - void unfreezeAppInternalLSP(ProcessRecord app) { + void unfreezeAppInternalLSP(ProcessRecord app, @OomAdjuster.OomAdjReason int reason) { final int pid = app.getPid(); final ProcessCachedOptimizerRecord opt = app.mOptRecord; if (opt.isPendingFreeze()) { @@ -1325,14 +1326,14 @@ public final class CachedAppOptimizer { mFreezeHandler.obtainMessage(REPORT_UNFREEZE_MSG, pid, (int) Math.min(opt.getFreezeUnfreezeTime() - freezeTime, Integer.MAX_VALUE), - app.processName)); + new Pair<String, Integer>(app.processName, reason))); } } @GuardedBy({"mAm", "mProcLock"}) - void unfreezeAppLSP(ProcessRecord app) { + void unfreezeAppLSP(ProcessRecord app, @OomAdjuster.OomAdjReason int reason) { synchronized (mFreezerLock) { - unfreezeAppInternalLSP(app); + unfreezeAppInternalLSP(app, reason); } } @@ -1343,25 +1344,14 @@ public final class CachedAppOptimizer { * The caller of this function should still trigger updateOomAdj for AMS to unfreeze the app. * @param pid pid of the process to be unfrozen */ - void unfreezeProcess(int pid) { + void unfreezeProcess(int pid, @OomAdjuster.OomAdjReason int reason) { synchronized (mFreezerLock) { ProcessRecord app = mFrozenProcesses.get(pid); if (app == null) { return; } Slog.d(TAG_AM, "quick sync unfreeze " + pid); - try { - freezeBinder(pid, false); - } catch (RuntimeException e) { - Slog.e(TAG_AM, "Unable to quick unfreeze binder for " + pid); - return; - } - - try { - Process.setProcessFrozen(pid, app.uid, false); - } catch (Exception e) { - Slog.e(TAG_AM, "Unable to quick unfreeze " + pid); - } + unfreezeAppLSP(app, reason); } } @@ -1880,9 +1870,11 @@ public final class CachedAppOptimizer { case REPORT_UNFREEZE_MSG: int pid = msg.arg1; int frozenDuration = msg.arg2; - String processName = (String) msg.obj; + Pair<String, Integer> obj = (Pair<String, Integer>) msg.obj; + String processName = obj.first; + int reason = obj.second; - reportUnfreeze(pid, frozenDuration, processName); + reportUnfreeze(pid, frozenDuration, processName, reason); break; default: return; @@ -1893,7 +1885,7 @@ public final class CachedAppOptimizer { private void rescheduleFreeze(final ProcessRecord proc, final String reason) { Slog.d(TAG_AM, "Reschedule freeze for process " + proc.getPid() + " " + proc.processName + " (" + reason + ")"); - unfreezeAppLSP(proc); + unfreezeAppLSP(proc, OomAdjuster.OOM_ADJ_REASON_NONE); freezeAppAsyncLSP(proc); } @@ -1981,7 +1973,8 @@ public final class CachedAppOptimizer { FrameworkStatsLog.APP_FREEZE_CHANGED__ACTION__FREEZE_APP, pid, name, - unfrozenDuration); + unfrozenDuration, + FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__NONE); } try { @@ -2011,12 +2004,13 @@ public final class CachedAppOptimizer { } catch (Exception e) { Slog.e(TAG_AM, "Unable to check file locks for " + name + "(" + pid + "): " + e); synchronized (mProcLock) { - unfreezeAppLSP(proc); + unfreezeAppLSP(proc, OomAdjuster.OOM_ADJ_REASON_NONE); } } } - private void reportUnfreeze(int pid, int frozenDuration, String processName) { + private void reportUnfreeze(int pid, int frozenDuration, String processName, + @OomAdjuster.OomAdjReason int reason) { EventLog.writeEvent(EventLogTags.AM_UNFREEZE, pid, processName); @@ -2027,7 +2021,39 @@ public final class CachedAppOptimizer { FrameworkStatsLog.APP_FREEZE_CHANGED__ACTION__UNFREEZE_APP, pid, processName, - frozenDuration); + frozenDuration, + getUnfreezeReasonCode(reason)); + } + } + + private int getUnfreezeReasonCode(@OomAdjuster.OomAdjReason int oomAdjReason) { + switch (oomAdjReason) { + case OomAdjuster.OOM_ADJ_REASON_ACTIVITY: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__ACTIVITY; + case OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__FINISH_RECEIVER; + case OomAdjuster.OOM_ADJ_REASON_START_RECEIVER: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__START_RECEIVER; + case OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__BIND_SERVICE; + case OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__UNBIND_SERVICE; + case OomAdjuster.OOM_ADJ_REASON_START_SERVICE: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__START_SERVICE; + case OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__GET_PROVIDER; + case OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__REMOVE_PROVIDER; + case OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__UI_VISIBILITY; + case OomAdjuster.OOM_ADJ_REASON_ALLOWLIST: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__ALLOWLIST; + case OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__PROCESS_BEGIN; + case OomAdjuster.OOM_ADJ_REASON_PROCESS_END: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__PROCESS_END; + default: + return FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON__NONE; } } @@ -2041,7 +2067,7 @@ public final class CachedAppOptimizer { ProcessRecord app = mFrozenProcesses.get(pid); if (app != null) { Slog.i(TAG_AM, app.processName + " (" + pid + ") holds blocking file lock"); - unfreezeAppLSP(app); + unfreezeAppLSP(app, OomAdjuster.OOM_ADJ_REASON_NONE); } } } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 8759f23065f0..12aa66b84d85 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -448,7 +448,7 @@ public class OomAdjuster { */ @GuardedBy({"mService", "mProcLock"}) private boolean performUpdateOomAdjLSP(ProcessRecord app, int cachedAdj, - ProcessRecord topApp, long now) { + ProcessRecord topApp, long now, @OomAdjReason int oomAdjReason) { if (app.getThread() == null) { return false; } @@ -492,7 +492,7 @@ public class OomAdjuster { } } - return applyOomAdjLSP(app, false, now, SystemClock.elapsedRealtime()); + return applyOomAdjLSP(app, false, now, SystemClock.elapsedRealtime(), oomAdjReason); } /** @@ -592,7 +592,7 @@ public class OomAdjuster { mPendingProcessSet.remove(app); app.mOptRecord.setLastOomAdjChangeReason(oomAdjReason); boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp, - SystemClock.uptimeMillis()); + SystemClock.uptimeMillis(), oomAdjReason); // The 'app' here itself might or might not be in the cycle, for example, // the case A <=> B vs. A -> B <=> C; anyway, if we spot a cycle here, re-compute them. if (!success || (wasCached == state.isCached() && oldAdj != ProcessList.INVALID_ADJ @@ -645,7 +645,7 @@ public class OomAdjuster { processes.add(app); assignCachedAdjIfNecessary(processes); applyOomAdjLSP(app, false, SystemClock.uptimeMillis(), - SystemClock.elapsedRealtime()); + SystemClock.elapsedRealtime(), oomAdjReason); } mTmpProcessList.clear(); mService.mOomAdjProfiler.oomAdjEnded(); @@ -941,7 +941,8 @@ public class OomAdjuster { mNumNonCachedProcs = 0; mNumCachedHiddenProcs = 0; - boolean allChanged = updateAndTrimProcessLSP(now, nowElapsed, oldTime, activeUids); + boolean allChanged = updateAndTrimProcessLSP(now, nowElapsed, oldTime, activeUids, + oomAdjReason); mNumServiceProcs = mNewNumServiceProcs; if (mService.mAlwaysFinishActivities) { @@ -1119,7 +1120,7 @@ public class OomAdjuster { @GuardedBy({"mService", "mProcLock"}) private boolean updateAndTrimProcessLSP(final long now, final long nowElapsed, - final long oldTime, final ActiveUids activeUids) { + final long oldTime, final ActiveUids activeUids, @OomAdjReason int oomAdjReason) { ArrayList<ProcessRecord> lruList = mProcessList.getLruProcessesLOSP(); final int numLru = lruList.size(); @@ -1147,7 +1148,7 @@ public class OomAdjuster { if (!app.isKilledByAm() && app.getThread() != null) { // We don't need to apply the update for the process which didn't get computed if (state.getCompletedAdjSeq() == mAdjSeq) { - applyOomAdjLSP(app, true, now, nowElapsed); + applyOomAdjLSP(app, true, now, nowElapsed, oomAdjReason); } final ProcessServiceRecord psr = app.mServices; @@ -2640,7 +2641,7 @@ public class OomAdjuster { /** Applies the computed oomadj, procstate and sched group values and freezes them in set* */ @GuardedBy({"mService", "mProcLock"}) private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now, - long nowElapsed) { + long nowElapsed, @OomAdjReason int oomAdjReson) { boolean success = true; final ProcessStateRecord state = app.mState; final UidRecord uidRec = app.getUidRecord(); @@ -2799,7 +2800,7 @@ public class OomAdjuster { changes |= ActivityManagerService.ProcessChangeItem.CHANGE_ACTIVITIES; } - updateAppFreezeStateLSP(app); + updateAppFreezeStateLSP(app, oomAdjReson); if (state.getReportedProcState() != state.getCurProcState()) { state.setReportedProcState(state.getCurProcState()); @@ -3160,7 +3161,7 @@ public class OomAdjuster { } @GuardedBy({"mService", "mProcLock"}) - private void updateAppFreezeStateLSP(ProcessRecord app) { + private void updateAppFreezeStateLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) { if (!mCachedAppOptimizer.useFreezer()) { return; } @@ -3172,7 +3173,7 @@ public class OomAdjuster { final ProcessCachedOptimizerRecord opt = app.mOptRecord; // if an app is already frozen and shouldNotFreeze becomes true, immediately unfreeze if (opt.isFrozen() && opt.shouldNotFreeze()) { - mCachedAppOptimizer.unfreezeAppLSP(app); + mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason); return; } @@ -3182,7 +3183,7 @@ public class OomAdjuster { && !opt.shouldNotFreeze()) { mCachedAppOptimizer.freezeAppAsyncLSP(app); } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) { - mCachedAppOptimizer.unfreezeAppLSP(app); + mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason); } } } diff --git a/services/core/java/com/android/server/notification/ReviewNotificationPermissionsJobService.java b/services/core/java/com/android/server/notification/ReviewNotificationPermissionsJobService.java index fde45f71a844..acb36a0660cb 100644 --- a/services/core/java/com/android/server/notification/ReviewNotificationPermissionsJobService.java +++ b/services/core/java/com/android/server/notification/ReviewNotificationPermissionsJobService.java @@ -42,10 +42,6 @@ public class ReviewNotificationPermissionsJobService extends JobService { */ public static void scheduleJob(Context context, long rescheduleTimeMillis) { JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); - // if the job already exists for some reason, cancel & reschedule - if (jobScheduler.getPendingJob(JOB_ID) != null) { - jobScheduler.cancel(JOB_ID); - } ComponentName component = new ComponentName( context, ReviewNotificationPermissionsJobService.class); JobInfo newJob = new JobInfo.Builder(JOB_ID, component) diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java index 5b8f473bad2e..c129f37b6d16 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java @@ -1256,6 +1256,18 @@ public class ParsingPackageUtils { return input.success(pkg.addPermission(result.getResult())); } + private int parseMinOrMaxSdkVersion(TypedArray sa, int attr, int defaultValue) { + int val = defaultValue; + TypedValue peekVal = sa.peekValue(attr); + if (peekVal != null) { + if (peekVal.type >= TypedValue.TYPE_FIRST_INT + && peekVal.type <= TypedValue.TYPE_LAST_INT) { + val = peekVal.data; + } + } + return val; + } + private ParseResult<ParsingPackage> parseUsesPermission(ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser) throws IOException, XmlPullParserException { @@ -1266,14 +1278,13 @@ public class ParsingPackageUtils { String name = sa.getNonResourceString( R.styleable.AndroidManifestUsesPermission_name); - int maxSdkVersion = 0; - TypedValue val = sa.peekValue( - R.styleable.AndroidManifestUsesPermission_maxSdkVersion); - if (val != null) { - if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) { - maxSdkVersion = val.data; - } - } + int minSdkVersion = parseMinOrMaxSdkVersion(sa, + R.styleable.AndroidManifestUsesPermission_minSdkVersion, + Integer.MIN_VALUE); + + int maxSdkVersion = parseMinOrMaxSdkVersion(sa, + R.styleable.AndroidManifestUsesPermission_maxSdkVersion, + Integer.MAX_VALUE); final ArraySet<String> requiredFeatures = new ArraySet<>(); String feature = sa.getNonConfigurationString( @@ -1338,7 +1349,8 @@ public class ParsingPackageUtils { return success; } - if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) { + if (Build.VERSION.RESOURCES_SDK_INT < minSdkVersion + || Build.VERSION.RESOURCES_SDK_INT > maxSdkVersion) { return success; } diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java index 35e6db947ac3..1b39add3b421 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java @@ -24,13 +24,17 @@ import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; -import static com.android.server.job.controllers.FlexibilityController.DEFAULT_FLEXIBILITY_DEADLINE; -import static com.android.server.job.controllers.FlexibilityController.FcConstants.KEY_FLEXIBILITY_ENABLED; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_DEADLINE_PROXIMITY_LIMIT; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FALLBACK_FLEXIBILITY_DEADLINE; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FLEXIBILITY_ENABLED; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS; import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW; import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING; import static com.android.server.job.controllers.JobStatus.CONSTRAINT_FLEXIBLE; import static com.android.server.job.controllers.JobStatus.CONSTRAINT_IDLE; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -76,7 +80,7 @@ public class FlexibilityControllerTest { private FlexibilityController mFlexibilityController; private DeviceConfig.Properties.Builder mDeviceConfigPropertiesBuilder; private JobStore mJobStore; - private FlexibilityController.FcConstants mFcConstants; + private FlexibilityController.FcConfig mFcConfig; @Mock private AlarmManager mAlarmManager; @@ -129,8 +133,9 @@ public class FlexibilityControllerTest { // Initialize real objects. mFlexibilityController = new FlexibilityController(mJobSchedulerService, mPrefetchController); - mFcConstants = mFlexibilityController.getFcConstants(); + mFcConfig = mFlexibilityController.getFcConfig(); + setDeviceConfigLong(KEY_DEADLINE_PROXIMITY_LIMIT, 0L); setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, true); } @@ -145,7 +150,25 @@ public class FlexibilityControllerTest { mDeviceConfigPropertiesBuilder.setBoolean(key, val); synchronized (mFlexibilityController.mLock) { mFlexibilityController.prepareForUpdatedConstantsLocked(); - mFcConstants.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key); + mFcConfig.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key); + mFlexibilityController.onConstantsUpdatedLocked(); + } + } + + private void setDeviceConfigLong(String key, Long val) { + mDeviceConfigPropertiesBuilder.setLong(key, val); + synchronized (mFlexibilityController.mLock) { + mFlexibilityController.prepareForUpdatedConstantsLocked(); + mFcConfig.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key); + mFlexibilityController.onConstantsUpdatedLocked(); + } + } + + private void setDeviceConfigString(String key, String val) { + mDeviceConfigPropertiesBuilder.setString(key, val); + synchronized (mFlexibilityController.mLock) { + mFlexibilityController.prepareForUpdatedConstantsLocked(); + mFcConfig.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key); mFlexibilityController.onConstantsUpdatedLocked(); } } @@ -162,6 +185,81 @@ public class FlexibilityControllerTest { return js; } + /** + * Tests that the there are equally many percents to drop constraints as there are constraints + */ + @Test + public void testDefaultVariableValues() { + assertEquals(FlexibilityController.NUM_FLEXIBLE_CONSTRAINTS, + mFlexibilityController.mFcConfig.DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS.length + ); + } + + @Test + public void testOnConstantsUpdated_DefaultFlexibility() { + JobStatus js = createJobStatus("testDefaultFlexibilityConfig", createJob(0)); + assertFalse(mFlexibilityController.isFlexibilitySatisfiedLocked(js)); + setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, false); + assertTrue(mFlexibilityController.isFlexibilitySatisfiedLocked(js)); + setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, true); + assertFalse(mFlexibilityController.isFlexibilitySatisfiedLocked(js)); + } + + @Test + public void testOnConstantsUpdated_DeadlineProximity() { + JobStatus js = createJobStatus("testDeadlineProximityConfig", createJob(0)); + setDeviceConfigLong(KEY_DEADLINE_PROXIMITY_LIMIT, Long.MAX_VALUE); + mFlexibilityController.mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js); + assertEquals(0, js.getNumRequiredFlexibleConstraints()); + } + + @Test + public void testOnConstantsUpdated_FallbackDeadline() { + JobStatus js = createJobStatus("testFallbackDeadlineConfig", createJob(0)); + assertEquals(DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS, + mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0L)); + setDeviceConfigLong(KEY_FALLBACK_FLEXIBILITY_DEADLINE, 100L); + assertEquals(100L, mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0L)); + } + + @Test + public void testOnConstantsUpdated_PercentsToDropConstraints() { + JobInfo.Builder jb = createJob(0).setOverrideDeadline(100L); + JobStatus js = createJobStatus("testPercentsToDropConstraintsConfig", jb); + assertEquals(150L, + mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); + setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "10,20,30,40"); + assertArrayEquals( + mFlexibilityController.mFcConfig.PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, + new int[] {10, 20, 30, 40}); + assertEquals(110L, + mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); + js.adjustNumRequiredFlexibleConstraints(-1); + assertEquals(120L, + mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); + js.adjustNumRequiredFlexibleConstraints(-1); + assertEquals(130L, + mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); + } + + @Test + public void testOnConstantsUpdated_PercentsToDropConstraintsInvalidValues() { + JobInfo.Builder jb = createJob(0).setOverrideDeadline(100L); + JobStatus js = createJobStatus("testPercentsToDropConstraintsConfig", jb); + js.enqueueTime = 100L; + assertEquals(150L, + mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); + setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "10,20a,030,40"); + assertEquals(150L, + mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); + setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "10,40"); + assertEquals(150L, + mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); + setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "50,40,10,40"); + assertEquals(150L, + mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); + } + @Test public void testGetNextConstraintDropTimeElapsedLocked() { long nextTimeToDropNumConstraints; @@ -347,7 +445,7 @@ public class FlexibilityControllerTest { // no deadline jb = createJob(0); js = createJobStatus("time", jb); - assertEquals(100L + DEFAULT_FLEXIBILITY_DEADLINE, + assertEquals(100L + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS, mFlexibilityController.getLifeCycleEndElapsedLocked(js, 100L)); } @@ -431,8 +529,8 @@ public class FlexibilityControllerTest { assertEquals(0, trackedJobs.get(3).size()); JobSchedulerService.sElapsedRealtimeClock = - Clock.fixed(Instant.ofEpochMilli( - (DEFAULT_FLEXIBILITY_DEADLINE / 2) + HOUR_IN_MILLIS), ZoneOffset.UTC); + Clock.fixed(Instant.ofEpochMilli((DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 2) + + HOUR_IN_MILLIS), ZoneOffset.UTC); flexTracker.resetJobNumDroppedConstraints(jobs[0]); assertEquals(0, trackedJobs.get(0).size()); @@ -577,19 +675,76 @@ public class FlexibilityControllerTest { } @Test + public void testResetJobNumDroppedConstraints() { + JobInfo.Builder jb = createJob(22).setOverrideDeadline(100L); + JobStatus js = createJobStatus("testResetJobNumDroppedConstraints", jb); + js.adjustNumRequiredFlexibleConstraints(3); + + mFlexibilityController.mFlexibilityTracker.add(js); + + assertEquals(3, js.getNumRequiredFlexibleConstraints()); + assertEquals(0, js.getNumDroppedFlexibleConstraints()); + assertEquals(1, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size()); + + JobSchedulerService.sElapsedRealtimeClock = + Clock.fixed(Instant.ofEpochMilli(155L), ZoneOffset.UTC); + + mFlexibilityController.mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1); + + assertEquals(2, js.getNumRequiredFlexibleConstraints()); + assertEquals(1, js.getNumDroppedFlexibleConstraints()); + assertEquals(1, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size()); + + mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js); + + assertEquals(2, js.getNumRequiredFlexibleConstraints()); + assertEquals(1, js.getNumDroppedFlexibleConstraints()); + assertEquals(1, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size()); + + JobSchedulerService.sElapsedRealtimeClock = + Clock.fixed(Instant.ofEpochMilli(140L), ZoneOffset.UTC); + + mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js); + + assertEquals(3, js.getNumRequiredFlexibleConstraints()); + assertEquals(0, js.getNumDroppedFlexibleConstraints()); + assertEquals(1, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size()); + + JobSchedulerService.sElapsedRealtimeClock = + Clock.fixed(Instant.ofEpochMilli(175), ZoneOffset.UTC); + + mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js); + + assertEquals(0, js.getNumRequiredFlexibleConstraints()); + assertEquals(3, js.getNumDroppedFlexibleConstraints()); + + JobSchedulerService.sElapsedRealtimeClock = + Clock.fixed(Instant.ofEpochMilli(165L), ZoneOffset.UTC); + + mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js); + + assertEquals(1, js.getNumRequiredFlexibleConstraints()); + assertEquals(2, js.getNumDroppedFlexibleConstraints()); + assertEquals(1, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(1).size()); + } + + @Test public void testOnPrefetchCacheUpdated() { ArraySet<JobStatus> jobs = new ArraySet<JobStatus>(); JobInfo.Builder jb = createJob(22).setPrefetch(true); JobStatus js = createJobStatus("onPrefetchCacheUpdated", jb); jobs.add(js); when(mPrefetchController.getLaunchTimeThresholdMs()).thenReturn(7 * HOUR_IN_MILLIS); - - mFlexibilityController.maybeStartTrackingJobLocked(js, null); - mFlexibilityController.mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1); - when(mPrefetchController.getNextEstimatedLaunchTimeLocked(js)).thenReturn( 1150L + mFlexibilityController.mConstants.PREFETCH_FORCE_BATCH_RELAX_THRESHOLD_MS); + mFlexibilityController.maybeStartTrackingJobLocked(js, null); + JobSchedulerService.sElapsedRealtimeClock = Clock.fixed(Instant.ofEpochMilli(150L), ZoneOffset.UTC); @@ -604,9 +759,9 @@ public class FlexibilityControllerTest { assertEquals(1150L, mFlexibilityController.getLifeCycleEndElapsedLocked(js, 150L)); assertEquals(0, mFlexibilityController.getCurPercentOfLifecycleLocked(js)); - assertEquals(0, js.getNumDroppedFlexibleConstraints()); assertEquals(650L, mFlexibilityController .getNextConstraintDropTimeElapsedLocked(js)); + assertEquals(3, js.getNumRequiredFlexibleConstraints()); assertEquals(1, mFlexibilityController .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size()); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java index 4a16874c7acf..842b23c91e41 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java @@ -17,13 +17,13 @@ package com.android.server.accessibility; +import static android.view.accessibility.AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_ANCESTORS; import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST; import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_DEPTH_FIRST; import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS_HYBRID; import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS; import static android.view.accessibility.AccessibilityNodeInfo.FLAG_PREFETCH_UNINTERRUPTIBLE; -import static android.view.accessibility.AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS; import static android.view.accessibility.AccessibilityNodeInfo.ROOT_NODE_ID; import static org.junit.Assert.assertEquals; @@ -528,8 +528,7 @@ public class AccessibilityInteractionControllerNodeRequestsTest { // different client that holds different fetch flags for TextView1. sendNodeRequestToController(nodeId, mMockClientCallback2, mMockClient2InteractionId, - FLAG_PREFETCH_SIBLINGS - | FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS + FLAG_PREFETCH_SIBLINGS | FLAG_INCLUDE_NOT_IMPORTANT_VIEWS | FLAG_PREFETCH_ANCESTORS); } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ReviewNotificationPermissionsJobServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ReviewNotificationPermissionsJobServiceTest.java index 5a4ce5da676e..3a6c0eb8fc2a 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ReviewNotificationPermissionsJobServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ReviewNotificationPermissionsJobServiceTest.java @@ -20,10 +20,8 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.app.job.JobInfo; import android.app.job.JobParameters; @@ -75,9 +73,6 @@ public class ReviewNotificationPermissionsJobServiceTest extends UiServiceTestCa @Test public void testScheduleJob() { - // if asked, the job doesn't currently exist yet - when(mMockJobScheduler.getPendingJob(anyInt())).thenReturn(null); - final int rescheduleTimeMillis = 350; // arbitrary number // attempt to schedule the job diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 789399205f23..2453f3cafaaa 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -140,6 +140,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -234,6 +235,54 @@ public class TelephonyManager { public static final int NETWORK_SELECTION_MODE_AUTO = 1; public static final int NETWORK_SELECTION_MODE_MANUAL = 2; + /** + * Reasons for Radio being powered off. + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"RADIO_POWER_REASON_"}, + value = { + RADIO_POWER_REASON_USER, + RADIO_POWER_REASON_THERMAL, + RADIO_POWER_REASON_CARRIER, + RADIO_POWER_REASON_NEARBY_DEVICE}) + public @interface RadioPowerReason {} + + /** + * This reason is used when users want to turn off radio, e.g., users turn on airplane mode. + * + * @hide + */ + @SystemApi + public static final int RADIO_POWER_REASON_USER = 0; + /** + * This reason is used when radio needs to be turned off due to thermal. + * + * @hide + */ + @SystemApi + public static final int RADIO_POWER_REASON_THERMAL = 1; + /** + * This reason is used when carriers want to turn off radio. A privileged app can request to + * turn off radio via the system service + * {@link com.android.carrierdefaultapp.CaptivePortalLoginActivity}, which subsequently calls + * the system APIs {@link requestRadioPowerOffForReason} and + * {@link clearRadioPowerOffForReason}. + * + * @hide + */ + @SystemApi + public static final int RADIO_POWER_REASON_CARRIER = 2; + /** + * Used to reduce power on a battery-constrained device when Telephony services are available + * via a paired device which is nearby. + * + * @hide + */ + @SystemApi + public static final int RADIO_POWER_REASON_NEARBY_DEVICE = 3; + /** The otaspMode passed to PhoneStateListener#onOtaspChanged */ /** @hide */ static public final int OTASP_UNINITIALIZED = 0; @@ -10506,34 +10555,155 @@ public class TelephonyManager { } } - /** @hide */ + /** + * @deprecated - use the APIs {@link requestRadioPowerOffForReason} and + * {@link clearRadioPowerOffForReason}. + * + * @hide + */ + @Deprecated @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) public boolean setRadio(boolean turnOn) { + boolean result = true; + try { + if (turnOn) { + clearRadioPowerOffForReason(RADIO_POWER_REASON_USER); + } else { + requestRadioPowerOffForReason(RADIO_POWER_REASON_USER); + } + } catch (Exception e) { + String calledFunction = + turnOn ? "clearRadioPowerOffForReason" : "requestRadioPowerOffForReason"; + Log.e(TAG, "Error calling " + calledFunction, e); + result = false; + } + return result; + } + + /** + * @deprecated - use the APIs {@link requestRadioPowerOffForReason} and + * {@link clearRadioPowerOffForReason}. + * + * @hide + */ + @Deprecated + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) + public boolean setRadioPower(boolean turnOn) { + boolean result = true; + try { + if (turnOn) { + clearRadioPowerOffForReason(RADIO_POWER_REASON_USER); + } else { + requestRadioPowerOffForReason(RADIO_POWER_REASON_USER); + } + } catch (Exception e) { + String calledFunction = + turnOn ? "clearRadioPowerOffForReason" : "requestRadioPowerOffForReason"; + Log.e(TAG, "Error calling " + calledFunction, e); + result = false; + } + return result; + } + + /** + * Vote on powering off the radio for a reason. The radio will be turned on only when there is + * no reason to power it off. When any of the voters want to power it off, it will be turned + * off. In case of emergency, the radio will be turned on even if there are some reasons for + * powering it off, and these radio off votes will be cleared. + * Multiple apps can vote for the same reason and the last vote will take effect. Each app is + * responsible for its vote. A powering-off vote of a reason will be maintained until it is + * cleared by calling {@link clearRadioPowerOffForReason} for that reason, or an emergency call + * is made, or the device is rebooted. When an app comes backup from a crash, it needs to make + * sure if its vote is as expected. An app can use the API {@link getRadioPowerOffReasons} to + * check its vote. + * + * @param reason The reason for powering off radio. + * @throws SecurityException if the caller does not have MODIFY_PHONE_STATE permission. + * @throws IllegalStateException if the Telephony service is not currently available. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) + public void requestRadioPowerOffForReason(@RadioPowerReason int reason) { try { ITelephony telephony = getITelephony(); - if (telephony != null) - return telephony.setRadio(turnOn); + if (telephony != null) { + if (!telephony.requestRadioPowerOffForReason(getSubId(), reason)) { + throw new IllegalStateException("Telephony service is not available."); + } + } else { + throw new IllegalStateException("Telephony service is null."); + } } catch (RemoteException e) { - Log.e(TAG, "Error calling ITelephony#setRadio", e); + Log.e(TAG, "Error calling ITelephony#requestRadioPowerOffForReason", e); + e.rethrowAsRuntimeException(); } - return false; } - /** @hide */ + /** + * Remove the vote on powering off the radio for a reason, as requested by + * {@link requestRadioPowerOffForReason}. + * + * @param reason The reason for powering off radio. + * @throws SecurityException if the caller does not have MODIFY_PHONE_STATE permission. + * @throws IllegalStateException if the Telephony service is not currently available. + * + * @hide + */ @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) - public boolean setRadioPower(boolean turnOn) { + public void clearRadioPowerOffForReason(@RadioPowerReason int reason) { try { ITelephony telephony = getITelephony(); - if (telephony != null) - return telephony.setRadioPower(turnOn); + if (telephony != null) { + if (!telephony.clearRadioPowerOffForReason(getSubId(), reason)) { + throw new IllegalStateException("Telephony service is not available."); + } + } else { + throw new IllegalStateException("Telephony service is null."); + } } catch (RemoteException e) { - Log.e(TAG, "Error calling ITelephony#setRadioPower", e); + Log.e(TAG, "Error calling ITelephony#clearRadioPowerOffForReason", e); + e.rethrowAsRuntimeException(); } - return false; + } + + /** + * Get reasons for powering off radio, as requested by {@link requestRadioPowerOffForReason}. + * If the reason set is empty, the radio is on in all cases. + * + * @return Set of reasons for powering off radio. + * @throws SecurityException if the caller does not have READ_PRIVILEGED_PHONE_STATE permission. + * @throws IllegalStateException if the Telephony service is not currently available. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) + @NonNull + public Set<Integer> getRadioPowerOffReasons() { + Set<Integer> result = new HashSet<>(); + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + result.addAll(telephony.getRadioPowerOffReasons(getSubId(), + mContext.getOpPackageName(), mContext.getAttributionTag())); + } else { + throw new IllegalStateException("Telephony service is null."); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#getRadioPowerOffReasons", e); + e.rethrowAsRuntimeException(); + } + return result; } /** @@ -13037,20 +13207,21 @@ public class TelephonyManager { * * @param enabled control enable or disable radio. * @see #resetAllCarrierActions() + * + * @deprecated - use the APIs {@link requestRadioPowerOffForReason} and + * {@link clearRadioPowerOffForReason}. + * * @hide */ + @Deprecated @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @RequiresFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) public void setRadioEnabled(boolean enabled) { - try { - ITelephony service = getITelephony(); - if (service != null) { - service.carrierActionSetRadioEnabled( - getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enabled); - } - } catch (RemoteException e) { - Log.e(TAG, "Error calling ITelephony#carrierActionSetRadioEnabled", e); + if (enabled) { + clearRadioPowerOffForReason(RADIO_POWER_REASON_CARRIER); + } else { + requestRadioPowerOffForReason(RADIO_POWER_REASON_CARRIER); } } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 0ce6b14ce3b0..42cac6630506 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -244,6 +244,44 @@ interface ITelephony { boolean setRadioPower(boolean turnOn); /** + * Vote on powering off the radio for a reason. The radio will be turned on only when there is + * no reason to power it off. When any of the voters want to power it off, it will be turned + * off. In case of emergency, the radio will be turned on even if there are some reasons for + * powering it off, and these radio off votes will be cleared. + * Multiple apps can vote for the same reason and the last vote will take effect. Each app is + * responsible for its vote. A powering-off vote of a reason will be maintained until it is + * cleared by calling {@link clearRadioPowerOffForReason} for that reason, or an emergency call + * is made, or the device is rebooted. When an app comes backup from a crash, it needs to make + * sure if its vote is as expected. An app can use the API {@link getRadioPowerOffReasons} to + * check its vote. + * + * @param subId The subscription ID. + * @param reason The reason for powering off radio. + * @return true on success and false on failure. + */ + boolean requestRadioPowerOffForReason(int subId, int reason); + + /** + * Remove the vote on powering off the radio for a reasonas, requested by + * {@link requestRadioPowerOffForReason}. + * + * @param subId The subscription ID. + * @param reason The reason for powering off radio. + * @return true on success and false on failure. + */ + boolean clearRadioPowerOffForReason(int subId, int reason); + + /** + * Get reasons for powering off radio, as requested by {@link requestRadioPowerOffForReason}. + * + * @param subId The subscription ID. + * @param callingPackage The package making the call. + * @param callingFeatureId The feature in the package. + * @return List of reasons for powering off radio. + */ + List getRadioPowerOffReasons(int subId, String callingPackage, String callingFeatureId); + + /** * This method has been removed due to security and stability issues. */ @UnsupportedAppUsage diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java index 1664746f4636..a2842b6e214d 100644 --- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java +++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java @@ -22,6 +22,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Align; import android.os.Bundle; +import android.os.Trace; import android.util.AttributeSet; import android.util.Log; import android.view.Display; @@ -30,9 +31,9 @@ import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.os.Trace; import android.view.Window; import android.view.WindowManager; + import java.math.RoundingMode; import java.text.DecimalFormat; @@ -280,6 +281,17 @@ public class TouchLatencyActivity extends Activity { WindowManager.LayoutParams params = w.getAttributes(); int modeIndex = (mCurrentModeIndex + 1) % mDisplayModes.length; + while (modeIndex != mCurrentModeIndex) { + // skip modes with different resolutions + Mode currentMode = mDisplayModes[mCurrentModeIndex]; + Mode nextMode = mDisplayModes[modeIndex]; + if (currentMode.getPhysicalHeight() == nextMode.getPhysicalHeight() + && currentMode.getPhysicalWidth() == nextMode.getPhysicalWidth()) { + break; + } + modeIndex = (modeIndex + 1) % mDisplayModes.length; + } + params.preferredDisplayModeId = mDisplayModes[modeIndex].getModeId(); w.setAttributes(params); diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt index d19f4cceeaaf..12f3a1659313 100644 --- a/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt +++ b/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt @@ -19,6 +19,8 @@ package com.google.android.lint import com.android.tools.lint.client.api.IssueRegistry import com.android.tools.lint.client.api.Vendor import com.android.tools.lint.detector.api.CURRENT_API +import com.google.android.lint.aidl.EnforcePermissionDetector +import com.google.android.lint.aidl.ManualPermissionCheckDetector import com.google.android.lint.parcel.SaferParcelChecker import com.google.auto.service.AutoService @@ -36,6 +38,7 @@ class AndroidFrameworkIssueRegistry : IssueRegistry() { CallingSettingsNonUserGetterMethodsDetector.ISSUE_NON_USER_GETTER_CALLED, EnforcePermissionDetector.ISSUE_MISSING_ENFORCE_PERMISSION, EnforcePermissionDetector.ISSUE_MISMATCHING_ENFORCE_PERMISSION, + ManualPermissionCheckDetector.ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION, SaferParcelChecker.ISSUE_UNSAFE_API_USAGE, PackageVisibilityDetector.ISSUE_PACKAGE_NAME_NO_PACKAGE_VISIBILITY_FILTERS ) diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt b/tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt new file mode 100644 index 000000000000..82eb8ed8f621 --- /dev/null +++ b/tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint + +import com.google.android.lint.model.Method + +const val CLASS_STUB = "Stub" +const val CLASS_CONTEXT = "android.content.Context" +const val CLASS_ACTIVITY_MANAGER_SERVICE = "com.android.server.am.ActivityManagerService" +const val CLASS_ACTIVITY_MANAGER_INTERNAL = "android.app.ActivityManagerInternal" + +// Enforce permission APIs +val ENFORCE_PERMISSION_METHODS = listOf( + Method(CLASS_CONTEXT, "checkPermission"), + Method(CLASS_CONTEXT, "checkCallingPermission"), + Method(CLASS_CONTEXT, "checkCallingOrSelfPermission"), + Method(CLASS_CONTEXT, "enforcePermission"), + Method(CLASS_CONTEXT, "enforceCallingPermission"), + Method(CLASS_CONTEXT, "enforceCallingOrSelfPermission"), + Method(CLASS_ACTIVITY_MANAGER_SERVICE, "checkPermission"), + Method(CLASS_ACTIVITY_MANAGER_INTERNAL, "enforceCallingPermission") +) diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/PackageVisibilityDetector.kt b/tools/lint/checks/src/main/java/com/google/android/lint/PackageVisibilityDetector.kt index 192dba17dd5b..48540b1da565 100644 --- a/tools/lint/checks/src/main/java/com/google/android/lint/PackageVisibilityDetector.kt +++ b/tools/lint/checks/src/main/java/com/google/android/lint/PackageVisibilityDetector.kt @@ -30,13 +30,13 @@ import com.android.tools.lint.detector.api.interprocedural.CallGraphResult import com.android.tools.lint.detector.api.interprocedural.searchForPaths import com.intellij.psi.PsiAnonymousClass import com.intellij.psi.PsiMethod +import java.util.LinkedList import org.jetbrains.uast.UCallExpression import org.jetbrains.uast.UElement import org.jetbrains.uast.UMethod import org.jetbrains.uast.UParameter import org.jetbrains.uast.USimpleNameReferenceExpression import org.jetbrains.uast.visitor.AbstractUastVisitor -import java.util.LinkedList /** * A lint checker to detect potential package visibility issues for system's APIs. APIs working @@ -362,14 +362,18 @@ class PackageVisibilityDetector : Detector(), SourceCodeScanner { name: String, matchArgument: Boolean = true, checkCaller: Boolean = false - ): this(clazz, name) { + ) : this(clazz, name) { this.matchArgument = matchArgument this.checkCaller = checkCaller } constructor( method: PsiMethod - ): this(method.containingClass?.qualifiedName ?: "", method.name) + ) : this(method.containingClass?.qualifiedName ?: "", method.name) + + constructor( + method: com.google.android.lint.model.Method + ) : this(method.clazz, method.name) } /** @@ -380,7 +384,7 @@ class PackageVisibilityDetector : Detector(), SourceCodeScanner { val typeName: String, val parameterName: String ) { - constructor(uParameter: UParameter): this( + constructor(uParameter: UParameter) : this( uParameter.type.canonicalText, uParameter.name.lowercase() ) @@ -405,19 +409,13 @@ class PackageVisibilityDetector : Detector(), SourceCodeScanner { // A valid call path list needs to contain a start node and a sink node private const val VALID_CALL_PATH_NODES_SIZE = 2 - private const val CLASS_STUB = "Stub" private const val CLASS_STRING = "java.lang.String" private const val CLASS_PACKAGE_MANAGER = "android.content.pm.PackageManager" private const val CLASS_IPACKAGE_MANAGER = "android.content.pm.IPackageManager" private const val CLASS_APPOPS_MANAGER = "android.app.AppOpsManager" - private const val CLASS_CONTEXT = "android.content.Context" private const val CLASS_BINDER = "android.os.Binder" private const val CLASS_PACKAGE_MANAGER_INTERNAL = "android.content.pm.PackageManagerInternal" - private const val CLASS_ACTIVITY_MANAGER_SERVICE = - "com.android.server.am.ActivityManagerService" - private const val CLASS_ACTIVITY_MANAGER_INTERNAL = - "android.app.ActivityManagerInternal" // Patterns of package name parameter private val PACKAGE_NAME_PATTERNS = setOf( @@ -455,16 +453,9 @@ class PackageVisibilityDetector : Detector(), SourceCodeScanner { ) // Enforce permission APIs - private val ENFORCE_PERMISSION_METHODS = listOf( - Method(CLASS_CONTEXT, "checkPermission"), - Method(CLASS_CONTEXT, "checkCallingPermission"), - Method(CLASS_CONTEXT, "checkCallingOrSelfPermission"), - Method(CLASS_CONTEXT, "enforcePermission"), - Method(CLASS_CONTEXT, "enforceCallingPermission"), - Method(CLASS_CONTEXT, "enforceCallingOrSelfPermission"), - Method(CLASS_ACTIVITY_MANAGER_SERVICE, "checkPermission"), - Method(CLASS_ACTIVITY_MANAGER_INTERNAL, "enforceCallingPermission") - ) + private val ENFORCE_PERMISSION_METHODS = + com.google.android.lint.ENFORCE_PERMISSION_METHODS + .map(PackageVisibilityDetector::Method) private val BYPASS_STUBS = listOf( "android.content.pm.IPackageDataObserver.Stub", diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/checks/src/main/java/com/google/android/lint/aidl/Constants.kt new file mode 100644 index 000000000000..8ee3763e5079 --- /dev/null +++ b/tools/lint/checks/src/main/java/com/google/android/lint/aidl/Constants.kt @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint.aidl + +const val ANNOTATION_ENFORCE_PERMISSION = "android.annotation.EnforcePermission" +const val ANNOTATION_REQUIRES_NO_PERMISSION = "android.annotation.RequiresNoPermission" +const val ANNOTATION_PERMISSION_MANUALLY_ENFORCED = "android.annotation.PermissionManuallyEnforced" + +val AIDL_PERMISSION_ANNOTATIONS = listOf( + ANNOTATION_ENFORCE_PERMISSION, + ANNOTATION_REQUIRES_NO_PERMISSION, + ANNOTATION_PERMISSION_MANUALLY_ENFORCED +) + +const val IINTERFACE_INTERFACE = "android.os.IInterface" + +/** + * If a non java (e.g. c++) backend is enabled, the @EnforcePermission + * annotation cannot be used. At time of writing, the mechanism + * is not implemented for non java backends. + * TODO: b/242564874 (have lint know which interfaces have the c++ backend enabled) + * rather than hard coding this list? + */ +val EXCLUDED_CPP_INTERFACES = listOf( + "AdbTransportType", + "FingerprintAndPairDevice", + "IAdbCallback", + "IAdbManager", + "PairDevice", + "IStatsBootstrapAtomService", + "StatsBootstrapAtom", + "StatsBootstrapAtomValue", + "FixedSizeArrayExample", + "PlaybackTrackMetadata", + "RecordTrackMetadata", + "SinkMetadata", + "SourceMetadata", + "IUpdateEngineStable", + "IUpdateEngineStableCallback", + "AudioCapabilities", + "ConfidenceLevel", + "ModelParameter", + "ModelParameterRange", + "Phrase", + "PhraseRecognitionEvent", + "PhraseRecognitionExtra", + "PhraseSoundModel", + "Properties", + "RecognitionConfig", + "RecognitionEvent", + "RecognitionMode", + "RecognitionStatus", + "SoundModel", + "SoundModelType", + "Status", + "IThermalService", + "IPowerManager", + "ITunerResourceManager" +) diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt b/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt index 9f216189ad62..a415217105a8 100644 --- a/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt +++ b/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionDetector.kt @@ -14,15 +14,15 @@ * limitations under the License. */ -package com.google.android.lint +package com.google.android.lint.aidl import com.android.tools.lint.client.api.UElementHandler import com.android.tools.lint.detector.api.AnnotationInfo import com.android.tools.lint.detector.api.AnnotationOrigin import com.android.tools.lint.detector.api.AnnotationUsageInfo import com.android.tools.lint.detector.api.AnnotationUsageType -import com.android.tools.lint.detector.api.ConstantEvaluator import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.ConstantEvaluator import com.android.tools.lint.detector.api.Detector import com.android.tools.lint.detector.api.Implementation import com.android.tools.lint.detector.api.Issue @@ -34,8 +34,8 @@ import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiClass import com.intellij.psi.PsiMethod import org.jetbrains.uast.UAnnotation -import org.jetbrains.uast.UElement import org.jetbrains.uast.UClass +import org.jetbrains.uast.UElement import org.jetbrains.uast.UMethod /** @@ -54,12 +54,11 @@ import org.jetbrains.uast.UMethod */ class EnforcePermissionDetector : Detector(), SourceCodeScanner { - val ENFORCE_PERMISSION = "android.annotation.EnforcePermission" val BINDER_CLASS = "android.os.Binder" val JAVA_OBJECT = "java.lang.Object" override fun applicableAnnotations(): List<String> { - return listOf(ENFORCE_PERMISSION) + return listOf(ANNOTATION_ENFORCE_PERMISSION) } override fun getApplicableUastTypes(): List<Class<out UElement>> { @@ -99,8 +98,8 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { overriddenMethod: PsiMethod, checkEquivalence: Boolean = true ) { - val overridingAnnotation = overridingMethod.getAnnotation(ENFORCE_PERMISSION) - val overriddenAnnotation = overriddenMethod.getAnnotation(ENFORCE_PERMISSION) + val overridingAnnotation = overridingMethod.getAnnotation(ANNOTATION_ENFORCE_PERMISSION) + val overriddenAnnotation = overriddenMethod.getAnnotation(ANNOTATION_ENFORCE_PERMISSION) val location = context.getLocation(element) val overridingClass = overridingMethod.parent as PsiClass val overriddenClass = overriddenMethod.parent as PsiClass @@ -133,8 +132,8 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { extendedClass: PsiClass, checkEquivalence: Boolean = true ) { - val newAnnotation = newClass.getAnnotation(ENFORCE_PERMISSION) - val extendedAnnotation = extendedClass.getAnnotation(ENFORCE_PERMISSION) + val newAnnotation = newClass.getAnnotation(ANNOTATION_ENFORCE_PERMISSION) + val extendedAnnotation = extendedClass.getAnnotation(ANNOTATION_ENFORCE_PERMISSION) val location = context.getLocation(element) val newClassName = newClass.qualifiedName @@ -180,7 +179,7 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner { override fun createUastHandler(context: JavaContext): UElementHandler { return object : UElementHandler() { override fun visitAnnotation(node: UAnnotation) { - if (node.qualifiedName != ENFORCE_PERMISSION) { + if (node.qualifiedName != ANNOTATION_ENFORCE_PERMISSION) { return } val method = node.uastParent as? UMethod diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt b/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt new file mode 100644 index 000000000000..510611161ea8 --- /dev/null +++ b/tools/lint/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint.aidl + +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Location +import com.intellij.psi.PsiVariable +import org.jetbrains.uast.UCallExpression +import org.jetbrains.uast.ULiteralExpression +import org.jetbrains.uast.UQualifiedReferenceExpression +import org.jetbrains.uast.USimpleNameReferenceExpression +import org.jetbrains.uast.asRecursiveLogString + +/** + * Helper ADT class that facilitates the creation of lint auto fixes + * + * Handles "Single" permission checks that should be migrated to @EnforcePermission(...), as well as consecutive checks + * that should be migrated to @EnforcePermission(allOf={...}) + * + * TODO: handle anyOf style annotations + */ +sealed class EnforcePermissionFix { + abstract fun locations(): List<Location> + abstract fun javaAnnotationParameter(): String + + fun javaAnnotation(): String = "@$ANNOTATION_ENFORCE_PERMISSION(${javaAnnotationParameter()})" + + companion object { + fun fromCallExpression(callExpression: UCallExpression, context: JavaContext): SingleFix = + SingleFix( + getPermissionCheckLocation(context, callExpression), + getPermissionCheckArgumentValue(callExpression) + ) + + fun maybeAddManifestPrefix(permissionName: String): String = + if (permissionName.contains(".")) permissionName + else "android.Manifest.permission.$permissionName" + + /** + * Given a permission check, get its proper location + * so that a lint fix can remove the entire expression + */ + private fun getPermissionCheckLocation( + context: JavaContext, + callExpression: UCallExpression + ): + Location { + val javaPsi = callExpression.javaPsi!! + return Location.create( + context.file, + javaPsi.containingFile?.text, + javaPsi.textRange.startOffset, + // unfortunately the element doesn't include the ending semicolon + javaPsi.textRange.endOffset + 1 + ) + } + + /** + * Given a permission check and an argument, + * pull out the permission value that is being used + */ + private fun getPermissionCheckArgumentValue( + callExpression: UCallExpression, + argumentPosition: Int = 0 + ): String { + + val identifier = when ( + val argument = callExpression.valueArguments.getOrNull(argumentPosition) + ) { + is UQualifiedReferenceExpression -> when (val selector = argument.selector) { + is USimpleNameReferenceExpression -> + ((selector.resolve() as PsiVariable).computeConstantValue() as String) + + else -> throw RuntimeException( + "Couldn't resolve argument: ${selector.asRecursiveLogString()}" + ) + } + + is USimpleNameReferenceExpression -> ( + (argument.resolve() as PsiVariable).computeConstantValue() as String) + + is ULiteralExpression -> argument.value as String + + else -> throw RuntimeException( + "Couldn't resolve argument: ${argument?.asRecursiveLogString()}" + ) + } + + return identifier.substringAfterLast(".") + } + } +} + +data class SingleFix(val location: Location, val permissionName: String) : EnforcePermissionFix() { + override fun locations(): List<Location> = listOf(this.location) + override fun javaAnnotationParameter(): String = maybeAddManifestPrefix(this.permissionName) +} +data class AllOfFix(val checks: List<SingleFix>) : EnforcePermissionFix() { + override fun locations(): List<Location> = this.checks.map { it.location } + override fun javaAnnotationParameter(): String = + "allOf={${ + this.checks.joinToString(", ") { maybeAddManifestPrefix(it.permissionName) } + }}" +} diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/aidl/ManualPermissionCheckDetector.kt b/tools/lint/checks/src/main/java/com/google/android/lint/aidl/ManualPermissionCheckDetector.kt new file mode 100644 index 000000000000..2cea39423f1d --- /dev/null +++ b/tools/lint/checks/src/main/java/com/google/android/lint/aidl/ManualPermissionCheckDetector.kt @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint.aidl + +import com.android.tools.lint.client.api.UElementHandler +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.google.android.lint.CLASS_STUB +import com.google.android.lint.ENFORCE_PERMISSION_METHODS +import com.intellij.psi.PsiAnonymousClass +import org.jetbrains.uast.UBlockExpression +import org.jetbrains.uast.UCallExpression +import org.jetbrains.uast.UElement +import org.jetbrains.uast.UIfExpression +import org.jetbrains.uast.UMethod +import org.jetbrains.uast.UQualifiedReferenceExpression + +/** + * Looks for methods implementing generated AIDL interface stubs + * that can have simple permission checks migrated to + * @EnforcePermission annotations + * + * TODO: b/242564870 (enable parse and autoFix of .aidl files) + */ +@Suppress("UnstableApiUsage") +class ManualPermissionCheckDetector : Detector(), SourceCodeScanner { + override fun getApplicableUastTypes(): List<Class<out UElement?>> = + listOf(UMethod::class.java) + + override fun createUastHandler(context: JavaContext): UElementHandler = AidlStubHandler(context) + + private inner class AidlStubHandler(val context: JavaContext) : UElementHandler() { + override fun visitMethod(node: UMethod) { + val interfaceName = getContainingAidlInterface(node) + .takeUnless(EXCLUDED_CPP_INTERFACES::contains) ?: return + val body = (node.uastBody as? UBlockExpression) ?: return + val fix = accumulateSimplePermissionCheckFixes(body) ?: return + + val javaRemoveFixes = fix.locations().map { + fix() + .replace() + .reformat(true) + .range(it) + .with("") + .autoFix() + .build() + } + + val javaAnnotateFix = fix() + .annotate(fix.javaAnnotation()) + .range(context.getLocation(node)) + .autoFix() + .build() + + val message = + "$interfaceName permission check can be converted to @EnforcePermission annotation" + + context.report( + ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION, + fix.locations().last(), + message, + fix().composite(*javaRemoveFixes.toTypedArray(), javaAnnotateFix) + ) + } + + /** + * Walk the expressions in the method, looking for simple permission checks. + * + * If a single permission check is found at the beginning of the method, + * this should be migrated to @EnforcePermission(value). + * + * If multiple consecutive permission checks are found, + * these should be migrated to @EnforcePermission(allOf={value1, value2, ...}) + * + * As soon as something other than a permission check is encountered, stop looking, + * as some other business logic is happening that prevents an automated fix. + */ + private fun accumulateSimplePermissionCheckFixes(methodBody: UBlockExpression): + EnforcePermissionFix? { + val singleFixes = mutableListOf<SingleFix>() + for (expression in methodBody.expressions) { + singleFixes.add(getPermissionCheckFix(expression) ?: break) + } + return when (singleFixes.size) { + 0 -> null + 1 -> singleFixes[0] + else -> AllOfFix(singleFixes) + } + } + + /** + * If an expression boils down to a permission check, return + * the helper for creating a lint auto fix to @EnforcePermission + */ + private fun getPermissionCheckFix(startingExpression: UElement?): + SingleFix? { + return when (startingExpression) { + is UQualifiedReferenceExpression -> getPermissionCheckFix( + startingExpression.selector + ) + + is UIfExpression -> getPermissionCheckFix(startingExpression.condition) + + is UCallExpression -> { + return if (isPermissionCheck(startingExpression)) + EnforcePermissionFix.fromCallExpression(startingExpression, context) + else null + } + + else -> null + } + } + } + + companion object { + + private val EXPLANATION = """ + Whenever possible, method implementations of AIDL interfaces should use the @EnforcePermission + annotation to declare the permissions to be enforced. The verification code is then + generated by the AIDL compiler, which also takes care of annotating the generated java + code. + + This reduces the risk of bugs around these permission checks (that often become vulnerabilities). + It also enables easier auditing and review. + + Please migrate to an @EnforcePermission annotation. (See: go/aidl-enforce-howto) + """.trimIndent() + + @JvmField + val ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION = Issue.create( + id = "UseEnforcePermissionAnnotation", + briefDescription = "Manual permission check can be @EnforcePermission annotation", + explanation = EXPLANATION, + category = Category.SECURITY, + priority = 5, + severity = Severity.WARNING, + implementation = Implementation( + ManualPermissionCheckDetector::class.java, + Scope.JAVA_FILE_SCOPE + ), + enabledByDefault = false, // TODO: enable once b/241171714 is resolved + ) + + private fun isPermissionCheck(callExpression: UCallExpression): Boolean { + val method = callExpression.resolve() ?: return false + val className = method.containingClass?.qualifiedName + return ENFORCE_PERMISSION_METHODS.any { + it.clazz == className && it.name == method.name + } + } + + /** + * given a UMethod, determine if this method is + * an entrypoint to an interface generated by AIDL, + * returning the interface name if so + */ + fun getContainingAidlInterface(node: UMethod): String? { + if (!isInClassCalledStub(node)) return null + for (superMethod in node.findSuperMethods()) { + for (extendsInterface in superMethod.containingClass?.extendsList?.referenceElements + ?: continue) { + if (extendsInterface.qualifiedName == IINTERFACE_INTERFACE) { + return superMethod.containingClass?.name + } + } + } + return null + } + + private fun isInClassCalledStub(node: UMethod): Boolean { + (node.containingClass as? PsiAnonymousClass)?.let { + return it.baseClassReference.referenceName == CLASS_STUB + } + return node.containingClass?.extendsList?.referenceElements?.any { + it.referenceName == CLASS_STUB + } ?: false + } + } +} diff --git a/lowpan/java/android/net/lowpan/ILowpanEnergyScanCallback.aidl b/tools/lint/checks/src/main/java/com/google/android/lint/model/Method.kt index f09dbe3d077e..3939b6109eaa 100644 --- a/lowpan/java/android/net/lowpan/ILowpanEnergyScanCallback.aidl +++ b/tools/lint/checks/src/main/java/com/google/android/lint/model/Method.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,13 @@ * limitations under the License. */ -package android.net.lowpan; +package com.google.android.lint.model -/** {@hide} */ -interface ILowpanEnergyScanCallback { - oneway void onEnergyScanResult(int channel, int rssi); - oneway void onEnergyScanFinished(); +/** + * Data class to represent a Method + */ +data class Method(val clazz: String, val name: String) { + override fun toString(): String { + return "$clazz#$name" + } } diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/EnforcePermissionDetectorTest.kt b/tools/lint/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt index 2cfc3fbcefcb..3c1d1e8e8a59 100644 --- a/tools/lint/checks/src/test/java/com/google/android/lint/EnforcePermissionDetectorTest.kt +++ b/tools/lint/checks/src/test/java/com/google/android/lint/aidl/EnforcePermissionDetectorTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.google.android.lint +package com.google.android.lint.aidl import com.android.tools.lint.checks.infrastructure.LintDetectorTest import com.android.tools.lint.checks.infrastructure.TestFile diff --git a/tools/lint/checks/src/test/java/com/google/android/lint/aidl/ManualPermissionCheckDetectorTest.kt b/tools/lint/checks/src/test/java/com/google/android/lint/aidl/ManualPermissionCheckDetectorTest.kt new file mode 100644 index 000000000000..1a1c6bc77785 --- /dev/null +++ b/tools/lint/checks/src/test/java/com/google/android/lint/aidl/ManualPermissionCheckDetectorTest.kt @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.lint.aidl + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue + +@Suppress("UnstableApiUsage") +class ManualPermissionCheckDetectorTest : LintDetectorTest() { + override fun getDetector(): Detector = ManualPermissionCheckDetector() + override fun getIssues(): List<Issue> = listOf( + ManualPermissionCheckDetector + .ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION + ) + + override fun lint(): TestLintTask = super.lint().allowMissingSdk() + + fun testClass() { + lint().files( + java( + """ + import android.content.Context; + import android.test.ITest; + public class Foo extends ITest.Stub { + private Context mContext; + @Override + public void test() throws android.os.RemoteException { + mContext.enforceCallingOrSelfPermission("android.Manifest.permission.READ_CONTACTS", "foo"); + } + } + """ + ).indented(), + *stubs + ) + .run() + .expect( + """ + src/Foo.java:7: Warning: ITest permission check can be converted to @EnforcePermission annotation [UseEnforcePermissionAnnotation] + mContext.enforceCallingOrSelfPermission("android.Manifest.permission.READ_CONTACTS", "foo"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 0 errors, 1 warnings + """ + ) + .expectFixDiffs( + """ + Fix for src/Foo.java line 7: Annotate with @EnforcePermission: + @@ -5 +5 + + @android.annotation.EnforcePermission(android.Manifest.permission.READ_CONTACTS) + @@ -7 +8 + - mContext.enforceCallingOrSelfPermission("android.Manifest.permission.READ_CONTACTS", "foo"); + """ + ) + } + + fun testAnonClass() { + lint().files( + java( + """ + import android.content.Context; + import android.test.ITest; + public class Foo { + private Context mContext; + private ITest itest = new ITest.Stub() { + @Override + public void test() throws android.os.RemoteException { + mContext.enforceCallingOrSelfPermission( + "android.Manifest.permission.READ_CONTACTS", "foo"); + } + }; + } + """ + ).indented(), + *stubs + ) + .run() + .expect( + """ + src/Foo.java:8: Warning: ITest permission check can be converted to @EnforcePermission annotation [UseEnforcePermissionAnnotation] + mContext.enforceCallingOrSelfPermission( + ^ + 0 errors, 1 warnings + """ + ) + .expectFixDiffs( + """ + Fix for src/Foo.java line 8: Annotate with @EnforcePermission: + @@ -6 +6 + + @android.annotation.EnforcePermission(android.Manifest.permission.READ_CONTACTS) + @@ -8 +9 + - mContext.enforceCallingOrSelfPermission( + - "android.Manifest.permission.READ_CONTACTS", "foo"); + """ + ) + } + + fun testAllOf() { + lint().files( + java( + """ + import android.content.Context; + import android.test.ITest; + public class Foo { + private Context mContext; + private ITest itest = new ITest.Stub() { + @Override + public void test() throws android.os.RemoteException { + mContext.enforceCallingOrSelfPermission( + "android.Manifest.permission.READ_CONTACTS", "foo"); + mContext.enforceCallingOrSelfPermission( + "android.Manifest.permission.WRITE_CONTACTS", "foo"); + } + }; + } + """ + ).indented(), + *stubs + ) + .run() + .expect( + """ + src/Foo.java:10: Warning: ITest permission check can be converted to @EnforcePermission annotation [UseEnforcePermissionAnnotation] + mContext.enforceCallingOrSelfPermission( + ^ + 0 errors, 1 warnings + """ + ) + .expectFixDiffs( + """ + Fix for src/Foo.java line 10: Annotate with @EnforcePermission: + @@ -6 +6 + + @android.annotation.EnforcePermission(allOf={android.Manifest.permission.READ_CONTACTS, android.Manifest.permission.WRITE_CONTACTS}) + @@ -8 +9 + - mContext.enforceCallingOrSelfPermission( + - "android.Manifest.permission.READ_CONTACTS", "foo"); + - mContext.enforceCallingOrSelfPermission( + - "android.Manifest.permission.WRITE_CONTACTS", "foo"); + """ + ) + } + + fun testPrecedingExpressions() { + lint().files( + java( + """ + import android.os.Binder; + import android.test.ITest; + public class Foo extends ITest.Stub { + private mContext Context; + @Override + public void test() throws android.os.RemoteException { + long uid = Binder.getCallingUid(); + mContext.enforceCallingOrSelfPermission("android.Manifest.permission.READ_CONTACTS", "foo"); + } + } + """ + ).indented(), + *stubs + ) + .run() + .expectClean() + } + + companion object { + private val aidlStub: TestFile = java( + """ + package android.test; + public interface ITest extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements android.test.ITest {} + public void test() throws android.os.RemoteException; + } + """ + ).indented() + + private val contextStub: TestFile = java( + """ + package android.content; + public class Context { + public void enforceCallingOrSelfPermission(String permission, String message) {} + } + """ + ).indented() + + private val binderStub: TestFile = java( + """ + package android.os; + public class Binder { + public static int getCallingUid() {} + } + """ + ).indented() + + val stubs = arrayOf(aidlStub, contextStub, binderStub) + } +} |