diff options
175 files changed, 2140 insertions, 1775 deletions
diff --git a/Android.bp b/Android.bp index cff863b44499..64d2c66f013c 100644 --- a/Android.bp +++ b/Android.bp @@ -410,6 +410,7 @@ java_defaults { "spatializer-aidl-java", "audiopolicy-aidl-java", "sounddose-aidl-java", + "modules-utils-expresslog", ], } diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java index fc6022859f5f..ba62e96b2a32 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java @@ -31,7 +31,7 @@ import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.expresslog.Counter; +import com.android.modules.expresslog.Counter; import com.android.server.job.JobSchedulerService; import com.android.server.job.StateControllerProto; diff --git a/boot/boot-image-profile.txt b/boot/boot-image-profile.txt index 996c3882701d..aebace57aa2c 100644 --- a/boot/boot-image-profile.txt +++ b/boot/boot-image-profile.txt @@ -33583,8 +33583,8 @@ Lcom/android/internal/dynamicanimation/animation/DynamicAnimation; Lcom/android/internal/dynamicanimation/animation/Force; Lcom/android/internal/dynamicanimation/animation/SpringAnimation; Lcom/android/internal/dynamicanimation/animation/SpringForce; -Lcom/android/internal/expresslog/Counter; -Lcom/android/internal/expresslog/Utils; +Lcom/android/modules/expresslog/Counter; +Lcom/android/modules/expresslog/Utils; Lcom/android/internal/graphics/ColorUtils$ContrastCalculator; Lcom/android/internal/graphics/ColorUtils; Lcom/android/internal/graphics/SfVsyncFrameCallbackProvider; diff --git a/boot/preloaded-classes b/boot/preloaded-classes index 21ae13474d84..4293caf57aea 100644 --- a/boot/preloaded-classes +++ b/boot/preloaded-classes @@ -10784,8 +10784,8 @@ com.android.internal.dynamicanimation.animation.DynamicAnimation com.android.internal.dynamicanimation.animation.Force com.android.internal.dynamicanimation.animation.SpringAnimation com.android.internal.dynamicanimation.animation.SpringForce -com.android.internal.expresslog.Counter -com.android.internal.expresslog.Utils +com.android.modules.expresslog.Counter +com.android.modules.expresslog.Utils com.android.internal.graphics.ColorUtils$ContrastCalculator com.android.internal.graphics.ColorUtils com.android.internal.graphics.SfVsyncFrameCallbackProvider diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt index 3cc990873c87..bb0748764cc8 100644 --- a/config/boot-image-profile.txt +++ b/config/boot-image-profile.txt @@ -43717,8 +43717,8 @@ Lcom/android/internal/dynamicanimation/animation/DynamicAnimation; Lcom/android/internal/dynamicanimation/animation/Force; Lcom/android/internal/dynamicanimation/animation/SpringAnimation; Lcom/android/internal/dynamicanimation/animation/SpringForce; -Lcom/android/internal/expresslog/Counter; -Lcom/android/internal/expresslog/Utils; +Lcom/android/modules/expresslog/Counter; +Lcom/android/modules/expresslog/Utils; Lcom/android/internal/graphics/ColorUtils$ContrastCalculator; Lcom/android/internal/graphics/ColorUtils; Lcom/android/internal/graphics/SfVsyncFrameCallbackProvider; diff --git a/config/preloaded-classes b/config/preloaded-classes index 8e50fe8e4e0f..1812c2bb61d6 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -10815,8 +10815,8 @@ com.android.internal.dynamicanimation.animation.DynamicAnimation com.android.internal.dynamicanimation.animation.Force com.android.internal.dynamicanimation.animation.SpringAnimation com.android.internal.dynamicanimation.animation.SpringForce -com.android.internal.expresslog.Counter -com.android.internal.expresslog.Utils +com.android.modules.expresslog.Counter +com.android.modules.expresslog.Utils com.android.internal.graphics.ColorUtils$ContrastCalculator com.android.internal.graphics.ColorUtils com.android.internal.graphics.SfVsyncFrameCallbackProvider diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 7d81a95774b2..5999e3c4a175 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -8,8 +8,6 @@ package android { field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS"; field public static final String BACKGROUND_CAMERA = "android.permission.BACKGROUND_CAMERA"; field public static final String BIND_CELL_BROADCAST_SERVICE = "android.permission.BIND_CELL_BROADCAST_SERVICE"; - field public static final String BODY_SENSORS_WRIST_TEMPERATURE = "android.permission.BODY_SENSORS_WRIST_TEMPERATURE"; - field public static final String BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND = "android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"; field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE"; field public static final String BROADCAST_CLOSE_SYSTEM_DIALOGS = "android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"; field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE"; diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 1dddf064e82a..3312294865d6 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1450,9 +1450,8 @@ public class AppOpsManager { public static final int OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD = AppProtoEnums.APP_OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD; - /** @hide Access to wrist temperature sensors. */ - public static final int OP_BODY_SENSORS_WRIST_TEMPERATURE = - AppProtoEnums.APP_OP_BODY_SENSORS_WRIST_TEMPERATURE; + // App op deprecated/removed. + private static final int OP_DEPRECATED_2 = AppProtoEnums.APP_OP_BODY_SENSORS_WRIST_TEMPERATURE; /** * Send an intent to launch instead of posting the notification to the status bar. @@ -1619,7 +1618,6 @@ public class AppOpsManager { OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION, OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION, OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD, - OPSTR_BODY_SENSORS_WRIST_TEMPERATURE, OPSTR_USE_FULL_SCREEN_INTENT, OPSTR_CAMERA_SANDBOXED, OPSTR_RECORD_AUDIO_SANDBOXED @@ -2221,11 +2219,10 @@ public class AppOpsManager { "android:capture_consentless_bugreport_on_userdebug_build"; /** - * Access to wrist temperature body sensors. + * App op deprecated/removed. * @hide */ - public static final String OPSTR_BODY_SENSORS_WRIST_TEMPERATURE = - "android:body_sensors_wrist_temperature"; + public static final String OPSTR_DEPRECATED_2 = "android:deprecated_2"; /** * Send an intent to launch instead of posting the notification to the status bar. @@ -2343,7 +2340,6 @@ public class AppOpsManager { OP_READ_MEDIA_VISUAL_USER_SELECTED, OP_FOREGROUND_SERVICE_SPECIAL_USE, OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD, - OP_BODY_SENSORS_WRIST_TEMPERATURE, OP_USE_FULL_SCREEN_INTENT }; @@ -2763,11 +2759,8 @@ public class AppOpsManager { "CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD") .setPermission(Manifest.permission.CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD) .build(), - new AppOpInfo.Builder(OP_BODY_SENSORS_WRIST_TEMPERATURE, - OPSTR_BODY_SENSORS_WRIST_TEMPERATURE, - "BODY_SENSORS_WRIST_TEMPERATURE") - .setPermission(Manifest.permission.BODY_SENSORS_WRIST_TEMPERATURE) - .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), + new AppOpInfo.Builder(OP_DEPRECATED_2, OPSTR_DEPRECATED_2, "DEPRECATED_2") + .setDefaultMode(AppOpsManager.MODE_IGNORED).build(), new AppOpInfo.Builder(OP_USE_FULL_SCREEN_INTENT, OPSTR_USE_FULL_SCREEN_INTENT, "USE_FULL_SCREEN_INTENT").setPermission(Manifest.permission.USE_FULL_SCREEN_INTENT) .build(), diff --git a/core/java/android/app/ForegroundServiceTypePolicy.java b/core/java/android/app/ForegroundServiceTypePolicy.java index be012cf8e202..c0c59a24dd8d 100644 --- a/core/java/android/app/ForegroundServiceTypePolicy.java +++ b/core/java/android/app/ForegroundServiceTypePolicy.java @@ -473,7 +473,6 @@ public abstract class ForegroundServiceTypePolicy { new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] { new RegularPermission(Manifest.permission.ACTIVITY_RECOGNITION), new RegularPermission(Manifest.permission.BODY_SENSORS), - new RegularPermission(Manifest.permission.BODY_SENSORS_WRIST_TEMPERATURE), new RegularPermission(Manifest.permission.HIGH_SAMPLING_RATE_SENSORS), }, false), FGS_TYPE_PERM_ENFORCEMENT_FLAG_HEALTH /* permissionEnforcementFlag */, diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 5feda785ece3..ad68866571e3 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -1310,6 +1310,10 @@ public abstract class CameraDevice implements AutoCloseable { * {@link Surface}, submitting a reprocess {@link CaptureRequest} with multiple * output targets will result in a {@link CaptureFailure}. * + * From Android 14 onward, {@link CaptureRequest#CONTROL_CAPTURE_INTENT} will be set to + * {@link CameraMetadata#CONTROL_CAPTURE_INTENT_STILL_CAPTURE} by default. Prior to Android 14, + * apps will need to explicitly set this key themselves. + * * @param inputResult The capture result of the output image or one of the output images used * to generate the reprocess input image for this capture request. * diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index cb1efe8c2b55..f2d8caaab0e7 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -26,6 +26,7 @@ import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraExtensionCharacteristics; +import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.CameraOfflineSession; import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; @@ -861,8 +862,13 @@ public class CameraDeviceImpl extends CameraDevice CameraMetadataNative resultMetadata = new CameraMetadataNative(inputResult.getNativeCopy()); - return new CaptureRequest.Builder(resultMetadata, /*reprocess*/true, - inputResult.getSessionId(), getId(), /*physicalCameraIdSet*/ null); + CaptureRequest.Builder builder = new CaptureRequest.Builder(resultMetadata, + /*reprocess*/true, inputResult.getSessionId(), getId(), + /*physicalCameraIdSet*/ null); + builder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, + CameraMetadata.CONTROL_CAPTURE_INTENT_STILL_CAPTURE); + + return builder; } } diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 8c4e90c81147..5dd2d82200bc 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -785,12 +785,13 @@ public final class Choreographer { DisplayEventReceiver.VsyncEventData vsyncEventData) { final long startNanos; final long frameIntervalNanos = vsyncEventData.frameInterval; + boolean resynced = false; try { + FrameTimeline timeline = mFrameData.update(frameTimeNanos, vsyncEventData); if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { - Trace.traceBegin(Trace.TRACE_TAG_VIEW, - "Choreographer#doFrame " + vsyncEventData.preferredFrameTimeline().vsyncId); + Trace.traceBegin( + Trace.TRACE_TAG_VIEW, "Choreographer#doFrame " + timeline.mVsyncId); } - mFrameData.update(frameTimeNanos, vsyncEventData); synchronized (mLock) { if (!mFrameScheduled) { traceMessage("Frame not scheduled"); @@ -828,7 +829,9 @@ public final class Choreographer { + " ms in the past."); } } - mFrameData.update(frameTimeNanos, mDisplayEventReceiver, jitterNanos); + timeline = mFrameData.update( + frameTimeNanos, mDisplayEventReceiver, jitterNanos); + resynced = true; } if (frameTimeNanos < mLastFrameTimeNanos) { @@ -860,6 +863,12 @@ public final class Choreographer { mLastVsyncEventData = vsyncEventData; } + if (resynced && Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { + String message = String.format("Choreographer#doFrame - resynced to %d in %.1fms", + timeline.mVsyncId, (timeline.mDeadlineNanos - startNanos) * 0.000001f); + Trace.traceBegin(Trace.TRACE_TAG_VIEW, message); + } + AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS); mFrameInfo.markInputHandlingStart(); @@ -875,6 +884,9 @@ public final class Choreographer { doCallbacks(Choreographer.CALLBACK_COMMIT, frameIntervalNanos); } finally { AnimationUtils.unlockAnimationClock(); + if (resynced) { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } Trace.traceEnd(Trace.TRACE_TAG_VIEW); } @@ -1149,7 +1161,8 @@ public final class Choreographer { * Update the frame data with a {@code DisplayEventReceiver.VsyncEventData} received from * native. */ - void update(long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) { + FrameTimeline update( + long frameTimeNanos, DisplayEventReceiver.VsyncEventData vsyncEventData) { if (vsyncEventData.frameTimelines.length != mFrameTimelines.length) { throw new IllegalStateException( "Length of native frame timelines received does not match Java. Did " @@ -1164,6 +1177,7 @@ public final class Choreographer { mFrameTimelines[i].update(frameTimeline.vsyncId, frameTimeline.expectedPresentationTime, frameTimeline.deadline); } + return mFrameTimelines[mPreferredFrameTimelineIndex]; } /** @@ -1171,7 +1185,7 @@ public final class Choreographer { * * @param jitterNanos currentTime - frameTime */ - void update( + FrameTimeline update( long frameTimeNanos, DisplayEventReceiver displayEventReceiver, long jitterNanos) { int newPreferredIndex = 0; final long minimumDeadline = @@ -1192,6 +1206,7 @@ public final class Choreographer { } else { update(frameTimeNanos, newPreferredIndex); } + return mFrameTimelines[mPreferredFrameTimelineIndex]; } void update(long frameTimeNanos, int newPreferredFrameTimelineIndex) { diff --git a/core/java/android/window/BackMotionEvent.java b/core/java/android/window/BackMotionEvent.java index 8012a1c26bac..c47572313eeb 100644 --- a/core/java/android/window/BackMotionEvent.java +++ b/core/java/android/window/BackMotionEvent.java @@ -34,6 +34,8 @@ public final class BackMotionEvent implements Parcelable { private final float mTouchX; private final float mTouchY; private final float mProgress; + private final float mVelocityX; + private final float mVelocityY; @BackEvent.SwipeEdge private final int mSwipeEdge; @@ -43,19 +45,32 @@ public final class BackMotionEvent implements Parcelable { /** * Creates a new {@link BackMotionEvent} instance. * + * <p>Note: Velocity is only computed for last event, for performance reasons.</p> + * * @param touchX Absolute X location of the touch point of this event. * @param touchY Absolute Y location of the touch point of this event. * @param progress Value between 0 and 1 on how far along the back gesture is. + * @param velocityX X velocity computed from the touch point of this event. + * Value in pixels/second. {@link Float#NaN} if was not computed. + * @param velocityY Y velocity computed from the touch point of this event. + * Value in pixels/second. {@link Float#NaN} if was not computed. * @param swipeEdge Indicates which edge the swipe starts from. * @param departingAnimationTarget The remote animation target of the departing * application window. */ - public BackMotionEvent(float touchX, float touchY, float progress, + public BackMotionEvent( + float touchX, + float touchY, + float progress, + float velocityX, + float velocityY, @BackEvent.SwipeEdge int swipeEdge, @Nullable RemoteAnimationTarget departingAnimationTarget) { mTouchX = touchX; mTouchY = touchY; mProgress = progress; + mVelocityX = velocityX; + mVelocityY = velocityY; mSwipeEdge = swipeEdge; mDepartingAnimationTarget = departingAnimationTarget; } @@ -64,6 +79,8 @@ public final class BackMotionEvent implements Parcelable { mTouchX = in.readFloat(); mTouchY = in.readFloat(); mProgress = in.readFloat(); + mVelocityX = in.readFloat(); + mVelocityY = in.readFloat(); mSwipeEdge = in.readInt(); mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR); } @@ -91,11 +108,27 @@ public final class BackMotionEvent implements Parcelable { dest.writeFloat(mTouchX); dest.writeFloat(mTouchY); dest.writeFloat(mProgress); + dest.writeFloat(mVelocityX); + dest.writeFloat(mVelocityY); dest.writeInt(mSwipeEdge); dest.writeTypedObject(mDepartingAnimationTarget, flags); } /** + * Returns the absolute X location of the touch point. + */ + public float getTouchX() { + return mTouchX; + } + + /** + * Returns the absolute Y location of the touch point. + */ + public float getTouchY() { + return mTouchY; + } + + /** * Returns the progress of a {@link BackEvent}. * * @see BackEvent#getProgress() @@ -106,17 +139,21 @@ public final class BackMotionEvent implements Parcelable { } /** - * Returns the absolute X location of the touch point. + * Returns the X velocity computed from the touch point. + * + * @return value in pixels/second or {@link Float#NaN} if was not computed. */ - public float getTouchX() { - return mTouchX; + public float getVelocityX() { + return mVelocityX; } /** - * Returns the absolute Y location of the touch point. + * Returns the Y velocity computed from the touch point. + * + * @return value in pixels/second or {@link Float#NaN} if was not computed. */ - public float getTouchY() { - return mTouchY; + public float getVelocityY() { + return mVelocityY; } /** @@ -143,6 +180,8 @@ public final class BackMotionEvent implements Parcelable { + "mTouchX=" + mTouchX + ", mTouchY=" + mTouchY + ", mProgress=" + mProgress + + ", mVelocityX=" + mVelocityX + + ", mVelocityY=" + mVelocityY + ", mSwipeEdge" + mSwipeEdge + ", mDepartingAnimationTarget" + mDepartingAnimationTarget + "}"; diff --git a/core/java/com/android/internal/expresslog/Counter.java b/core/java/com/android/internal/expresslog/Counter.java deleted file mode 100644 index 4a46d91efbf0..000000000000 --- a/core/java/com/android/internal/expresslog/Counter.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2023 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.internal.expresslog; - -import android.annotation.NonNull; - -import com.android.internal.util.FrameworkStatsLog; - -/** Counter encapsulates StatsD write API calls */ -public final class Counter { - - // Not instantiable. - private Counter() {} - - /** - * Increments Telemetry Express Counter metric by 1 - * @param metricId to log, no-op if metricId is not defined in the TeX catalog - * @hide - */ - public static void logIncrement(@NonNull String metricId) { - logIncrement(metricId, 1); - } - - /** - * Increments Telemetry Express Counter metric by 1 - * @param metricId to log, no-op if metricId is not defined in the TeX catalog - * @param uid used as a dimension for the count metric - * @hide - */ - public static void logIncrementWithUid(@NonNull String metricId, int uid) { - logIncrementWithUid(metricId, uid, 1); - } - - /** - * Increments Telemetry Express Counter metric by arbitrary value - * @param metricId to log, no-op if metricId is not defined in the TeX catalog - * @param amount to increment counter - * @hide - */ - public static void logIncrement(@NonNull String metricId, long amount) { - final long metricIdHash = Utils.hashString(metricId); - FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_EVENT_REPORTED, metricIdHash, amount); - } - - /** - * Increments Telemetry Express Counter metric by arbitrary value - * @param metricId to log, no-op if metricId is not defined in the TeX catalog - * @param uid used as a dimension for the count metric - * @param amount to increment counter - * @hide - */ - public static void logIncrementWithUid(@NonNull String metricId, int uid, long amount) { - final long metricIdHash = Utils.hashString(metricId); - FrameworkStatsLog.write( - FrameworkStatsLog.EXPRESS_UID_EVENT_REPORTED, metricIdHash, amount, uid); - } -} diff --git a/core/java/com/android/internal/expresslog/Histogram.java b/core/java/com/android/internal/expresslog/Histogram.java deleted file mode 100644 index 2fe784a5a855..000000000000 --- a/core/java/com/android/internal/expresslog/Histogram.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2023 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.internal.expresslog; - -import android.annotation.FloatRange; -import android.annotation.IntRange; -import android.annotation.NonNull; - -import com.android.internal.util.FrameworkStatsLog; - -import java.util.Arrays; - -/** Histogram encapsulates StatsD write API calls */ -public final class Histogram { - - private final long mMetricIdHash; - private final BinOptions mBinOptions; - - /** - * Creates Histogram metric logging wrapper - * - * @param metricId to log, logging will be no-op if metricId is not defined in the TeX catalog - * @param binOptions to calculate bin index for samples - * @hide - */ - public Histogram(@NonNull String metricId, @NonNull BinOptions binOptions) { - mMetricIdHash = Utils.hashString(metricId); - mBinOptions = binOptions; - } - - /** - * Logs increment sample count for automatically calculated bin - * - * @param sample value - * @hide - */ - public void logSample(float sample) { - final int binIndex = mBinOptions.getBinForSample(sample); - FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash, - /*count*/ 1, binIndex); - } - - /** - * Logs increment sample count for automatically calculated bin - * - * @param uid used as a dimension for the count metric - * @param sample value - * @hide - */ - public void logSampleWithUid(int uid, float sample) { - final int binIndex = mBinOptions.getBinForSample(sample); - FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_UID_HISTOGRAM_SAMPLE_REPORTED, - mMetricIdHash, /*count*/ 1, binIndex, uid); - } - - /** Used by Histogram to map data sample to corresponding bin */ - public interface BinOptions { - /** - * Returns bins count to be used by a histogram - * - * @return bins count used to initialize Options, including overflow & underflow bins - * @hide - */ - int getBinsCount(); - - /** - * Returns bin index for the input sample value - * index == 0 stands for underflow - * index == getBinsCount() - 1 stands for overflow - * - * @return zero based index - * @hide - */ - int getBinForSample(float sample); - } - - /** Used by Histogram to map data sample to corresponding bin for uniform bins */ - public static final class UniformOptions implements BinOptions { - - private final int mBinCount; - private final float mMinValue; - private final float mExclusiveMaxValue; - private final float mBinSize; - - /** - * Creates options for uniform (linear) sized bins - * - * @param binCount amount of histogram bins. 2 bin indexes will be calculated - * automatically to represent underflow & overflow bins - * @param minValue is included in the first bin, values less than minValue - * go to underflow bin - * @param exclusiveMaxValue is included in the overflow bucket. For accurate - * measure up to kMax, then exclusiveMaxValue - * should be set to kMax + 1 - * @hide - */ - public UniformOptions(@IntRange(from = 1) int binCount, float minValue, - float exclusiveMaxValue) { - if (binCount < 1) { - throw new IllegalArgumentException("Bin count should be positive number"); - } - - if (exclusiveMaxValue <= minValue) { - throw new IllegalArgumentException("Bins range invalid (maxValue < minValue)"); - } - - mMinValue = minValue; - mExclusiveMaxValue = exclusiveMaxValue; - mBinSize = (mExclusiveMaxValue - minValue) / binCount; - - // Implicitly add 2 for the extra underflow & overflow bins - mBinCount = binCount + 2; - } - - @Override - public int getBinsCount() { - return mBinCount; - } - - @Override - public int getBinForSample(float sample) { - if (sample < mMinValue) { - // goes to underflow - return 0; - } else if (sample >= mExclusiveMaxValue) { - // goes to overflow - return mBinCount - 1; - } - return (int) ((sample - mMinValue) / mBinSize + 1); - } - } - - /** Used by Histogram to map data sample to corresponding bin for scaled bins */ - public static final class ScaledRangeOptions implements BinOptions { - // store minimum value per bin - final long[] mBins; - - /** - * Creates options for scaled range bins - * - * @param binCount amount of histogram bins. 2 bin indexes will be calculated - * automatically to represent underflow & overflow bins - * @param minValue is included in the first bin, values less than minValue - * go to underflow bin - * @param firstBinWidth used to represent first bin width and as a reference to calculate - * width for consecutive bins - * @param scaleFactor used to calculate width for consecutive bins - * @hide - */ - public ScaledRangeOptions(@IntRange(from = 1) int binCount, int minValue, - @FloatRange(from = 1.f) float firstBinWidth, - @FloatRange(from = 1.f) float scaleFactor) { - if (binCount < 1) { - throw new IllegalArgumentException("Bin count should be positive number"); - } - - if (firstBinWidth < 1.f) { - throw new IllegalArgumentException( - "First bin width invalid (should be 1.f at minimum)"); - } - - if (scaleFactor < 1.f) { - throw new IllegalArgumentException( - "Scaled factor invalid (should be 1.f at minimum)"); - } - - // precalculating bins ranges (no need to create a bin for underflow reference value) - mBins = initBins(binCount + 1, minValue, firstBinWidth, scaleFactor); - } - - @Override - public int getBinsCount() { - return mBins.length + 1; - } - - @Override - public int getBinForSample(float sample) { - if (sample < mBins[0]) { - // goes to underflow - return 0; - } else if (sample >= mBins[mBins.length - 1]) { - // goes to overflow - return mBins.length; - } - - return lower_bound(mBins, (long) sample) + 1; - } - - // To find lower bound using binary search implementation of Arrays utility class - private static int lower_bound(long[] array, long sample) { - int index = Arrays.binarySearch(array, sample); - // If key is not present in the array - if (index < 0) { - // Index specify the position of the key when inserted in the sorted array - // so the element currently present at this position will be the lower bound - return Math.abs(index) - 2; - } - return index; - } - - private static long[] initBins(int count, int minValue, float firstBinWidth, - float scaleFactor) { - long[] bins = new long[count]; - bins[0] = minValue; - double lastWidth = firstBinWidth; - for (int i = 1; i < count; i++) { - // current bin minValue = previous bin width * scaleFactor - double currentBinMinValue = bins[i - 1] + lastWidth; - if (currentBinMinValue > Integer.MAX_VALUE) { - throw new IllegalArgumentException( - "Attempted to create a bucket larger than maxint"); - } - - bins[i] = (long) currentBinMinValue; - lastWidth *= scaleFactor; - } - return bins; - } - } -} diff --git a/core/java/com/android/internal/expresslog/OWNERS b/core/java/com/android/internal/expresslog/OWNERS deleted file mode 100644 index ee865b1e4ec8..000000000000 --- a/core/java/com/android/internal/expresslog/OWNERS +++ /dev/null @@ -1 +0,0 @@ -include /services/core/java/com/android/server/stats/OWNERS diff --git a/core/java/com/android/internal/expresslog/TEST_MAPPING b/core/java/com/android/internal/expresslog/TEST_MAPPING deleted file mode 100644 index c9b0cf80a1e6..000000000000 --- a/core/java/com/android/internal/expresslog/TEST_MAPPING +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presubmit": [ - { - "name": "ExpressLogTests", - "options": [ - { - "exclude-annotation": "org.junit.Ignore" - } - ] - } - ] -}
\ No newline at end of file diff --git a/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java b/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java index e2c096c11fee..aa6b1c00d186 100644 --- a/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java +++ b/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java @@ -20,7 +20,7 @@ import android.annotation.Nullable; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.expresslog.Counter; +import com.android.modules.expresslog.Counter; import java.io.IOException; import java.util.Arrays; diff --git a/core/jni/Android.bp b/core/jni/Android.bp index fc26766d7090..6bec6bc236bd 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -225,7 +225,6 @@ cc_library_shared { "android_security_Scrypt.cpp", "com_android_internal_content_om_OverlayConfig.cpp", "com_android_internal_content_om_OverlayManagerImpl.cpp", - "com_android_internal_expresslog_Utils.cpp", "com_android_internal_net_NetworkUtilsInternal.cpp", "com_android_internal_os_ClassLoaderFactory.cpp", "com_android_internal_os_FuseAppLoop.cpp", @@ -262,6 +261,7 @@ cc_library_shared { "libstatssocket_lazy", "libskia", "libtextclassifier_hash_static", + "libexpresslog_jni", ], shared_libs: [ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index b550f28e0934..21bdf099f18d 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -200,7 +200,7 @@ extern int register_com_android_internal_content_F2fsUtils(JNIEnv* env); extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env); extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env); extern int register_com_android_internal_content_om_OverlayManagerImpl(JNIEnv* env); -extern int register_com_android_internal_expresslog_Utils(JNIEnv* env); +extern int register_com_android_modules_expresslog_Utils(JNIEnv* env); extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env); extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env); extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env); @@ -1586,7 +1586,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_incremental_IncrementalManager), REG_JNI(register_com_android_internal_content_om_OverlayConfig), REG_JNI(register_com_android_internal_content_om_OverlayManagerImpl), - REG_JNI(register_com_android_internal_expresslog_Utils), + REG_JNI(register_com_android_modules_expresslog_Utils), REG_JNI(register_com_android_internal_net_NetworkUtilsInternal), REG_JNI(register_com_android_internal_os_ClassLoaderFactory), REG_JNI(register_com_android_internal_os_LongArrayMultiStateCounter), diff --git a/core/jni/OWNERS b/core/jni/OWNERS index bce533281186..4e4abec88040 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -104,6 +104,3 @@ per-file com_android_internal_os_*MultiStateCounter* = file:/BATTERY_STATS_OWNER # PM per-file com_android_internal_content_* = file:/PACKAGE_MANAGER_OWNERS - -# Stats/expresslog -per-file *expresslog* = file:/services/core/java/com/android/server/stats/OWNERS diff --git a/core/jni/com_android_internal_expresslog_Utils.cpp b/core/jni/com_android_internal_expresslog_Utils.cpp deleted file mode 100644 index d33a7bda27f7..000000000000 --- a/core/jni/com_android_internal_expresslog_Utils.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <nativehelper/JNIHelp.h> -#include <utils/hash/farmhash.h> - -#include "core_jni_helpers.h" - -// ---------------------------------------------------------------------------- -// JNI Glue -// ---------------------------------------------------------------------------- - -static jclass g_stringClass = nullptr; - -/** - * Class: com_android_internal_expresslog_Utils - * Method: hashString - * Signature: (Ljava/lang/String;)J - */ -static jlong hashString(JNIEnv* env, jclass /*class*/, jstring metricNameObj) { - ScopedUtfChars name(env, metricNameObj); - if (name.c_str() == nullptr) { - return 0; - } - - return static_cast<jlong>(farmhash::Fingerprint64(name.c_str(), name.size())); -} - -static const JNINativeMethod g_methods[] = { - {"hashString", "(Ljava/lang/String;)J", (void*)hashString}, -}; - -static const char* const kUtilsPathName = "com/android/internal/expresslog/Utils"; - -namespace android { - -int register_com_android_internal_expresslog_Utils(JNIEnv* env) { - jclass stringClass = FindClassOrDie(env, "java/lang/String"); - g_stringClass = MakeGlobalRefOrDie(env, stringClass); - - return RegisterMethodsOrDie(env, kUtilsPathName, g_methods, NELEM(g_methods)); -} - -} // namespace android diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 78d39236b392..05b38a562e29 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1746,37 +1746,6 @@ android:protectionLevel="dangerous" android:permissionFlags="hardRestricted" /> - <!-- @TestApi Allows an application to access wrist temperature data from the watch sensors. - <p class="note"><strong>Note: </strong> This permission is for Wear OS only. - <p>Protection level: dangerous - @hide - --> - <permission android:name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE" - android:permissionGroup="android.permission-group.UNDEFINED" - android:label="@string/permlab_bodySensorsWristTemperature" - android:description="@string/permdesc_bodySensorsWristTemperature" - android:backgroundPermission="android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND" - android:protectionLevel="dangerous" /> - - <!-- @TestApi Allows an application to access wrist temperature data from the watch sensors. - If you're requesting this permission, you must also request - {@link #BODY_SENSORS_WRIST_TEMPERATURE}. Requesting this permission by itself doesn't - give you wrist temperature body sensors access. - <p class="note"><strong>Note: </strong> This permission is for Wear OS only. - <p>Protection level: dangerous - - <p> This is a hard restricted permission which cannot be held by an app until - the installer on record allowlists the permission. For more details see - {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. - @hide - --> - <permission android:name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND" - android:permissionGroup="android.permission-group.UNDEFINED" - android:label="@string/permlab_bodySensors_wristTemperature_background" - android:description="@string/permdesc_bodySensors_wristTemperature_background" - android:protectionLevel="dangerous" - android:permissionFlags="hardRestricted" /> - <!-- Allows an app to use fingerprint hardware. <p>Protection level: normal @deprecated Applications should request {@link diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 82314072fbac..947dc2de9841 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1347,16 +1347,6 @@ <!-- Description of the background body sensors permission, listed so the user can decide whether to allow the application to access data from body sensors in the background. [CHAR LIMIT=NONE] --> <string name="permdesc_bodySensors_background" product="default">Allows the app to access body sensor data, such as heart rate, temperature, and blood oxygen percentage, while the app is in the background.</string> - <!-- Title of the body sensors wrist temperature permission, listed so the user can decide whether to allow the application to access body sensor wrist temperature data. [CHAR LIMIT=NONE] --> - <string name="permlab_bodySensorsWristTemperature">Access body sensor wrist temperature data while the app is in use.</string> - <!-- Description of the body sensors wrist temperature permission, listed so the user can decide whether to allow the application to access data from body sensors. [CHAR LIMIT=NONE] --> - <string name="permdesc_bodySensorsWristTemperature" product="default">Allows the app to access body sensor wrist temperature data, while the app is in use.</string> - - <!-- Title of the body sensors wrist temperature permission, listed so the user can decide whether to allow the application to access body sensor wrist temperature data. [CHAR LIMIT=NONE] --> - <string name="permlab_bodySensors_wristTemperature_background">Access body sensor wrist temperature data while the app is in the background.</string> - <!-- Description of the body sensors wrist temperature permission, listed so the user can decide whether to allow the application to access data from body sensors. [CHAR LIMIT=NONE] --> - <string name="permdesc_bodySensors_wristTemperature_background" product="default">Allows the app to access body sensor wrist temperature data, while the app is in the background.</string> - <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_readCalendar">Read calendar events and details</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java index 3b6e8eaafc22..cde100cc20aa 100644 --- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java +++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java @@ -70,7 +70,13 @@ public class WindowOnBackInvokedDispatcherTest { private ApplicationInfo mApplicationInfo; private final BackMotionEvent mBackEvent = new BackMotionEvent( - 0, 0, 0, BackEvent.EDGE_LEFT, null); + /* touchX = */ 0, + /* touchY = */ 0, + /* progress = */ 0, + /* velocityX = */ 0, + /* velocityY = */ 0, + /* swipeEdge = */ BackEvent.EDGE_LEFT, + /* departingAnimationTarget = */ null); @Before public void setUp() throws Exception { diff --git a/core/tests/expresslog/AndroidManifest.xml b/core/tests/expresslog/AndroidManifest.xml deleted file mode 100644 index 94a39e06c974..000000000000 --- a/core/tests/expresslog/AndroidManifest.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2023 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" - android:installLocation="internalOnly" - package="com.android.internal.expresslog" > - - <application > - <uses-library android:name="android.test.runner" /> - </application> - - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.internal.expresslog" - android:label="Telemetry Express Logging Helper Tests" /> - -</manifest> diff --git a/core/tests/expresslog/OWNERS b/core/tests/expresslog/OWNERS deleted file mode 100644 index 3dc958b07f9c..000000000000 --- a/core/tests/expresslog/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -# Bug component: 719316 -# Stats/expresslog -file:/services/core/java/com/android/server/stats/OWNERS diff --git a/core/tests/expresslog/TEST_MAPPING b/core/tests/expresslog/TEST_MAPPING deleted file mode 100644 index c9b0cf80a1e6..000000000000 --- a/core/tests/expresslog/TEST_MAPPING +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presubmit": [ - { - "name": "ExpressLogTests", - "options": [ - { - "exclude-annotation": "org.junit.Ignore" - } - ] - } - ] -}
\ No newline at end of file diff --git a/core/tests/expresslog/src/com/android/internal/expresslog/ScaledRangeOptionsTest.java b/core/tests/expresslog/src/com/android/internal/expresslog/ScaledRangeOptionsTest.java deleted file mode 100644 index ee62d7528818..000000000000 --- a/core/tests/expresslog/src/com/android/internal/expresslog/ScaledRangeOptionsTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2023 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.internal.expresslog; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -@SmallTest -public class ScaledRangeOptionsTest { - private static final String TAG = ScaledRangeOptionsTest.class.getSimpleName(); - - @Test - public void testGetBinsCount() { - Histogram.ScaledRangeOptions options1 = new Histogram.ScaledRangeOptions(1, 100, 100, 2); - assertEquals(3, options1.getBinsCount()); - - Histogram.ScaledRangeOptions options10 = new Histogram.ScaledRangeOptions(10, 100, 100, 2); - assertEquals(12, options10.getBinsCount()); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructZeroBinsCount() { - new Histogram.ScaledRangeOptions(0, 100, 100, 2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructNegativeBinsCount() { - new Histogram.ScaledRangeOptions(-1, 100, 100, 2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructNegativeFirstBinWidth() { - new Histogram.ScaledRangeOptions(10, 100, -100, 2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructTooSmallFirstBinWidth() { - new Histogram.ScaledRangeOptions(10, 100, 0.5f, 2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructNegativeScaleFactor() { - new Histogram.ScaledRangeOptions(10, 100, 100, -2); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructTooSmallScaleFactor() { - new Histogram.ScaledRangeOptions(10, 100, 100, 0.5f); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructTooBigScaleFactor() { - new Histogram.ScaledRangeOptions(10, 100, 100, 500.f); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructTooBigBinRange() { - new Histogram.ScaledRangeOptions(100, 100, 100, 10.f); - } - - @Test - public void testBinIndexForRangeEqual1() { - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(10, 1, 1, 1); - assertEquals(12, options.getBinsCount()); - - assertEquals(11, options.getBinForSample(11)); - - for (int i = 0, bins = options.getBinsCount(); i < bins; i++) { - assertEquals(i, options.getBinForSample(i)); - } - } - - @Test - public void testBinIndexForRangeEqual2() { - // this should produce bin otpions similar to linear histogram with bin width 2 - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(10, 1, 2, 1); - assertEquals(12, options.getBinsCount()); - - for (int i = 0, bins = options.getBinsCount(); i < bins; i++) { - assertEquals(i, options.getBinForSample(i * 2)); - assertEquals(i, options.getBinForSample(i * 2 - 1)); - } - } - - @Test - public void testBinIndexForRangeEqual5() { - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(2, 0, 5, 1); - assertEquals(4, options.getBinsCount()); - for (int i = 0; i < 2; i++) { - for (int sample = 0; sample < 5; sample++) { - assertEquals(i + 1, options.getBinForSample(i * 5 + sample)); - } - } - } - - @Test - public void testBinIndexForRangeEqual10() { - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(10, 1, 10, 1); - assertEquals(0, options.getBinForSample(0)); - assertEquals(options.getBinsCount() - 2, options.getBinForSample(100)); - assertEquals(options.getBinsCount() - 1, options.getBinForSample(101)); - - final float binSize = (101 - 1) / 10f; - for (int i = 1, bins = options.getBinsCount() - 1; i < bins; i++) { - assertEquals(i, options.getBinForSample(i * binSize)); - } - } - - @Test - public void testBinIndexForScaleFactor2() { - final int binsCount = 10; - final int minValue = 10; - final int firstBinWidth = 5; - final int scaledFactor = 2; - - Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions( - binsCount, minValue, firstBinWidth, scaledFactor); - assertEquals(binsCount + 2, options.getBinsCount()); - long[] binCounts = new long[10]; - - // precalculate max valid value - start value for the overflow bin - int lastBinStartValue = minValue; //firstBinMin value - int lastBinWidth = firstBinWidth; - for (int binIdx = 2; binIdx <= binsCount + 1; binIdx++) { - lastBinStartValue = lastBinStartValue + lastBinWidth; - lastBinWidth *= scaledFactor; - } - - // underflow bin - for (int i = 1; i < minValue; i++) { - assertEquals(0, options.getBinForSample(i)); - } - - for (int i = 10; i < lastBinStartValue; i++) { - assertTrue(options.getBinForSample(i) > 0); - assertTrue(options.getBinForSample(i) <= binsCount); - binCounts[options.getBinForSample(i) - 1]++; - } - - // overflow bin - assertEquals(binsCount + 1, options.getBinForSample(lastBinStartValue)); - - for (int i = 1; i < binsCount; i++) { - assertEquals(binCounts[i], binCounts[i - 1] * 2L); - } - } -} diff --git a/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java b/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java deleted file mode 100644 index 037dbb32c2f8..000000000000 --- a/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2023 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.internal.expresslog; - -import androidx.test.filters.SmallTest; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -@SmallTest -public class UniformOptionsTest { - private static final String TAG = UniformOptionsTest.class.getSimpleName(); - - @Test - public void testGetBinsCount() { - Histogram.UniformOptions options1 = new Histogram.UniformOptions(1, 100, 1000); - assertEquals(3, options1.getBinsCount()); - - Histogram.UniformOptions options10 = new Histogram.UniformOptions(10, 100, 1000); - assertEquals(12, options10.getBinsCount()); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructZeroBinsCount() { - new Histogram.UniformOptions(0, 100, 1000); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructNegativeBinsCount() { - new Histogram.UniformOptions(-1, 100, 1000); - } - - @Test(expected = IllegalArgumentException.class) - public void testConstructMaxValueLessThanMinValue() { - new Histogram.UniformOptions(10, 1000, 100); - } - - @Test - public void testBinIndexForRangeEqual1() { - Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 11); - for (int i = 0, bins = options.getBinsCount(); i < bins; i++) { - assertEquals(i, options.getBinForSample(i)); - } - } - - @Test - public void testBinIndexForRangeEqual2() { - Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 21); - for (int i = 0, bins = options.getBinsCount(); i < bins; i++) { - assertEquals(i, options.getBinForSample(i * 2)); - assertEquals(i, options.getBinForSample(i * 2 - 1)); - } - } - - @Test - public void testBinIndexForRangeEqual5() { - Histogram.UniformOptions options = new Histogram.UniformOptions(2, 0, 10); - assertEquals(4, options.getBinsCount()); - for (int i = 0; i < 2; i++) { - for (int sample = 0; sample < 5; sample++) { - assertEquals(i + 1, options.getBinForSample(i * 5 + sample)); - } - } - } - - @Test - public void testBinIndexForRangeEqual10() { - Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 101); - assertEquals(0, options.getBinForSample(0)); - assertEquals(options.getBinsCount() - 2, options.getBinForSample(100)); - assertEquals(options.getBinsCount() - 1, options.getBinForSample(101)); - - final float binSize = (101 - 1) / 10f; - for (int i = 1, bins = options.getBinsCount() - 1; i < bins; i++) { - assertEquals(i, options.getBinForSample(i * binSize)); - } - } - - @Test - public void testBinIndexForRangeEqual90() { - final int binCount = 10; - final int minValue = 100; - final int maxValue = 100000; - - Histogram.UniformOptions options = new Histogram.UniformOptions(binCount, minValue, - maxValue); - - // logging underflow sample - assertEquals(0, options.getBinForSample(minValue - 1)); - - // logging overflow sample - assertEquals(binCount + 1, options.getBinForSample(maxValue)); - assertEquals(binCount + 1, options.getBinForSample(maxValue + 1)); - - // logging min edge sample - assertEquals(1, options.getBinForSample(minValue)); - - // logging max edge sample - assertEquals(binCount, options.getBinForSample(maxValue - 1)); - - // logging single valid sample per bin - final int binSize = (maxValue - minValue) / binCount; - - for (int i = 0; i < binCount; i++) { - assertEquals(i + 1, options.getBinForSample(minValue + binSize * i)); - } - } -} diff --git a/data/etc/preinstalled-packages-platform-overlays.xml b/data/etc/preinstalled-packages-platform-overlays.xml index 99594336999b..2fd65dc29363 100644 --- a/data/etc/preinstalled-packages-platform-overlays.xml +++ b/data/etc/preinstalled-packages-platform-overlays.xml @@ -56,6 +56,9 @@ <install-in-user-type package="com.android.internal.systemui.navbar.transparent"> <install-in user-type="FULL" /> </install-in-user-type> + <install-in-user-type package="com.android.role.notes.enabled"> + <install-in user-type="FULL" /> + </install-in-user-type> <install-in-user-type package="com.android.theme.color.amethyst"> <install-in user-type="FULL" /> <install-in user-type="PROFILE" /> diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index 0b29973507d2..56c3068fe5e9 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -2083,32 +2083,29 @@ public final class ImageDecoder implements AutoCloseable { } sIsP010SupportedForAV1Initialized = true; - - if (hasHardwareDecoder("video/av01")) { - sIsP010SupportedForAV1 = true; - return true; - } - - sIsP010SupportedForAV1 = Build.VERSION.DEVICE_INITIAL_SDK_INT - >= Build.VERSION_CODES.S; - return sIsP010SupportedForAV1; + return sIsP010SupportedForAV1 = isP010SupportedforMime("video/av01"); } } /** - * Checks if the device has hardware decoder for the target mime type. - */ - private static boolean hasHardwareDecoder(String mime) { - final MediaCodecList sMCL = new MediaCodecList(MediaCodecList.REGULAR_CODECS); - for (MediaCodecInfo info : sMCL.getCodecInfos()) { - if (info.isEncoder() == false && info.isHardwareAccelerated()) { - try { - if (info.getCapabilitiesForType(mime) != null) { - return true; - } - } catch (IllegalArgumentException e) { - // mime is not supported - return false; + * Checks if the device supports decoding 10-bit for the given mime type. + */ + private static boolean isP010SupportedforMime(String mime) { + MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS); + for (MediaCodecInfo mediaCodecInfo : codecList.getCodecInfos()) { + if (mediaCodecInfo.isEncoder()) { + continue; + } + for (String mediaType : mediaCodecInfo.getSupportedTypes()) { + if (mediaType.equalsIgnoreCase(mime)) { + MediaCodecInfo.CodecCapabilities codecCapabilities = + mediaCodecInfo.getCapabilitiesForType(mediaType); + for (int i = 0; i < codecCapabilities.colorFormats.length; ++i) { + if (codecCapabilities.colorFormats[i] + == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010) { + return true; + } + } } } } diff --git a/libs/WindowManager/Jetpack/Android.bp b/libs/WindowManager/Jetpack/Android.bp index a5b192cd7ceb..abe8f859f2fe 100644 --- a/libs/WindowManager/Jetpack/Android.bp +++ b/libs/WindowManager/Jetpack/Android.bp @@ -55,20 +55,6 @@ prebuilt_etc { } // Extensions -// NOTE: This module is still under active development and must not -// be used in production. Use 'androidx.window.sidecar' instead. -android_library_import { - name: "window-extensions", - aars: ["window-extensions-release.aar"], - sdk_version: "current", -} - -android_library_import { - name: "window-extensions-core", - aars: ["window-extensions-core-release.aar"], - sdk_version: "current", -} - java_library { name: "androidx.window.extensions", srcs: [ @@ -77,8 +63,8 @@ java_library { "src/androidx/window/common/**/*.java", ], static_libs: [ - "window-extensions", - "window-extensions-core", + "androidx.window.extensions_extensions-nodeps", + "androidx.window.extensions.core_core-nodeps", ], installable: true, sdk_version: "core_platform", diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java index 8386131b177d..a7a6b3c92157 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -122,16 +122,6 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { addWindowLayoutInfoListener(activity, extConsumer); } - @Override - public void addWindowLayoutInfoListener(@NonNull @UiContext Context context, - @NonNull java.util.function.Consumer<WindowLayoutInfo> consumer) { - final Consumer<WindowLayoutInfo> extConsumer = consumer::accept; - synchronized (mLock) { - mJavaToExtConsumers.put(consumer, extConsumer); - } - addWindowLayoutInfoListener(context, extConsumer); - } - /** * Similar to {@link #addWindowLayoutInfoListener(Activity, java.util.function.Consumer)}, but * takes a UI Context as a parameter. diff --git a/libs/WindowManager/Jetpack/window-extensions-core-release.aar b/libs/WindowManager/Jetpack/window-extensions-core-release.aar Binary files differdeleted file mode 100644 index 96ff840b984b..000000000000 --- a/libs/WindowManager/Jetpack/window-extensions-core-release.aar +++ /dev/null diff --git a/libs/WindowManager/Jetpack/window-extensions-release.aar b/libs/WindowManager/Jetpack/window-extensions-release.aar Binary files differdeleted file mode 100644 index c3b6916121d0..000000000000 --- a/libs/WindowManager/Jetpack/window-extensions-release.aar +++ /dev/null diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java index e84a78f42616..133fd87a2f63 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java @@ -33,12 +33,19 @@ public interface BackAnimation { * * @param touchX the X touch position of the {@link MotionEvent}. * @param touchY the Y touch position of the {@link MotionEvent}. + * @param velocityX the X velocity computed from the {@link MotionEvent}. + * @param velocityY the Y velocity computed from the {@link MotionEvent}. * @param keyAction the original {@link KeyEvent#getAction()} when the event was dispatched to * the process. This is forwarded separately because the input pipeline may mutate * the {#event} action state later. * @param swipeEdge the edge from which the swipe begins. */ - void onBackMotion(float touchX, float touchY, int keyAction, + void onBackMotion( + float touchX, + float touchY, + float velocityX, + float velocityY, + int keyAction, @BackEvent.SwipeEdge int swipeEdge); /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 04f8477eb749..47d3a5c52074 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -256,8 +256,20 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont private class BackAnimationImpl implements BackAnimation { @Override public void onBackMotion( - float touchX, float touchY, int keyAction, @BackEvent.SwipeEdge int swipeEdge) { - mShellExecutor.execute(() -> onMotionEvent(touchX, touchY, keyAction, swipeEdge)); + float touchX, + float touchY, + float velocityX, + float velocityY, + int keyAction, + @BackEvent.SwipeEdge int swipeEdge + ) { + mShellExecutor.execute(() -> onMotionEvent( + /* touchX = */ touchX, + /* touchY = */ touchY, + /* velocityX = */ velocityX, + /* velocityY = */ velocityY, + /* keyAction = */ keyAction, + /* swipeEdge = */ swipeEdge)); } @Override @@ -332,13 +344,18 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont * Called when a new motion event needs to be transferred to this * {@link BackAnimationController} */ - public void onMotionEvent(float touchX, float touchY, int keyAction, + public void onMotionEvent( + float touchX, + float touchY, + float velocityX, + float velocityY, + int keyAction, @BackEvent.SwipeEdge int swipeEdge) { if (mPostCommitAnimationInProgress) { return; } - mTouchTracker.update(touchX, touchY); + mTouchTracker.update(touchX, touchY, velocityX, velocityY); if (keyAction == MotionEvent.ACTION_DOWN) { if (!mBackGestureStarted) { mShouldStartOnNextMoveEvent = true; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java index 695ef4e66302..904574b08562 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java @@ -42,11 +42,13 @@ class TouchTracker { */ private float mInitTouchX; private float mInitTouchY; + private float mLatestVelocityX; + private float mLatestVelocityY; private float mStartThresholdX; private int mSwipeEdge; private boolean mCancelled; - void update(float touchX, float touchY) { + void update(float touchX, float touchY, float velocityX, float velocityY) { /** * If back was previously cancelled but the user has started swiping in the forward * direction again, restart back. @@ -58,6 +60,8 @@ class TouchTracker { } mLatestTouchX = touchX; mLatestTouchY = touchY; + mLatestVelocityX = velocityX; + mLatestVelocityY = velocityY; } void setTriggerBack(boolean triggerBack) { @@ -84,7 +88,14 @@ class TouchTracker { } BackMotionEvent createStartEvent(RemoteAnimationTarget target) { - return new BackMotionEvent(mInitTouchX, mInitTouchY, 0, mSwipeEdge, target); + return new BackMotionEvent( + /* touchX = */ mInitTouchX, + /* touchY = */ mInitTouchY, + /* progress = */ 0, + /* velocityX = */ 0, + /* velocityY = */ 0, + /* swipeEdge = */ mSwipeEdge, + /* departingAnimationTarget = */ target); } BackMotionEvent createProgressEvent() { @@ -111,7 +122,14 @@ class TouchTracker { } BackMotionEvent createProgressEvent(float progress) { - return new BackMotionEvent(mLatestTouchX, mLatestTouchY, progress, mSwipeEdge, null); + return new BackMotionEvent( + /* touchX = */ mLatestTouchX, + /* touchY = */ mLatestTouchY, + /* progress = */ progress, + /* velocityX = */ mLatestVelocityX, + /* velocityY = */ mLatestVelocityY, + /* swipeEdge = */ mSwipeEdge, + /* departingAnimationTarget = */ null); } public void setProgressThreshold(float progressThreshold) { diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml index 67ca9a1a17f7..b6d92814ad43 100644 --- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml +++ b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml @@ -29,6 +29,7 @@ <option name="teardown-command" value="settings delete secure show_ime_with_hard_keyboard" /> <option name="teardown-command" value="settings delete system show_touches" /> <option name="teardown-command" value="settings delete system pointer_location" /> + <option name="teardown-command" value="cmd overlay enable com.android.internal.systemui.navbar.gestural" /> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> <option name="cleanup-apks" value="true"/> diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java index 0673484f6336..d95c7a488ea1 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java @@ -474,9 +474,12 @@ public class BackAnimationControllerTest extends ShellTestCase { private void doMotionEvent(int actionDown, int coordinate) { mController.onMotionEvent( - coordinate, coordinate, - actionDown, - BackEvent.EDGE_LEFT); + /* touchX */ coordinate, + /* touchY */ coordinate, + /* velocityX = */ 0, + /* velocityY = */ 0, + /* keyAction */ actionDown, + /* swipeEdge */ BackEvent.EDGE_LEFT); } private void simulateRemoteAnimationStart(int type) throws RemoteException { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java index 3608474bd90e..874ef80c29f0 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackProgressAnimatorTest.java @@ -16,8 +16,6 @@ package com.android.wm.shell.back; -import static android.window.BackEvent.EDGE_LEFT; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -48,12 +46,21 @@ public class BackProgressAnimatorTest { private CountDownLatch mTargetProgressCalled = new CountDownLatch(1); private Handler mMainThreadHandler; + private BackMotionEvent backMotionEventFrom(float touchX, float progress) { + return new BackMotionEvent( + /* touchX = */ touchX, + /* touchY = */ 0, + /* progress = */ progress, + /* velocityX = */ 0, + /* velocityY = */ 0, + /* swipeEdge = */ BackEvent.EDGE_LEFT, + /* departingAnimationTarget = */ null); + } + @Before public void setUp() throws Exception { mMainThreadHandler = new Handler(Looper.getMainLooper()); - final BackMotionEvent backEvent = new BackMotionEvent( - 0, 0, - 0, EDGE_LEFT, null); + final BackMotionEvent backEvent = backMotionEventFrom(0, 0); mMainThreadHandler.post( () -> { mProgressAnimator = new BackProgressAnimator(); @@ -63,9 +70,7 @@ public class BackProgressAnimatorTest { @Test public void testBackProgressed() throws InterruptedException { - final BackMotionEvent backEvent = new BackMotionEvent( - 100, 0, - mTargetProgress, EDGE_LEFT, null); + final BackMotionEvent backEvent = backMotionEventFrom(100, mTargetProgress); mMainThreadHandler.post( () -> mProgressAnimator.onBackProgressed(backEvent)); @@ -78,9 +83,7 @@ public class BackProgressAnimatorTest { @Test public void testBackCancelled() throws InterruptedException { // Give the animator some progress. - final BackMotionEvent backEvent = new BackMotionEvent( - 100, 0, - mTargetProgress, EDGE_LEFT, null); + final BackMotionEvent backEvent = backMotionEventFrom(100, mTargetProgress); mMainThreadHandler.post( () -> mProgressAnimator.onBackProgressed(backEvent)); mTargetProgressCalled.await(1, TimeUnit.SECONDS); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.java index ba9c159bad28..d62e6601723a 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.java @@ -47,43 +47,45 @@ public class TouchTrackerTest { public void generatesProgress_leftEdge() { mTouchTracker.setGestureStartLocation(INITIAL_X_LEFT_EDGE, 0, BackEvent.EDGE_LEFT); float touchX = 10; + float velocityX = 0; + float velocityY = 0; // Pre-commit - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (touchX - INITIAL_X_LEFT_EDGE) / FAKE_THRESHOLD, 0f); // Post-commit touchX += 100; mTouchTracker.setTriggerBack(true); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (touchX - INITIAL_X_LEFT_EDGE) / FAKE_THRESHOLD, 0f); // Cancel touchX -= 10; mTouchTracker.setTriggerBack(false); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Cancel more touchX -= 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Restart touchX += 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Restarted, but pre-commit float restartX = touchX; touchX += 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (touchX - restartX) / FAKE_THRESHOLD, 0f); // Restarted, post-commit touchX += 10; mTouchTracker.setTriggerBack(true); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (touchX - INITIAL_X_LEFT_EDGE) / FAKE_THRESHOLD, 0f); } @@ -91,43 +93,45 @@ public class TouchTrackerTest { public void generatesProgress_rightEdge() { mTouchTracker.setGestureStartLocation(INITIAL_X_RIGHT_EDGE, 0, BackEvent.EDGE_RIGHT); float touchX = INITIAL_X_RIGHT_EDGE - 10; // Fake right edge + float velocityX = 0f; + float velocityY = 0f; // Pre-commit - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (INITIAL_X_RIGHT_EDGE - touchX) / FAKE_THRESHOLD, 0f); // Post-commit touchX -= 100; mTouchTracker.setTriggerBack(true); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (INITIAL_X_RIGHT_EDGE - touchX) / FAKE_THRESHOLD, 0f); // Cancel touchX += 10; mTouchTracker.setTriggerBack(false); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Cancel more touchX += 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Restart touchX -= 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), 0, 0f); // Restarted, but pre-commit float restartX = touchX; touchX -= 10; - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (restartX - touchX) / FAKE_THRESHOLD, 0f); // Restarted, post-commit touchX -= 10; mTouchTracker.setTriggerBack(true); - mTouchTracker.update(touchX, 0); + mTouchTracker.update(touchX, 0, velocityX, velocityY); assertEquals(getProgress(), (INITIAL_X_RIGHT_EDGE - touchX) / FAKE_THRESHOLD, 0f); } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index fedfb43535cc..78d93bd19a15 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -58,7 +58,6 @@ <uses-permission android:name="android.permission.ACCEPT_HANDOVER" /> <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" /> <uses-permission android:name="android.permission.BODY_SENSORS" /> - <uses-permission android:name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE" /> <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" /> <uses-permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" /> <uses-permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" /> diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt index 322fc774e805..05630e795476 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt @@ -199,6 +199,9 @@ data class ClockConfig( */ val hasCustomPositionUpdatedAnimation: Boolean = false, + /** Transition to AOD should move smartspace like large clock instead of small clock */ + val useAlternateSmartspaceAODTransition: Boolean = false, + /** True if the clock will react to tone changes in the seed color. */ val isReactiveToTone: Boolean = true, ) diff --git a/packages/SystemUI/res/drawable/chipbar_background.xml b/packages/SystemUI/res/drawable/chipbar_background.xml index 57221776a32f..7530f5ba244a 100644 --- a/packages/SystemUI/res/drawable/chipbar_background.xml +++ b/packages/SystemUI/res/drawable/chipbar_background.xml @@ -17,6 +17,6 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> - <solid android:color="?androidprv:attr/colorAccentSecondary" /> + <solid android:color="?androidprv:attr/materialColorSecondaryFixed" /> <corners android:radius="32dp" /> </shape> diff --git a/packages/SystemUI/res/drawable/chipbar_end_button_background.xml b/packages/SystemUI/res/drawable/chipbar_end_button_background.xml index 80c7207a35b6..a3832eef957f 100644 --- a/packages/SystemUI/res/drawable/chipbar_end_button_background.xml +++ b/packages/SystemUI/res/drawable/chipbar_end_button_background.xml @@ -20,7 +20,7 @@ android:color="?android:textColorPrimary"> <item android:id="@android:id/background"> <shape> - <solid android:color="@android:color/system_accent1_200"/> + <solid android:color="?androidprv:attr/materialColorPrimaryFixedDim"/> <corners android:radius="24dp" /> </shape> </item> diff --git a/packages/SystemUI/res/drawable/hearing.xml b/packages/SystemUI/res/drawable/hearing.xml new file mode 100644 index 000000000000..02f5f92ec5fe --- /dev/null +++ b/packages/SystemUI/res/drawable/hearing.xml @@ -0,0 +1,24 @@ +<!-- Copyright (C) 2023 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="48dp" + android:height="48dp" + android:viewportWidth="48" + android:viewportHeight="48" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M34.4,43.95Q31.55,43.95 29.45,42.4Q27.35,40.85 26.35,38.3Q25.35,35.75 24.375,34.325Q23.4,32.9 20.7,30.75Q17.4,28.1 15.95,25.1Q14.5,22.1 14.5,17.8Q14.5,11.8 18.3,7.975Q22.1,4.15 28.1,4.15Q34,4.15 37.875,7.825Q41.75,11.5 42,17.2H39Q38.75,12.8 35.725,9.975Q32.7,7.15 28.1,7.15Q23.6,7.15 20.55,10.225Q17.5,13.3 17.5,17.8Q17.5,21.4 18.9,24.025Q20.3,26.65 23.55,29.1Q25.5,30.55 26.675,32.25Q27.85,33.95 28.9,36.45Q29.75,38.55 31.125,39.75Q32.5,40.95 34.4,40.95Q36.15,40.95 37.425,39.75Q38.7,38.55 38.95,36.8H41.95Q41.7,39.8 39.55,41.875Q37.4,43.95 34.4,43.95ZM11.95,32.9Q9.1,29.75 7.55,25.825Q6,21.9 6,17.6Q6,13.35 7.475,9.375Q8.95,5.4 11.95,2.35L14.2,4.35Q11.6,7 10.3,10.425Q9,13.85 9,17.6Q9,21.3 10.325,24.725Q11.65,28.15 14.2,30.85ZM28.1,22.45Q26.15,22.45 24.8,21.1Q23.45,19.75 23.45,17.8Q23.45,15.85 24.8,14.45Q26.15,13.05 28.1,13.05Q30.05,13.05 31.45,14.45Q32.85,15.85 32.85,17.8Q32.85,19.75 31.45,21.1Q30.05,22.45 28.1,22.45Z"/> +</vector> diff --git a/packages/SystemUI/res/layout/chipbar.xml b/packages/SystemUI/res/layout/chipbar.xml index 762dcdced9c4..8fa975be43d2 100644 --- a/packages/SystemUI/res/layout/chipbar.xml +++ b/packages/SystemUI/res/layout/chipbar.xml @@ -49,15 +49,17 @@ android:alpha="0.0" /> + <!-- LINT.IfChange textColor --> <TextView android:id="@+id/text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:textSize="@dimen/chipbar_text_size" - android:textColor="@color/chipbar_text_and_icon_color" + style="@style/Chipbar.Text" + android:textColor="?androidprv:attr/materialColorOnSecondaryFixed" android:alpha="0.0" /> + <!-- LINT.ThenChange(systemui.temporarydisplay.chipbar.ChipbarInfo.kt) --> <!-- At most one of [loading, failure_icon, undo] will be visible at a time. --> <ImageView @@ -66,7 +68,7 @@ android:layout_height="@dimen/chipbar_end_icon_size" android:layout_marginStart="@dimen/chipbar_end_item_start_margin" android:src="@drawable/ic_progress_activity" - android:tint="@android:color/system_accent2_700" + android:tint="?androidprv:attr/materialColorOnSecondaryFixedVariant" android:alpha="0.0" /> @@ -84,9 +86,9 @@ android:id="@+id/end_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="?androidprv:attr/textColorOnAccent" android:layout_marginStart="@dimen/chipbar_end_item_start_margin" - android:textSize="@dimen/chipbar_text_size" + style="@style/Chipbar.Text" + android:textColor="?androidprv:attr/materialColorOnPrimaryFixed" android:paddingStart="@dimen/chipbar_outer_padding" android:paddingEnd="@dimen/chipbar_outer_padding" android:paddingTop="@dimen/chipbar_end_button_vertical_padding" diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 96e6d4e1a234..cb8c2a73c15d 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -231,9 +231,6 @@ <color name="people_tile_background">@color/material_dynamic_secondary95</color> - <!-- Chipbar --> - <color name="chipbar_text_and_icon_color">@android:color/system_accent2_900</color> - <!-- Internet Dialog --> <!-- Material next state on color--> <color name="settingslib_state_on_color">@color/settingslib_state_on</color> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 4db42aacbdcd..0eb0a078a478 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1110,6 +1110,7 @@ <!-- Chipbar --> <!-- (Used for media tap-to-transfer chip for sender device and active unlock) --> <dimen name="chipbar_outer_padding">16dp</dimen> + <dimen name="chipbar_outer_padding_half">8dp</dimen> <dimen name="chipbar_text_size">16sp</dimen> <dimen name="chipbar_start_icon_size">24dp</dimen> <dimen name="chipbar_end_icon_size">20dp</dimen> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 2098aea87ab2..a359d3b21938 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -70,6 +70,15 @@ <item name="android:fontWeight">700</item> </style> + <style name="Chipbar" /> + + <style name="Chipbar.Text" parent="@*android:style/TextAppearance.DeviceDefault.Notification.Title"> + <!-- Text size should be kept in sync with the notification conversation header size. (The + conversation header doesn't have a defined style, so the size must be copied here.) + See notification_template_conversation_header.xml. --> + <item name="android:textSize">16sp</item> + </style> + <style name="TextAppearance" /> <style name="TextAppearance.QS"> diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index 0779653430b2..7262a736c433 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -25,6 +25,7 @@ import android.graphics.Rect import android.text.format.DateFormat import android.util.TypedValue import android.view.View +import android.view.View.OnAttachStateChangeListener import android.view.ViewTreeObserver import android.widget.FrameLayout import androidx.annotation.VisibleForTesting @@ -105,6 +106,24 @@ constructor( } updateFontSizes() updateTimeListeners() + value.smallClock.view.addOnAttachStateChangeListener( + object : OnAttachStateChangeListener { + override fun onViewAttachedToWindow(p0: View?) { + value.events.onTimeFormatChanged(DateFormat.is24HourFormat(context)) + } + + override fun onViewDetachedFromWindow(p0: View?) { + } + }) + value.largeClock.view.addOnAttachStateChangeListener( + object : OnAttachStateChangeListener { + override fun onViewAttachedToWindow(p0: View?) { + value.events.onTimeFormatChanged(DateFormat.is24HourFormat(context)) + } + + override fun onViewDetachedFromWindow(p0: View?) { + } + }) } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index 6f549881d12a..0cdef4d63639 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -73,7 +73,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV */ private static final int KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION = 1000; - private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = + public static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); private final KeyguardSliceViewController mKeyguardSliceViewController; @@ -221,16 +221,32 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV mView.setImportantForAccessibility(mode); } + @VisibleForTesting + void setProperty(AnimatableProperty property, float value, boolean animate) { + PropertyAnimator.setProperty(mView, property, value, CLOCK_ANIMATION_PROPERTIES, animate); + } + /** * Update position of the view with an optional animation */ public void updatePosition(int x, int y, float scale, boolean animate) { float oldY = mView.getY(); - PropertyAnimator.setProperty(mView, AnimatableProperty.Y, y, CLOCK_ANIMATION_PROPERTIES, - animate); + setProperty(AnimatableProperty.Y, y, animate); + + ClockController clock = mKeyguardClockSwitchController.getClock(); + if (clock != null && clock.getConfig().getUseAlternateSmartspaceAODTransition()) { + // If requested, scale the entire view instead of just the clock view + mKeyguardClockSwitchController.updatePosition(x, 1f /* scale */, + CLOCK_ANIMATION_PROPERTIES, animate); + setProperty(AnimatableProperty.SCALE_X, scale, animate); + setProperty(AnimatableProperty.SCALE_Y, scale, animate); + } else { + mKeyguardClockSwitchController.updatePosition(x, scale, + CLOCK_ANIMATION_PROPERTIES, animate); + setProperty(AnimatableProperty.SCALE_X, 1f, animate); + setProperty(AnimatableProperty.SCALE_Y, 1f, animate); + } - mKeyguardClockSwitchController.updatePosition(x, scale, CLOCK_ANIMATION_PROPERTIES, - animate); if (oldY != y) { mKeyguardClockSwitchController.updateKeyguardStatusViewOffset(); } diff --git a/packages/SystemUI/src/com/android/systemui/common/shared/model/TintedIcon.kt b/packages/SystemUI/src/com/android/systemui/common/shared/model/TintedIcon.kt index 6a6c3eb05399..0869351e727b 100644 --- a/packages/SystemUI/src/com/android/systemui/common/shared/model/TintedIcon.kt +++ b/packages/SystemUI/src/com/android/systemui/common/shared/model/TintedIcon.kt @@ -16,10 +16,10 @@ package com.android.systemui.common.shared.model -import androidx.annotation.ColorRes +import androidx.annotation.AttrRes /** Models an icon with a specific tint. */ data class TintedIcon( val icon: Icon, - @ColorRes val tint: Int?, + @AttrRes val tint: Int?, ) diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/binder/TintedIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/common/ui/binder/TintedIconViewBinder.kt index bcc5932dcf30..5c5723fa0a5e 100644 --- a/packages/SystemUI/src/com/android/systemui/common/ui/binder/TintedIconViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/common/ui/binder/TintedIconViewBinder.kt @@ -17,6 +17,7 @@ package com.android.systemui.common.ui.binder import android.widget.ImageView +import com.android.settingslib.Utils import com.android.systemui.common.shared.model.TintedIcon object TintedIconViewBinder { @@ -33,7 +34,7 @@ object TintedIconViewBinder { IconViewBinder.bind(tintedIcon.icon, view) view.imageTintList = if (tintedIcon.tint != null) { - view.resources.getColorStateList(tintedIcon.tint, view.context.theme) + Utils.getColorAttr(view.context, tintedIcon.tint) } else { null } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java index 7f44463f1191..aca621bd9e55 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java @@ -41,6 +41,7 @@ import com.google.common.util.concurrent.ListenableFuture; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.Set; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -195,7 +196,14 @@ public class DreamOverlayTouchMonitor { * Called by the monitor when this session is removed. */ private void onRemoved() { - mCallbacks.forEach(callback -> callback.onRemoved()); + mEventListeners.clear(); + mGestureListeners.clear(); + final Iterator<Callback> iter = mCallbacks.iterator(); + while (iter.hasNext()) { + final Callback callback = iter.next(); + callback.onRemoved(); + iter.remove(); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 012c8cfdd115..2987004347e4 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -108,11 +108,6 @@ object Flags { val NOTIFICATION_SHELF_REFACTOR = unreleasedFlag(271161129, "notification_shelf_refactor") - // TODO(b/263414400): Tracking Bug - @JvmField - val NOTIFICATION_ANIMATE_BIG_PICTURE = - releasedFlag(120, "notification_animate_big_picture") - @JvmField val ANIMATED_NOTIFICATION_SHADE_INSETS = releasedFlag(270682168, "animated_notification_shade_insets") diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt index dbc2a5ec4e0a..b29b5887545a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt @@ -19,7 +19,7 @@ package com.android.systemui.media.taptotransfer.common import android.content.Context import android.content.pm.PackageManager import android.graphics.drawable.Drawable -import androidx.annotation.ColorRes +import androidx.annotation.AttrRes import androidx.annotation.DrawableRes import com.android.systemui.R import com.android.systemui.common.shared.model.ContentDescription @@ -108,7 +108,7 @@ class MediaTttUtils { data class IconInfo( val contentDescription: ContentDescription, val icon: MediaTttIcon, - @ColorRes val tint: Int?, + @AttrRes val tint: Int?, /** * True if [drawable] is the app's icon, and false if [drawable] is some generic default icon. */ diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index 26b0e8dd9895..b9ef916eebdf 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -55,6 +55,7 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; +import android.view.VelocityTracker; import android.view.ViewConfiguration; import android.view.WindowInsets; import android.view.WindowManager; @@ -173,7 +174,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack } }; - + private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private final Context mContext; private final UserTracker mUserTracker; private final OverviewProxyService mOverviewProxyService; @@ -901,6 +902,10 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack Log.d(DEBUG_MISSING_GESTURE_TAG, "Start gesture: " + ev); } + // ACTION_UP or ACTION_CANCEL is not guaranteed to be called before a new + // ACTION_DOWN, in that case we should just reuse the old instance. + mVelocityTracker.clear(); + // Verify if this is in within the touch region and we aren't in immersive mode, and // either the bouncer is showing or the notification panel is hidden mInputEventReceiver.setBatchingEnabled(false); @@ -1027,11 +1032,30 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack private void dispatchToBackAnimation(MotionEvent event) { if (mBackAnimation != null) { + mVelocityTracker.addMovement(event); + + final float velocityX; + final float velocityY; + if (event.getAction() == MotionEvent.ACTION_UP) { + // Compute the current velocity is expensive (see computeCurrentVelocity), so we + // are only doing it when the user completes the gesture. + int unitPixelPerSecond = 1000; + int maxVelocity = mViewConfiguration.getScaledMaximumFlingVelocity(); + mVelocityTracker.computeCurrentVelocity(unitPixelPerSecond, maxVelocity); + velocityX = mVelocityTracker.getXVelocity(); + velocityY = mVelocityTracker.getYVelocity(); + } else { + velocityX = Float.NaN; + velocityY = Float.NaN; + } + mBackAnimation.onBackMotion( - event.getX(), - event.getY(), - event.getActionMasked(), - mIsOnLeftEdge ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT); + /* touchX = */ event.getX(), + /* touchY = */ event.getY(), + /* velocityX = */ velocityX, + /* velocityY = */ velocityY, + /* keyAction = */ event.getActionMasked(), + /* swipeEdge = */ mIsOnLeftEdge ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java index 57b479e6899f..856c64a52290 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java @@ -20,8 +20,6 @@ import android.content.res.Resources; import android.os.Build; import android.provider.Settings; -import com.android.internal.logging.InstanceId; -import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.qs.QSTile; @@ -55,11 +53,9 @@ public interface QSHost { return tiles; } - void warn(String message, Throwable t); Context getContext(); Context getUserContext(); int getUserId(); - UiEventLogger getUiEventLogger(); Collection<QSTile> getTiles(); void addCallback(Callback callback); void removeCallback(Callback callback); @@ -107,8 +103,6 @@ public interface QSHost { int indexOf(String tileSpec); - InstanceId getNewInstanceId(); - interface Callback { void onTilesChanged(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt index 14acb4b3ccf4..67927a4153b3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt @@ -19,8 +19,6 @@ package com.android.systemui.qs import android.content.ComponentName import android.content.Context import androidx.annotation.GuardedBy -import com.android.internal.logging.InstanceId -import com.android.internal.logging.UiEventLogger import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dump.DumpManager @@ -39,10 +37,9 @@ import kotlinx.coroutines.launch /** * Adapter to determine what real class to use for classes that depend on [QSHost]. - * * * When [Flags.QS_PIPELINE_NEW_HOST] is off, all calls will be routed to [QSTileHost]. * * When [Flags.QS_PIPELINE_NEW_HOST] is on, calls regarding the current set of tiles will be - * routed to [CurrentTilesInteractor]. Other calls (like [warn]) will still be routed to + * routed to [CurrentTilesInteractor]. Other calls (like [createTileView]) will still be routed to * [QSTileHost]. * * This routing also includes dumps. @@ -71,10 +68,7 @@ constructor( init { scope.launch { tileServiceRequestControllerBuilder.create(this@QSHostAdapter).init() } // Redirect dump to the correct host (needed for CTS tests) - dumpManager.registerCriticalDumpable( - TAG, - if (useNewHost) interactor else qsTileHost - ) + dumpManager.registerCriticalDumpable(TAG, if (useNewHost) interactor else qsTileHost) } override fun getTiles(): Collection<QSTile> { @@ -103,10 +97,7 @@ constructor( override fun addCallback(callback: QSHost.Callback) { if (useNewHost) { - val job = - scope.launch { - interactor.currentTiles.collect { callback.onTilesChanged() } - } + val job = scope.launch { interactor.currentTiles.collect { callback.onTilesChanged() } } synchronized(callbacksMap) { callbacksMap.put(callback, job) } } else { qsTileHost.addCallback(callback) @@ -147,10 +138,7 @@ constructor( override fun addTile(component: ComponentName, end: Boolean) { if (useNewHost) { - interactor.addTile( - TileSpec.create(component), - if (end) POSITION_AT_END else 0 - ) + interactor.addTile(TileSpec.create(component), if (end) POSITION_AT_END else 0) } else { qsTileHost.addTile(component, end) } @@ -164,10 +152,6 @@ constructor( } } - override fun warn(message: String?, t: Throwable?) { - qsTileHost.warn(message, t) - } - override fun getContext(): Context { return if (useNewHost) { context @@ -192,10 +176,6 @@ constructor( } } - override fun getUiEventLogger(): UiEventLogger { - return qsTileHost.uiEventLogger - } - override fun createTileView( themedContext: Context?, tile: QSTile?, @@ -219,8 +199,4 @@ constructor( override fun indexOf(tileSpec: String): Int { return specs.indexOf(tileSpec) } - - override fun getNewInstanceId(): InstanceId { - return qsTileHost.newInstanceId - } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index 0ca897373d13..59b94b7c4bd4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -29,9 +29,6 @@ import androidx.annotation.MainThread; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.logging.InstanceId; -import com.android.internal.logging.InstanceIdSequence; -import com.android.internal.logging.UiEventLogger; import com.android.systemui.Dumpable; import com.android.systemui.ProtoDumpable; import com.android.systemui.R; @@ -91,7 +88,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P PanelInteractor, CustomTileAddedRepository { private static final String TAG = "QSTileHost"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - private static final int MAX_QS_INSTANCE_ID = 1 << 20; // Shared prefs that hold tile lifecycle info. @VisibleForTesting @@ -103,8 +99,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P private final TunerService mTunerService; private final PluginManager mPluginManager; private final QSLogger mQSLogger; - private final UiEventLogger mUiEventLogger; - private final InstanceIdSequence mInstanceIdSequence; private final CustomTileStatePersister mCustomTileStatePersister; private final Executor mMainExecutor; private final UserFileManager mUserFileManager; @@ -137,7 +131,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P Provider<AutoTileManager> autoTiles, Optional<CentralSurfaces> centralSurfacesOptional, QSLogger qsLogger, - UiEventLogger uiEventLogger, UserTracker userTracker, SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister, @@ -150,13 +143,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P mTunerService = tunerService; mPluginManager = pluginManager; mQSLogger = qsLogger; - mUiEventLogger = uiEventLogger; mMainExecutor = mainExecutor; mTileLifeCycleManagerFactory = tileLifecycleManagerFactory; mUserFileManager = userFileManager; mFeatureFlags = featureFlags; - mInstanceIdSequence = new InstanceIdSequence(MAX_QS_INSTANCE_ID); mCentralSurfacesOptional = centralSurfacesOptional; mQsFactories.add(defaultFactory); @@ -175,11 +166,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P }); } - @Override - public InstanceId getNewInstanceId() { - return mInstanceIdSequence.newInstanceId(); - } - public void destroy() { mTiles.values().forEach(tile -> tile.destroy()); mAutoTiles.destroy(); @@ -207,11 +193,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P } @Override - public UiEventLogger getUiEventLogger() { - return mUiEventLogger; - } - - @Override public void addCallback(Callback callback) { mCallbacks.add(callback); } @@ -227,11 +208,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, P } @Override - public void warn(String message, Throwable t) { - // already logged - } - - @Override public void collapsePanels() { mCentralSurfacesOptional.ifPresent(CentralSurfaces::postAnimateCollapsePanels); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QsEventLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/QsEventLogger.kt new file mode 100644 index 000000000000..fc739edc69d2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/QsEventLogger.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 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.qs + +import com.android.internal.logging.InstanceId +import com.android.internal.logging.InstanceIdSequence +import com.android.internal.logging.UiEventLogger +import com.android.systemui.dagger.SysUISingleton +import javax.inject.Inject + +interface QsEventLogger : UiEventLogger { + fun getNewInstanceId(): InstanceId +} + +@SysUISingleton +class QsEventLoggerImpl +@Inject +constructor( + uiEventLogger: UiEventLogger, +) : QsEventLogger, UiEventLogger by uiEventLogger { + + companion object { + private const val MAX_QS_INSTANCE_ID = 1 shl 20 + } + + val sequence = InstanceIdSequence(MAX_QS_INSTANCE_ID) + override fun getNewInstanceId(): InstanceId { + return sequence.newInstanceId() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt index 3ddd9f1cfe5f..1f63f5da2f2b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt @@ -21,6 +21,8 @@ import com.android.systemui.flags.Flags import com.android.systemui.qs.QSHost import com.android.systemui.qs.QSHostAdapter import com.android.systemui.qs.QSTileHost +import com.android.systemui.qs.QsEventLogger +import com.android.systemui.qs.QsEventLoggerImpl import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedRepository import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedSharedPrefsRepository import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor @@ -34,8 +36,12 @@ interface QSHostModule { @Binds fun provideQsHost(controllerImpl: QSHostAdapter): QSHost + @Binds fun provideEventLogger(impl: QsEventLoggerImpl): QsEventLogger + @Module companion object { + private const val MAX_QS_INSTANCE_ID = 1 shl 20 + @Provides @JvmStatic fun providePanelInteractor( diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java index d4854e1a7daf..897b0e73dca0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java @@ -59,17 +59,20 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.State; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.settings.DisplayTracker; +import dagger.Lazy; + import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import javax.inject.Inject; -import dagger.Lazy; + public class CustomTile extends QSTileImpl<State> implements TileChangeListener { public static final String PREFIX = "custom("; @@ -111,6 +114,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener private CustomTile( QSHost host, + QsEventLogger uiEventLogger, Looper backgroundLooper, Handler mainHandler, FalsingManager falsingManager, @@ -124,7 +128,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener TileServices tileServices, DisplayTracker displayTracker ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mTileServices = tileServices; mWindowManager = WindowManagerGlobal.getWindowManagerService(); @@ -561,6 +565,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener public static class Builder { final Lazy<QSHost> mQSHostLazy; + final QsEventLogger mUiEventLogger; final Looper mBackgroundLooper; final Handler mMainHandler; private final FalsingManager mFalsingManager; @@ -578,6 +583,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener @Inject public Builder( Lazy<QSHost> hostLazy, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -590,6 +596,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener DisplayTracker displayTracker ) { mQSHostLazy = hostLazy; + mUiEventLogger = uiEventLogger; mBackgroundLooper = backgroundLooper; mMainHandler = mainHandler; mFalsingManager = falsingManager; @@ -620,6 +627,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener String action = getAction(mSpec); return new CustomTile( mQSHostLazy.get(), + mUiEventLogger, mBackgroundLooper, mMainHandler, mFalsingManager, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 49ba5086f64d..2a9e7d05c187 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -66,6 +66,7 @@ import com.android.systemui.plugins.qs.QSTile.State; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSEvent; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SideLabelTileLayout; import com.android.systemui.qs.logging.QSLogger; @@ -179,6 +180,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy protected QSTileImpl( QSHost host, + QsEventLogger uiEventLogger, Looper backgroundLooper, Handler mainHandler, FalsingManager falsingManager, @@ -189,8 +191,8 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy ) { mHost = host; mContext = host.getContext(); - mInstanceId = host.getNewInstanceId(); - mUiEventLogger = host.getUiEventLogger(); + mInstanceId = uiEventLogger.getNewInstanceId(); + mUiEventLogger = uiEventLogger; mUiHandler = mainHandler; mHandler = new H(backgroundLooper); @@ -633,7 +635,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy } catch (Throwable t) { final String error = "Error in " + name; Log.w(TAG, error, t); - mHost.warn(error, t); } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java index 92a83bba8a68..30765f7f974d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java @@ -45,15 +45,18 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.settings.UserTracker; import com.android.systemui.util.settings.GlobalSettings; +import dagger.Lazy; + import javax.inject.Inject; -import dagger.Lazy; + /** Quick settings tile: Airplane mode **/ public class AirplaneModeTile extends QSTileImpl<BooleanState> { @@ -69,6 +72,7 @@ public class AirplaneModeTile extends QSTileImpl<BooleanState> { @Inject public AirplaneModeTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -81,7 +85,7 @@ public class AirplaneModeTile extends QSTileImpl<BooleanState> { GlobalSettings globalSettings, UserTracker userTracker ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mBroadcastDispatcher = broadcastDispatcher; mLazyConnectivityManager = lazyConnectivityManager; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt index 2ca452e45ecf..c709969ec6e2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt @@ -22,6 +22,7 @@ import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.settings.UserTracker @@ -31,6 +32,7 @@ import javax.inject.Inject class AlarmTile @Inject constructor( host: QSHost, + uiEventLogger: QsEventLogger, @Background backgroundLooper: Looper, @Main mainHandler: Handler, falsingManager: FalsingManager, @@ -42,6 +44,7 @@ class AlarmTile @Inject constructor( nextAlarmController: NextAlarmController ) : QSTileImpl<QSTile.State>( host, + uiEventLogger, backgroundLooper, mainHandler, falsingManager, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java index 027a464251c9..a444e7631527 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java @@ -37,6 +37,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -62,6 +63,7 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements @Inject public BatterySaverTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -72,7 +74,7 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements BatteryController batteryController, SecureSettings secureSettings ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mBatteryController = batteryController; mBatteryController.observe(getLifecycle(), this); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 08fe2709b810..30218a6a3180 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -47,6 +47,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.BluetoothController; @@ -74,6 +75,7 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { @Inject public BluetoothTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -83,7 +85,7 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { QSLogger qsLogger, BluetoothController bluetoothController ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mController = bluetoothController; mController.observe(getLifecycle(), mCallback); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java index 93e5f1efbdc8..65ef6b9c31a5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java @@ -37,6 +37,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -48,7 +49,9 @@ public class CameraToggleTile extends SensorPrivacyToggleTile { public static final String TILE_SPEC = "cameratoggle"; @Inject - protected CameraToggleTile(QSHost host, + protected CameraToggleTile( + QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, MetricsLogger metricsLogger, @@ -58,7 +61,7 @@ public class CameraToggleTile extends SensorPrivacyToggleTile { QSLogger qsLogger, IndividualSensorPrivacyController sensorPrivacyController, KeyguardStateController keyguardStateController) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger, sensorPrivacyController, keyguardStateController); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 8d984817ba77..54376fe604df 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -47,6 +47,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.connectivity.NetworkController; @@ -84,6 +85,7 @@ public class CastTile extends QSTileImpl<BooleanState> { @Inject public CastTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -97,7 +99,7 @@ public class CastTile extends QSTileImpl<BooleanState> { HotspotController hotspotController, DialogLaunchAnimator dialogLaunchAnimator ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mController = castController; mKeyguard = keyguardStateController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java index b6205d5df63d..cf9e3468c8f5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java @@ -37,6 +37,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -56,6 +57,7 @@ public class ColorCorrectionTile extends QSTileImpl<BooleanState> { @Inject public ColorCorrectionTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -66,7 +68,7 @@ public class ColorCorrectionTile extends QSTileImpl<BooleanState> { UserTracker userTracker, SecureSettings secureSettings ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mSetting = new SettingObserver(secureSettings, mHandler, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index 9a44e83ad9a1..4ecde6123dd5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -38,6 +38,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -55,6 +56,7 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> { @Inject public ColorInversionTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -65,7 +67,7 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> { UserTracker userTracker, SecureSettings secureSettings ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mSetting = new SettingObserver(secureSettings, mHandler, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java index add517e18516..e769b5ef9989 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java @@ -38,6 +38,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.SystemUIDialog; @@ -58,6 +59,7 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements @Inject public DataSaverTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -68,7 +70,7 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements DataSaverController dataSaverController, DialogLaunchAnimator dialogLaunchAnimator ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mDataSaverController = dataSaverController; mDialogLaunchAnimator = dialogLaunchAnimator; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt index 01164fb0a009..ddaff3bb9a64 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt @@ -40,6 +40,7 @@ import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import java.util.concurrent.atomic.AtomicBoolean @@ -47,6 +48,7 @@ import javax.inject.Inject class DeviceControlsTile @Inject constructor( host: QSHost, + uiEventLogger: QsEventLogger, @Background backgroundLooper: Looper, @Main mainHandler: Handler, falsingManager: FalsingManager, @@ -56,14 +58,15 @@ class DeviceControlsTile @Inject constructor( qsLogger: QSLogger, private val controlsComponent: ControlsComponent ) : QSTileImpl<QSTile.State>( - host, - backgroundLooper, - mainHandler, - falsingManager, - metricsLogger, - statusBarStateController, - activityStarter, - qsLogger + host, + uiEventLogger, + backgroundLooper, + mainHandler, + falsingManager, + metricsLogger, + statusBarStateController, + activityStarter, + qsLogger ) { private var hasControlsApps = AtomicBoolean(false) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 434fe45f47c0..3e7bdd1a1444 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -54,6 +54,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -88,6 +89,7 @@ public class DndTile extends QSTileImpl<BooleanState> { @Inject public DndTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -100,7 +102,7 @@ public class DndTile extends QSTileImpl<BooleanState> { SecureSettings secureSettings, DialogLaunchAnimator dialogLaunchAnimator ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mController = zenModeController; mSharedPreferences = sharedPreferences; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java index f913326a6a67..eef4c1dd4436 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java @@ -48,6 +48,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -90,6 +91,7 @@ public class DreamTile extends QSTileImpl<QSTile.BooleanState> { @Inject public DreamTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -105,7 +107,7 @@ public class DreamTile extends QSTileImpl<QSTile.BooleanState> { @Named(DreamModule.DREAM_ONLY_ENABLED_FOR_DOCK_USER) boolean dreamOnlyEnabledForDockUser ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mDreamManager = dreamManager; mBroadcastDispatcher = broadcastDispatcher; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index e091a750fbec..2c986da8370a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -37,6 +37,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.FlashlightController; @@ -55,6 +56,7 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements @Inject public FlashlightTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -64,7 +66,7 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements QSLogger qsLogger, FlashlightController flashlightController ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mFlashlightController = flashlightController; mFlashlightController.observe(getLifecycle(), this); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt index 3f514344cee1..12d98473ff07 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt @@ -36,6 +36,7 @@ import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.phone.SystemUIDialog @@ -47,6 +48,7 @@ class FontScalingTile @Inject constructor( host: QSHost, + uiEventLogger: QsEventLogger, @Background backgroundLooper: Looper, @Main mainHandler: Handler, falsingManager: FalsingManager, @@ -61,6 +63,7 @@ constructor( ) : QSTileImpl<QSTile.State?>( host, + uiEventLogger, backgroundLooper, mainHandler, falsingManager, diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index 6bf8b7666054..4c3699ced6e5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -41,6 +41,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.DataSaverController; @@ -61,6 +62,7 @@ public class HotspotTile extends QSTileImpl<BooleanState> { @Inject public HotspotTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -71,7 +73,7 @@ public class HotspotTile extends QSTileImpl<BooleanState> { HotspotController hotspotController, DataSaverController dataSaverController ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mHotspotController = hotspotController; mDataSaverController = dataSaverController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java index 75d01723667d..f16f0dcc5dba 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java @@ -51,6 +51,7 @@ import com.android.systemui.plugins.qs.QSTile.SignalState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.AlphaControlledSignalTileView; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; @@ -90,6 +91,7 @@ public class InternetTile extends QSTileImpl<SignalState> { @Inject public InternetTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -101,7 +103,7 @@ public class InternetTile extends QSTileImpl<SignalState> { AccessPointController accessPointController, InternetDialogFactory internetDialogFactory ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mInternetDialogFactory = internetDialogFactory; mHandler = mainHandler; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index 27f58269722a..83c568878c94 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -37,6 +37,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -59,6 +60,7 @@ public class LocationTile extends QSTileImpl<BooleanState> { @Inject public LocationTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -70,7 +72,7 @@ public class LocationTile extends QSTileImpl<BooleanState> { KeyguardStateController keyguardStateController, PanelInteractor panelInteractor ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mController = locationController; mKeyguard = keyguardStateController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java index 2e475d40d55f..86a6a8c6a2b6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java @@ -37,6 +37,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -48,7 +49,9 @@ public class MicrophoneToggleTile extends SensorPrivacyToggleTile { public static final String TILE_SPEC = "mictoggle"; @Inject - protected MicrophoneToggleTile(QSHost host, + protected MicrophoneToggleTile( + QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, MetricsLogger metricsLogger, @@ -58,7 +61,7 @@ public class MicrophoneToggleTile extends SensorPrivacyToggleTile { QSLogger qsLogger, IndividualSensorPrivacyController sensorPrivacyController, KeyguardStateController keyguardStateController) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger, sensorPrivacyController, keyguardStateController); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java index e189f80a7c23..29ccb76de820 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java @@ -43,6 +43,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -65,6 +66,7 @@ public class NfcTile extends QSTileImpl<BooleanState> { @Inject public NfcTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -74,7 +76,7 @@ public class NfcTile extends QSTileImpl<BooleanState> { QSLogger qsLogger, BroadcastDispatcher broadcastDispatcher ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mBroadcastDispatcher = broadcastDispatcher; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java index aacd53bde51c..405e1394871c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java @@ -45,6 +45,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.LocationController; @@ -80,6 +81,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements @Inject public NightDisplayTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -91,7 +93,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements ColorDisplayManager colorDisplayManager, NightDisplayListenerModule.Builder nightDisplayListenerBuilder ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mLocationController = locationController; mManager = colorDisplayManager; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java index ae67d99ea2fb..1eb317aaeae8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java @@ -36,6 +36,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -57,6 +58,7 @@ public class OneHandedModeTile extends QSTileImpl<BooleanState> { @Inject public OneHandedModeTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -66,7 +68,7 @@ public class OneHandedModeTile extends QSTileImpl<BooleanState> { QSLogger qsLogger, UserTracker userTracker, SecureSettings secureSettings) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mSetting = new SettingObserver(secureSettings, mHandler, Settings.Secure.ONE_HANDED_MODE_ENABLED, userTracker.getUserId()) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java index 92f52724ca0c..9e365d34bed9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java @@ -37,6 +37,7 @@ import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -62,6 +63,7 @@ public class QRCodeScannerTile extends QSTileImpl<QSTile.State> { @Inject public QRCodeScannerTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -70,7 +72,7 @@ public class QRCodeScannerTile extends QSTileImpl<QSTile.State> { ActivityStarter activityStarter, QSLogger qsLogger, QRCodeScannerController qrCodeScannerController) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mQRCodeScannerController = qrCodeScannerController; mQRCodeScannerController.observe(getLifecycle(), mCallback); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java index 4a3c56328006..e026bdbc2e08 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java @@ -49,6 +49,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -83,6 +84,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> { @Inject public QuickAccessWalletTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -94,7 +96,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> { PackageManager packageManager, SecureSettings secureSettings, QuickAccessWalletController quickAccessWalletController) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mController = quickAccessWalletController; mKeyguardStateController = keyguardStateController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java index 10f1ce4946c8..2e04afb0048a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java @@ -38,6 +38,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.ReduceBrightColorsController; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -59,6 +60,7 @@ public class ReduceBrightColorsTile extends QSTileImpl<QSTile.BooleanState> @Named(RBC_AVAILABLE) boolean isAvailable, ReduceBrightColorsController reduceBrightColorsController, QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -67,7 +69,7 @@ public class ReduceBrightColorsTile extends QSTileImpl<QSTile.BooleanState> ActivityStarter activityStarter, QSLogger qsLogger ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mReduceBrightColorsController = reduceBrightColorsController; mReduceBrightColorsController.observe(getLifecycle(), this); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index 8888c733c3c1..7f7f8ad6a4c1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -44,6 +44,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SettingObserver; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -71,6 +72,7 @@ public class RotationLockTile extends QSTileImpl<BooleanState> implements @Inject public RotationLockTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -83,7 +85,7 @@ public class RotationLockTile extends QSTileImpl<BooleanState> implements BatteryController batteryController, SecureSettings secureSettings ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mController = rotationLockController; mController.observe(this, mCallback); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java index 65592a717565..2d4652db6b80 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java @@ -41,6 +41,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -74,6 +75,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> @Inject public ScreenRecordTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -88,7 +90,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> DialogLaunchAnimator dialogLaunchAnimator, PanelInteractor panelInteractor ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mController = controller; mController.observe(this, mCallback); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java index d99c1d1daf7e..7c4f097a1724 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java @@ -39,6 +39,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; @@ -68,7 +69,9 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS */ public abstract String getRestriction(); - protected SensorPrivacyToggleTile(QSHost host, + protected SensorPrivacyToggleTile( + QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -78,7 +81,7 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS QSLogger qsLogger, IndividualSensorPrivacyController sensorPrivacyController, KeyguardStateController keyguardStateController) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mSensorPrivacyController = sensorPrivacyController; mKeyguard = keyguardStateController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java index 809689cb806d..a60d1ad448b4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java @@ -39,6 +39,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.BatteryController; @@ -69,6 +70,7 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements @Inject public UiModeNightTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -80,7 +82,7 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements BatteryController batteryController, LocationController locationController ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mBatteryController = batteryController; mUiModeManager = host.getUserContext().getSystemService(UiModeManager.class); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index 6a5c99032457..17e72e597e58 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -40,6 +40,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile.BooleanState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.ManagedProfileController; @@ -59,6 +60,7 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements @Inject public WorkModeTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -68,7 +70,7 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements QSLogger qsLogger, ManagedProfileController managedProfileController ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mProfileController = managedProfileController; mProfileController.observe(getLifecycle(), this); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index a9d125508397..98b4cc4d7d27 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -419,15 +419,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView */ public void setAnimationRunning(boolean running) { // Sets animations running in the private/public layouts. - if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_ANIMATE_BIG_PICTURE)) { - for (NotificationContentView l : mLayouts) { - if (l != null) { - l.setContentAnimationRunning(running); - setIconAnimationRunning(running, l); - } - } - } else { - for (NotificationContentView l : mLayouts) { + for (NotificationContentView l : mLayouts) { + if (l != null) { + l.setContentAnimationRunning(running); setIconAnimationRunning(running, l); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt index 075e6ec11ae7..a05ab849088d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt @@ -26,15 +26,7 @@ import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsVi import java.io.PrintWriter import javax.inject.Inject import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.mapLatest -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** @@ -46,39 +38,16 @@ import kotlinx.coroutines.launch * the list of available mobile lines of service for which we want to show icons. */ @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") -@OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton class MobileUiAdapter @Inject constructor( - interactor: MobileIconsInteractor, private val iconController: StatusBarIconController, - private val iconsViewModelFactory: MobileIconsViewModel.Factory, + val mobileIconsViewModel: MobileIconsViewModel, private val logger: MobileViewLogger, @Application private val scope: CoroutineScope, private val statusBarPipelineFlags: StatusBarPipelineFlags, ) : CoreStartable { - private val mobileSubIds: Flow<List<Int>> = - interactor.filteredSubscriptions.mapLatest { subscriptions -> - subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId } - } - - /** - * We expose the list of tracked subscriptions as a flow of a list of ints, where each int is - * the subscriptionId of the relevant subscriptions. These act as a key into the layouts which - * house the mobile infos. - * - * NOTE: this should go away as the view presenter learns more about this data pipeline - */ - private val mobileSubIdsState: StateFlow<List<Int>> = - mobileSubIds - .distinctUntilChanged() - .onEach { logger.logUiAdapterSubIdsUpdated(it) } - .stateIn(scope, SharingStarted.WhileSubscribed(), listOf()) - - /** In order to keep the logs tame, we will reuse the same top-level mobile icons view model */ - val mobileIconsViewModel = iconsViewModelFactory.create(mobileSubIdsState) - private var isCollecting: Boolean = false private var lastValue: List<Int>? = null @@ -90,7 +59,7 @@ constructor( if (statusBarPipelineFlags.useNewMobileIcons()) { scope.launch { isCollecting = true - mobileSubIds.collectLatest { + mobileIconsViewModel.subscriptionIdsFlow.collectLatest { logger.logUiAdapterSubIdsSentToIconController(it) lastValue = it iconController.setNewMobileIconSubIds(it) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt index 90dff23c637c..f2f91430eba6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt @@ -41,15 +41,6 @@ constructor( private val collectionStatuses = mutableMapOf<String, Boolean>() - fun logUiAdapterSubIdsUpdated(subs: List<Int>) { - buffer.log( - TAG, - LogLevel.INFO, - { str1 = subs.toString() }, - { "Sub IDs in MobileUiAdapter updated internally: $str1" }, - ) - } - fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) { buffer.log( TAG, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt index 2b90065284d0..9af5e836659f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt @@ -29,18 +29,23 @@ import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMob import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants import javax.inject.Inject import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch /** * View model for describing the system's current mobile cellular connections. The result is a list * of [MobileIconViewModel]s which describe the individual icons and can be bound to - * [ModernStatusBarMobileView] + * [ModernStatusBarMobileView]. */ +@OptIn(ExperimentalCoroutinesApi::class) +@SysUISingleton class MobileIconsViewModel @Inject constructor( - val subscriptionIdsFlow: StateFlow<List<Int>>, val logger: MobileViewLogger, private val verboseLogger: VerboseMobileViewLogger, private val interactor: MobileIconsInteractor, @@ -51,6 +56,13 @@ constructor( ) { @VisibleForTesting val mobileIconSubIdCache = mutableMapOf<Int, MobileIconViewModel>() + val subscriptionIdsFlow: StateFlow<List<Int>> = + interactor.filteredSubscriptions + .mapLatest { subscriptions -> + subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId } + } + .stateIn(scope, SharingStarted.WhileSubscribed(), listOf()) + init { scope.launch { subscriptionIdsFlow.collect { removeInvalidModelsFromCache(it) } } } @@ -79,30 +91,4 @@ constructor( val subIdsToRemove = mobileIconSubIdCache.keys.filter { !subIds.contains(it) } subIdsToRemove.forEach { mobileIconSubIdCache.remove(it) } } - - @SysUISingleton - class Factory - @Inject - constructor( - private val logger: MobileViewLogger, - private val verboseLogger: VerboseMobileViewLogger, - private val interactor: MobileIconsInteractor, - private val airplaneModeInteractor: AirplaneModeInteractor, - private val constants: ConnectivityConstants, - @Application private val scope: CoroutineScope, - private val statusBarPipelineFlags: StatusBarPipelineFlags, - ) { - fun create(subscriptionIdsFlow: StateFlow<List<Int>>): MobileIconsViewModel { - return MobileIconsViewModel( - subscriptionIdsFlow, - logger, - verboseLogger, - interactor, - airplaneModeInteractor, - constants, - scope, - statusBarPipelineFlags, - ) - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt index a20a5b2fdbbc..e819f946a6d6 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt @@ -31,6 +31,7 @@ import android.view.WindowManager import android.view.accessibility.AccessibilityManager import android.widget.ImageView import android.widget.TextView +import androidx.annotation.DimenRes import androidx.annotation.IdRes import androidx.annotation.VisibleForTesting import com.android.internal.widget.CachingIconView @@ -180,8 +181,9 @@ constructor( // Button val buttonView = currentView.requireViewById<TextView>(R.id.end_button) - if (newInfo.endItem is ChipbarEndItem.Button) { - TextViewBinder.bind(buttonView, newInfo.endItem.text) + val hasButton = newInfo.endItem is ChipbarEndItem.Button + if (hasButton) { + TextViewBinder.bind(buttonView, (newInfo.endItem as ChipbarEndItem.Button).text) val onClickListener = View.OnClickListener { clickedView -> @@ -196,6 +198,12 @@ constructor( buttonView.visibility = View.GONE } + currentView + .getInnerView() + .setEndPadding( + if (hasButton) R.dimen.chipbar_outer_padding_half else R.dimen.chipbar_outer_padding + ) + // ---- Overall accessibility ---- val iconDesc = newInfo.startIcon.icon.contentDescription val loadedIconDesc = @@ -309,6 +317,15 @@ constructor( viewUtil.setRectToViewWindowLocation(view, outRect) } + private fun View.setEndPadding(@DimenRes endPaddingDimen: Int) { + this.setPaddingRelative( + this.paddingStart, + this.paddingTop, + context.resources.getDimensionPixelSize(endPaddingDimen), + this.paddingBottom, + ) + } + private fun Boolean.visibleIfTrue(): Int { return if (this) { View.VISIBLE diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt index 6e58f2296c86..52f2d11f814e 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt @@ -18,7 +18,7 @@ package com.android.systemui.temporarydisplay.chipbar import android.os.VibrationEffect import android.view.View -import androidx.annotation.ColorRes +import androidx.annotation.AttrRes import com.android.systemui.R import com.android.systemui.common.shared.model.Text import com.android.systemui.common.shared.model.TintedIcon @@ -49,7 +49,9 @@ data class ChipbarInfo( override val priority: ViewPriority, ) : TemporaryViewInfo() { companion object { - @ColorRes val DEFAULT_ICON_TINT = R.color.chipbar_text_and_icon_color + // LINT.IfChange + @AttrRes val DEFAULT_ICON_TINT = com.android.internal.R.attr.materialColorOnSecondaryFixed + // LINT.ThenChange(systemui/res/layout/chipbar.xml) } } diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java index 209ea41fed61..58cffa761a66 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java @@ -58,6 +58,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -418,6 +419,7 @@ public class GarbageMonitor implements Dumpable { @Inject public MemoryTile( QSHost host, + QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, @@ -428,7 +430,7 @@ public class GarbageMonitor implements Dumpable { GarbageMonitor monitor, PanelInteractor panelInteractor ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); gm = monitor; mPanelInteractor = panelInteractor; diff --git a/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java index 35af44442ca9..e3ed2b405fb0 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java @@ -16,20 +16,34 @@ package com.android.systemui.volume; +import static android.app.PendingIntent.FLAG_IMMUTABLE; + import android.annotation.StringRes; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; -import android.os.CountDownTimer; +import android.provider.Settings; import android.util.Log; import android.view.KeyEvent; import android.view.WindowManager; import com.android.internal.annotations.GuardedBy; +import com.android.internal.messages.nano.SystemMessageProto; +import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.statusbar.phone.SystemUIDialog; +import com.android.systemui.util.NotificationChannels; +import com.android.systemui.util.concurrency.DelayableExecutor; + +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; /** * A class that implements the four Computed Sound Dose-related warnings defined in {@link AudioManager}: @@ -53,34 +67,58 @@ import com.android.systemui.statusbar.phone.SystemUIDialog; * communication between the native audio framework that implements the dose computation and the * audio service. */ -public abstract class CsdWarningDialog extends SystemUIDialog +public class CsdWarningDialog extends SystemUIDialog implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener { private static final String TAG = Util.logTag(CsdWarningDialog.class); private static final int KEY_CONFIRM_ALLOWED_AFTER_MS = 1000; // milliseconds // time after which action is taken when the user hasn't ack'd or dismissed the dialog - private static final int NO_ACTION_TIMEOUT_MS = 5000; + public static final int NO_ACTION_TIMEOUT_MS = 5000; private final Context mContext; private final AudioManager mAudioManager; private final @AudioManager.CsdWarning int mCsdWarning; private final Object mTimerLock = new Object(); + /** * Timer to keep track of how long the user has before an action (here volume reduction) is * taken on their behalf. */ @GuardedBy("mTimerLock") - private final CountDownTimer mNoUserActionTimer; + private Runnable mNoUserActionRunnable; + private Runnable mCancelScheduledNoUserActionRunnable = null; + + private final DelayableExecutor mDelayableExecutor; + private NotificationManager mNotificationManager; + private Runnable mOnCleanup; private long mShowTime; - public CsdWarningDialog(@AudioManager.CsdWarning int csdWarning, Context context, - AudioManager audioManager) { + /** + * To inject dependencies and allow for easier testing + */ + @AssistedFactory + public interface Factory { + /** + * Create a dialog object + */ + CsdWarningDialog create(int csdWarning, Runnable onCleanup); + } + + @AssistedInject + public CsdWarningDialog(@Assisted @AudioManager.CsdWarning int csdWarning, Context context, + AudioManager audioManager, NotificationManager notificationManager, + @Background DelayableExecutor delayableExecutor, @Assisted Runnable onCleanup) { super(context); mCsdWarning = csdWarning; mContext = context; mAudioManager = audioManager; + mNotificationManager = notificationManager; + mOnCleanup = onCleanup; + + mDelayableExecutor = delayableExecutor; + getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); setShowForAllUsers(true); setMessage(mContext.getString(getStringForWarning(csdWarning))); @@ -95,25 +133,24 @@ public abstract class CsdWarningDialog extends SystemUIDialog Context.RECEIVER_EXPORTED_UNAUDITED); if (csdWarning == AudioManager.CSD_WARNING_DOSE_REACHED_1X) { - mNoUserActionTimer = new CountDownTimer(NO_ACTION_TIMEOUT_MS, NO_ACTION_TIMEOUT_MS) { - @Override - public void onTick(long millisUntilFinished) { } - - @Override - public void onFinish() { - if (mCsdWarning == AudioManager.CSD_WARNING_DOSE_REACHED_1X) { - // unlike on the 5x dose repeat, level is only reduced to RS1 - // when the warning is not acknowledged quick enough - mAudioManager.lowerVolumeToRs1(); - } + mNoUserActionRunnable = () -> { + if (mCsdWarning == AudioManager.CSD_WARNING_DOSE_REACHED_1X) { + // unlike on the 5x dose repeat, level is only reduced to RS1 when the warning + // is not acknowledged quickly enough + mAudioManager.lowerVolumeToRs1(); + sendNotification(); } }; } else { - mNoUserActionTimer = null; + mNoUserActionRunnable = null; } } - protected abstract void cleanUp(); + private void cleanUp() { + if (mOnCleanup != null) { + mOnCleanup.run(); + } + } // NOT overriding onKeyDown as we're not allowing a dismissal on any key other than // VOLUME_DOWN, and for this, we don't need to track if it's the start of a new @@ -153,12 +190,9 @@ public abstract class CsdWarningDialog extends SystemUIDialog super.onStart(); mShowTime = System.currentTimeMillis(); synchronized (mTimerLock) { - if (mNoUserActionTimer != null) { - new Thread(() -> { - synchronized (mTimerLock) { - mNoUserActionTimer.start(); - } - }).start(); + if (mNoUserActionRunnable != null) { + mCancelScheduledNoUserActionRunnable = mDelayableExecutor.executeDelayed( + mNoUserActionRunnable, NO_ACTION_TIMEOUT_MS); } } } @@ -166,8 +200,8 @@ public abstract class CsdWarningDialog extends SystemUIDialog @Override protected void onStop() { synchronized (mTimerLock) { - if (mNoUserActionTimer != null) { - mNoUserActionTimer.cancel(); + if (mCancelScheduledNoUserActionRunnable != null) { + mCancelScheduledNoUserActionRunnable.run(); } } } @@ -212,4 +246,32 @@ public abstract class CsdWarningDialog extends SystemUIDialog Log.e(TAG, "Invalid CSD warning event " + csdWarning, new Exception()); return com.android.internal.R.string.csd_dose_reached_warning; } + + + /** + * In case user did not respond to the dialog, they still need to know volume was lowered. + */ + private void sendNotification() { + Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS); + PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, + FLAG_IMMUTABLE); + + String text = mContext.getString(R.string.csd_system_lowered_text); + String title = mContext.getString(R.string.csd_lowered_title); + + Notification.Builder builder = + new Notification.Builder(mContext, NotificationChannels.ALERTS) + .setSmallIcon(R.drawable.hearing) + .setContentTitle(title) + .setContentText(text) + .setContentIntent(pendingIntent) + .setStyle(new Notification.BigTextStyle().bigText(text)) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setLocalOnly(true) + .setAutoCancel(true) + .setCategory(Notification.CATEGORY_SYSTEM); + + mNotificationManager.notify(SystemMessageProto.SystemMessage.NOTE_CSD_LOWER_AUDIO, + builder.build()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 95cc12a48bb2..3c007f99a654 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -263,6 +263,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, private final ConfigurationController mConfigurationController; private final MediaOutputDialogFactory mMediaOutputDialogFactory; private final VolumePanelFactory mVolumePanelFactory; + private final CsdWarningDialog.Factory mCsdWarningDialogFactory; private final ActivityStarter mActivityStarter; private boolean mShowing; @@ -311,6 +312,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, InteractionJankMonitor interactionJankMonitor, DeviceConfigProxy deviceConfigProxy, Executor executor, + CsdWarningDialog.Factory csdWarningDialogFactory, DumpManager dumpManager) { mContext = new ContextThemeWrapper(context, R.style.volume_dialog_theme); @@ -322,6 +324,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mConfigurationController = configurationController; mMediaOutputDialogFactory = mediaOutputDialogFactory; mVolumePanelFactory = volumePanelFactory; + mCsdWarningDialogFactory = csdWarningDialogFactory; mActivityStarter = activityStarter; mShowActiveStreamOnly = showActiveStreamOnly(); mHasSeenODICaptionsTooltip = @@ -2084,21 +2087,21 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, rescheduleTimeoutH(); } - private void showCsdWarningH(int csdWarning, int durationMs) { + @VisibleForTesting void showCsdWarningH(int csdWarning, int durationMs) { synchronized (mSafetyWarningLock) { + if (mCsdDialog != null) { return; } - mCsdDialog = new CsdWarningDialog(csdWarning, - mContext, mController.getAudioManager()) { - @Override - protected void cleanUp() { - synchronized (mSafetyWarningLock) { - mCsdDialog = null; - } - recheckH(null); + + final Runnable cleanUp = () -> { + synchronized (mSafetyWarningLock) { + mCsdDialog = null; } + recheckH(null); }; + + mCsdDialog = mCsdWarningDialogFactory.create(csdWarning, cleanUp); mCsdDialog.show(); } recheckH(null); diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java index 0ab6c690e1e1..14d3ca334073 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java +++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java @@ -30,17 +30,18 @@ import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.util.DeviceConfigProxy; +import com.android.systemui.volume.CsdWarningDialog; import com.android.systemui.volume.VolumeComponent; import com.android.systemui.volume.VolumeDialogComponent; import com.android.systemui.volume.VolumeDialogImpl; import com.android.systemui.volume.VolumePanelFactory; -import java.util.concurrent.Executor; - import dagger.Binds; import dagger.Module; import dagger.Provides; +import java.util.concurrent.Executor; + /** Dagger Module for code in the volume package. */ @Module @@ -63,6 +64,7 @@ public interface VolumeModule { InteractionJankMonitor interactionJankMonitor, DeviceConfigProxy deviceConfigProxy, @Main Executor executor, + CsdWarningDialog.Factory csdFactory, DumpManager dumpManager) { VolumeDialogImpl impl = new VolumeDialogImpl( context, @@ -76,6 +78,7 @@ public interface VolumeModule { interactionJankMonitor, deviceConfigProxy, executor, + csdFactory, dumpManager); impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false); impl.setAutomute(true); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java index f1ee1080f6c0..2c1d2adb11ee 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java @@ -16,7 +16,9 @@ package com.android.keyguard; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; @@ -25,6 +27,9 @@ import com.android.internal.jank.InteractionJankMonitor; import com.android.keyguard.logging.KeyguardLogger; import com.android.systemui.SysuiTestCase; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.plugins.ClockConfig; +import com.android.systemui.plugins.ClockController; +import com.android.systemui.statusbar.notification.AnimatableProperty; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.ScreenOffAnimationController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -76,7 +81,16 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase { mScreenOffAnimationController, mKeyguardLogger, mFeatureFlags, - mInteractionJankMonitor); + mInteractionJankMonitor) { + @Override + void setProperty( + AnimatableProperty property, + float value, + boolean animate) { + // Route into the mock version for verification + mControllerMock.setProperty(property, value, animate); + } + }; } @Test @@ -111,4 +125,34 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase { configurationListenerArgumentCaptor.getValue().onLocaleListChanged(); verify(mKeyguardClockSwitchController).onLocaleListChanged(); } + + @Test + public void updatePosition_primaryClockAnimation() { + ClockController mockClock = mock(ClockController.class); + when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock); + when(mockClock.getConfig()).thenReturn(new ClockConfig(false, false, true)); + + mController.updatePosition(10, 15, 20f, true); + + verify(mControllerMock).setProperty(AnimatableProperty.Y, 15f, true); + verify(mKeyguardClockSwitchController).updatePosition( + 10, 20f, KeyguardStatusViewController.CLOCK_ANIMATION_PROPERTIES, true); + verify(mControllerMock).setProperty(AnimatableProperty.SCALE_X, 1f, true); + verify(mControllerMock).setProperty(AnimatableProperty.SCALE_Y, 1f, true); + } + + @Test + public void updatePosition_alternateClockAnimation() { + ClockController mockClock = mock(ClockController.class); + when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock); + when(mockClock.getConfig()).thenReturn(new ClockConfig(false, true, true)); + + mController.updatePosition(10, 15, 20f, true); + + verify(mControllerMock).setProperty(AnimatableProperty.Y, 15f, true); + verify(mKeyguardClockSwitchController).updatePosition( + 10, 1f, KeyguardStatusViewController.CLOCK_ANIMATION_PROPERTIES, true); + verify(mControllerMock).setProperty(AnimatableProperty.SCALE_X, 20f, true); + verify(mControllerMock).setProperty(AnimatableProperty.SCALE_Y, 20f, true); + } } 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 0978c824cb15..9c36af3a35e4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -18,6 +18,7 @@ package com.android.systemui.accessibility; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; +import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static android.view.Choreographer.FrameCallback; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_UP; @@ -172,6 +173,12 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { returnsSecondArg()); mResources = getContext().getOrCreateTestableResources().getResources(); + // prevent the config orientation from undefined, which may cause config.diff method + // neglecting the orientation update. + if (mResources.getConfiguration().orientation == ORIENTATION_UNDEFINED) { + mResources.getConfiguration().orientation = ORIENTATION_PORTRAIT; + } + mWindowMagnificationAnimationController = new WindowMagnificationAnimationController( mContext, mValueAnimator); mWindowMagnificationController = @@ -688,7 +695,11 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test public void enableWindowMagnification_rotationIsChanged_updateRotationValue() { - final Configuration config = mContext.getResources().getConfiguration(); + // the config orientation should not be undefined, since it would cause config.diff + // returning 0 and thus the orientation changed would not be detected + assertNotEquals(ORIENTATION_UNDEFINED, mResources.getConfiguration().orientation); + + final Configuration config = mResources.getConfiguration(); config.orientation = config.orientation == ORIENTATION_LANDSCAPE ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; final int newRotation = simulateRotateTheDevice(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtensionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtensionTest.kt index 921f9a8fc7d6..2b95973363ad 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtensionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtensionTest.kt @@ -37,7 +37,13 @@ class OnBackAnimationCallbackExtensionTest : SysuiTestCase() { @Test fun onBackProgressed_shouldInvoke_onBackProgress() { - val backEvent = BackEvent(0f, 0f, 0f, BackEvent.EDGE_LEFT) + val backEvent = + BackEvent( + /* touchX = */ 0f, + /* touchY = */ 0f, + /* progress = */ 0f, + /* swipeEdge = */ BackEvent.EDGE_LEFT + ) onBackAnimationCallback.onBackStarted(backEvent) onBackAnimationCallback.onBackProgressed(backEvent) @@ -47,7 +53,13 @@ class OnBackAnimationCallbackExtensionTest : SysuiTestCase() { @Test fun onBackStarted_shouldInvoke_onBackStart() { - val backEvent = BackEvent(0f, 0f, 0f, BackEvent.EDGE_LEFT) + val backEvent = + BackEvent( + /* touchX = */ 0f, + /* touchY = */ 0f, + /* progress = */ 0f, + /* swipeEdge = */ BackEvent.EDGE_LEFT + ) onBackAnimationCallback.onBackStarted(backEvent) diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java index 08427dab978b..21397d97b578 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java @@ -269,6 +269,30 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { } @Test + public void testInputEventPropagationAfterRemoval() { + final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + + final Environment environment = new Environment(Stream.of(touchHandler) + .collect(Collectors.toCollection(HashSet::new))); + + final InputEvent initialEvent = Mockito.mock(InputEvent.class); + environment.publishInputEvent(initialEvent); + + // Ensure session started + final DreamTouchHandler.TouchSession session = captureSession(touchHandler); + final InputChannelCompat.InputEventListener eventListener = + registerInputEventListener(session); + + session.pop(); + environment.executeAll(); + + final InputEvent event = Mockito.mock(InputEvent.class); + environment.publishInputEvent(event); + + verify(eventListener, never()).onInputEvent(eq(event)); + } + + @Test public void testInputGesturePropagation() { final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java index aa92177e863e..e4d8b2598fe3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java @@ -46,7 +46,6 @@ import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.UiEventLogger; import com.android.internal.util.CollectionUtils; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -117,8 +116,6 @@ public class QSTileHostTest extends SysuiTestCase { @Mock private CustomTile mCustomTile; @Mock - private UiEventLogger mUiEventLogger; - @Mock private UserTracker mUserTracker; private SecureSettings mSecureSettings; @Mock @@ -164,7 +161,7 @@ public class QSTileHostTest extends SysuiTestCase { saveSetting(""); mQSTileHost = new TestQSTileHost(mContext, mDefaultFactory, mMainExecutor, mPluginManager, mTunerService, mAutoTiles, mCentralSurfaces, - mQSLogger, mUiEventLogger, mUserTracker, mSecureSettings, mCustomTileStatePersister, + mQSLogger, mUserTracker, mSecureSettings, mCustomTileStatePersister, mTileLifecycleManagerFactory, mUserFileManager, mFeatureFlags); mSecureSettings.registerContentObserverForUser(SETTING, new ContentObserver(null) { @@ -684,14 +681,14 @@ public class QSTileHostTest extends SysuiTestCase { QSFactory defaultFactory, Executor mainExecutor, PluginManager pluginManager, TunerService tunerService, Provider<AutoTileManager> autoTiles, - CentralSurfaces centralSurfaces, QSLogger qsLogger, UiEventLogger uiEventLogger, + CentralSurfaces centralSurfaces, QSLogger qsLogger, UserTracker userTracker, SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister, TileLifecycleManager.Factory tileLifecycleManagerFactory, UserFileManager userFileManager, FeatureFlags featureFlags) { super(context, defaultFactory, mainExecutor, pluginManager, tunerService, autoTiles, Optional.of(centralSurfaces), qsLogger, - uiEventLogger, userTracker, secureSettings, customTileStatePersister, + userTracker, secureSettings, customTileStatePersister, tileLifecycleManagerFactory, userFileManager, featureFlags); } @@ -710,6 +707,7 @@ public class QSTileHostTest extends SysuiTestCase { protected TestTile(QSHost host) { super( host, + mock(QsEventLogger.class), mock(Looper.class), mock(Handler.class), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QsEventLoggerFake.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QsEventLoggerFake.kt new file mode 100644 index 000000000000..40aa2607dc94 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QsEventLoggerFake.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 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.qs + +import com.android.internal.logging.InstanceId +import com.android.internal.logging.UiEventLogger +import com.android.internal.logging.testing.UiEventLoggerFake +import com.android.systemui.InstanceIdSequenceFake + +class QsEventLoggerFake( + uiEventLogger: UiEventLoggerFake, + private val instanceIdSequence: InstanceIdSequenceFake, +) : QsEventLogger, UiEventLogger by uiEventLogger { + + val lastInstanceId: Int + get() = instanceIdSequence.lastInstanceId + + override fun getNewInstanceId(): InstanceId { + return instanceIdSequence.newInstanceId() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt index ac106ef9bf51..198ed4ac08fd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt @@ -41,6 +41,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.settings.FakeDisplayTracker import com.android.systemui.util.mockito.any @@ -56,12 +57,12 @@ import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @@ -89,6 +90,7 @@ class CustomTileTest : SysuiTestCase() { @Mock private lateinit var applicationInfo: ApplicationInfo @Mock private lateinit var serviceInfo: ServiceInfo @Mock private lateinit var customTileStatePersister: CustomTileStatePersister + @Mock private lateinit var uiEventLogger: QsEventLogger private var displayTracker = FakeDisplayTracker(mContext) private lateinit var customTile: CustomTile @@ -115,6 +117,7 @@ class CustomTileTest : SysuiTestCase() { customTileBuilder = CustomTile.Builder( { tileHost }, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java index 36549fb826ec..962b53737274 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java @@ -61,6 +61,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; +import com.android.systemui.InstanceIdSequenceFake; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; @@ -69,6 +70,8 @@ import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSEvent; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; +import com.android.systemui.qs.QsEventLoggerFake; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.statusbar.StatusBarState; @@ -106,7 +109,8 @@ public class QSTileImplTest extends SysuiTestCase { private ActivityStarter mActivityStarter; private UiEventLoggerFake mUiEventLoggerFake; - private InstanceId mInstanceId = InstanceId.fakeInstanceId(5); + private QsEventLoggerFake mQsEventLoggerFake; + private InstanceId mInstanceId; @Captor private ArgumentCaptor<LogMaker> mLogCaptor; @@ -115,18 +119,29 @@ public class QSTileImplTest extends SysuiTestCase { public void setup() throws Exception { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); + mUiEventLoggerFake = new UiEventLoggerFake(); + mQsEventLoggerFake = + new QsEventLoggerFake(mUiEventLoggerFake, new InstanceIdSequenceFake(10)); when(mHost.indexOf(SPEC)).thenReturn(POSITION); when(mHost.getContext()).thenReturn(mContext); - when(mHost.getUiEventLogger()).thenReturn(mUiEventLoggerFake); - when(mHost.getNewInstanceId()).thenReturn(mInstanceId); Handler mainHandler = new Handler(mTestableLooper.getLooper()); - mTile = new TileImpl(mHost, mTestableLooper.getLooper(), mainHandler, mFalsingManager, - mMetricsLogger, mStatusBarStateController, mActivityStarter, mQsLogger); + mTile = new TileImpl( + mHost, + mQsEventLoggerFake, + mTestableLooper.getLooper(), + mainHandler, + mFalsingManager, + mMetricsLogger, + mStatusBarStateController, + mActivityStarter, + mQsLogger + ); mTile.initialize(); mTestableLooper.processAllMessages(); + mInstanceId = InstanceId.fakeInstanceId(mQsEventLoggerFake.getLastInstanceId()); mTile.setTileSpec(SPEC); } @@ -507,6 +522,7 @@ public class QSTileImplTest extends SysuiTestCase { protected TileImpl( QSHost host, + QsEventLogger uiEventLogger, Looper backgroundLooper, Handler mainHandler, FalsingManager falsingManager, @@ -515,7 +531,7 @@ public class QSTileImplTest extends SysuiTestCase { ActivityStarter activityStarter, QSLogger qsLogger ) { - super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); getState().state = Tile.STATE_ACTIVE; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt index 5e0190b65a12..c60cecb29d75 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt @@ -22,8 +22,6 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.UiEventLogger -import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher @@ -32,6 +30,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.settings.UserTracker @@ -68,20 +67,21 @@ class AirplaneModeTileTest : SysuiTestCase() { private lateinit var mGlobalSettings: GlobalSettings @Mock private lateinit var mUserTracker: UserTracker + @Mock + private lateinit var mUiEventLogger: QsEventLogger private lateinit var mTestableLooper: TestableLooper private lateinit var mTile: AirplaneModeTile - private val mUiEventLogger: UiEventLogger = UiEventLoggerFake() - @Before fun setUp() { MockitoAnnotations.initMocks(this) mTestableLooper = TestableLooper.get(this) Mockito.`when`(mHost.context).thenReturn(mContext) - Mockito.`when`(mHost.uiEventLogger).thenReturn(mUiEventLogger) Mockito.`when`(mHost.userContext).thenReturn(mContext) - mTile = AirplaneModeTile(mHost, + mTile = AirplaneModeTile( + mHost, + mUiEventLogger, mTestableLooper.looper, Handler(mTestableLooper.looper), FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt index f1e3e8a71398..52b84559f396 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt @@ -9,12 +9,12 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingManagerFake import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.policy.NextAlarmController @@ -28,8 +28,8 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @@ -52,7 +52,7 @@ class AlarmTileTest : SysuiTestCase() { @Mock private lateinit var nextAlarmController: NextAlarmController @Mock - private lateinit var uiEventLogger: UiEventLogger + private lateinit var uiEventLogger: QsEventLogger @Mock private lateinit var pendingIntent: PendingIntent @Captor @@ -67,10 +67,10 @@ class AlarmTileTest : SysuiTestCase() { testableLooper = TestableLooper.get(this) `when`(qsHost.context).thenReturn(mContext) - `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) tile = AlarmTile( qsHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt index a5c0004afe02..ff6814c06001 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt @@ -31,6 +31,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.BatteryController @@ -43,10 +44,10 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) @@ -63,6 +64,8 @@ class BatterySaverTileTest : SysuiTestCase() { @Mock private lateinit var qsHost: QSHost @Mock + private lateinit var uiEventLogger: QsEventLogger + @Mock private lateinit var metricsLogger: MetricsLogger @Mock private lateinit var statusBarStateController: StatusBarStateController @@ -90,6 +93,7 @@ class BatterySaverTileTest : SysuiTestCase() { tile = BatterySaverTile( qsHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt index 2e77de270c65..5e7f68ccf3d7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt @@ -9,7 +9,6 @@ import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.testing.UiEventLoggerFake import com.android.settingslib.Utils import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.systemui.R @@ -20,6 +19,7 @@ import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.BluetoothController @@ -49,8 +49,8 @@ class BluetoothTileTest : SysuiTestCase() { @Mock private lateinit var statusBarStateController: StatusBarStateController @Mock private lateinit var activityStarter: ActivityStarter @Mock private lateinit var bluetoothController: BluetoothController + @Mock private lateinit var uiEventLogger: QsEventLogger - private val uiEventLogger = UiEventLoggerFake() private lateinit var testableLooper: TestableLooper private lateinit var tile: FakeBluetoothTile @@ -60,11 +60,11 @@ class BluetoothTileTest : SysuiTestCase() { testableLooper = TestableLooper.get(this) whenever(qsHost.context).thenReturn(mContext) - whenever(qsHost.uiEventLogger).thenReturn(uiEventLogger) tile = FakeBluetoothTile( qsHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), falsingManager, @@ -211,6 +211,7 @@ class BluetoothTileTest : SysuiTestCase() { private class FakeBluetoothTile( qsHost: QSHost, + uiEventLogger: QsEventLogger, backgroundLooper: Looper, mainHandler: Handler, falsingManager: FalsingManager, @@ -222,6 +223,7 @@ class BluetoothTileTest : SysuiTestCase() { ) : BluetoothTile( qsHost, + uiEventLogger, backgroundLooper, mainHandler, falsingManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt index 41938541124a..70d82fdb6e5a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt @@ -21,8 +21,6 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.UiEventLogger -import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingManagerFake @@ -30,6 +28,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLoggerFake import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController @@ -67,19 +66,21 @@ class CameraToggleTileTest : SysuiTestCase() { private lateinit var privacyController: IndividualSensorPrivacyController @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock + private lateinit var uiEventLogger: QsEventLoggerFake private lateinit var testableLooper: TestableLooper private lateinit var tile: CameraToggleTile - private val uiEventLogger: UiEventLogger = UiEventLoggerFake() @Before fun setUp() { MockitoAnnotations.initMocks(this) testableLooper = TestableLooper.get(this) whenever(host.context).thenReturn(mContext) - whenever(host.uiEventLogger).thenReturn(uiEventLogger) - tile = CameraToggleTile(host, + tile = CameraToggleTile( + host, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), metricsLogger, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java index 64fd09d5f5d9..93ed99423f0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java @@ -43,6 +43,7 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.statusbar.connectivity.IconState; import com.android.systemui.statusbar.connectivity.NetworkController; @@ -94,6 +95,8 @@ public class CastTileTest extends SysuiTestCase { private QSLogger mQSLogger; @Mock private DialogLaunchAnimator mDialogLaunchAnimator; + @Mock + private QsEventLogger mUiEventLogger; private TestableLooper mTestableLooper; private CastTile mCastTile; @@ -107,6 +110,7 @@ public class CastTileTest extends SysuiTestCase { mCastTile = new CastTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java index 13c30e9ea9ab..2250ef33f9b4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java @@ -32,12 +32,12 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.UiEventLogger; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.settings.UserTracker; import com.android.systemui.util.settings.FakeSettings; @@ -67,7 +67,7 @@ public class ColorCorrectionTileTest extends SysuiTestCase { @Mock private QSLogger mQSLogger; @Mock - private UiEventLogger mUiEventLogger; + private QsEventLogger mUiEventLogger; @Mock private UserTracker mUserTracker; @@ -83,10 +83,10 @@ public class ColorCorrectionTileTest extends SysuiTestCase { mTestableLooper = TestableLooper.get(this); when(mHost.getContext()).thenReturn(mContext); - when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger); mTile = new ColorCorrectionTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java index ff27e0255aa3..2e02bbe2ebf2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java @@ -32,7 +32,6 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; @@ -40,6 +39,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.settings.UserTracker; @@ -72,7 +72,7 @@ public class ColorInversionTileTest extends SysuiTestCase { @Mock private QSLogger mQSLogger; @Mock - private UiEventLogger mUiEventLogger; + private QsEventLogger mUiEventLogger; @Mock private UserTracker mUserTracker; @@ -88,10 +88,10 @@ public class ColorInversionTileTest extends SysuiTestCase { mTestableLooper = TestableLooper.get(this); when(mHost.getContext()).thenReturn(mContext); - when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger); mTile = new ColorInversionTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt index b048643aba84..176b33fa9fc8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt @@ -21,7 +21,6 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.DialogLaunchAnimator @@ -30,6 +29,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.DataSaverController @@ -57,8 +57,8 @@ class DataSaverTileTest : SysuiTestCase() { @Mock private lateinit var activityStarter: ActivityStarter @Mock private lateinit var dataSaverController: DataSaverController @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator + @Mock private lateinit var uiEventLogger: QsEventLogger - private val uiEventLogger = UiEventLoggerFake() private lateinit var testableLooper: TestableLooper private lateinit var tile: DataSaverTile @@ -68,11 +68,11 @@ class DataSaverTileTest : SysuiTestCase() { testableLooper = TestableLooper.get(this) Mockito.`when`(mHost.context).thenReturn(mContext) - Mockito.`when`(mHost.uiEventLogger).thenReturn(uiEventLogger) tile = DataSaverTile( mHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), falsingManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt index b51c378f6b6b..1346069d3c25 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt @@ -27,7 +27,6 @@ import android.testing.TestableLooper import androidx.lifecycle.LifecycleOwner import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.UiEventLogger import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityLaunchAnimator @@ -44,6 +43,7 @@ import com.android.systemui.controls.ui.SelectedItem import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.util.mockito.any @@ -52,6 +52,7 @@ import com.android.systemui.util.mockito.eq import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.SecureSettings import com.google.common.truth.Truth.assertThat +import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -59,15 +60,14 @@ import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.Captor import org.mockito.Mock -import org.mockito.MockitoAnnotations -import org.mockito.Mockito.`when` import org.mockito.Mockito.doNothing import org.mockito.Mockito.nullable import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions +import org.mockito.Mockito.`when` +import org.mockito.MockitoAnnotations import java.util.Optional -import org.junit.After @SmallTest @RunWith(AndroidTestingRunner::class) @@ -95,7 +95,7 @@ class DeviceControlsTileTest : SysuiTestCase() { @Mock private lateinit var serviceInfo: ControlsServiceInfo @Mock - private lateinit var uiEventLogger: UiEventLogger + private lateinit var uiEventLogger: QsEventLogger @Captor private lateinit var listingCallbackCaptor: ArgumentCaptor<ControlsListingController.ControlsListingCallback> @@ -118,7 +118,6 @@ class DeviceControlsTileTest : SysuiTestCase() { spiedContext = spy(mContext) doNothing().`when`(spiedContext).startActivity(any(Intent::class.java)) `when`(qsHost.context).thenReturn(spiedContext) - `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) `when`(controlsComponent.isEnabled()).thenReturn(true) `when`(controlsController.getPreferredSelection()) .thenReturn(SelectedItem.StructureItem( @@ -399,6 +398,7 @@ class DeviceControlsTileTest : SysuiTestCase() { private fun createTile(): DeviceControlsTile { return DeviceControlsTile( qsHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt index 6c0904eb9bfd..f0e4e3adda7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt @@ -28,7 +28,6 @@ import android.testing.TestableLooper import android.view.View import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.UiEventLogger import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.DialogLaunchAnimator @@ -37,6 +36,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.ZenModeController @@ -46,7 +46,6 @@ import com.android.systemui.util.mockito.nullable import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.SecureSettings import com.google.common.truth.Truth.assertThat -import java.io.File import org.junit.After import org.junit.Before import org.junit.Test @@ -55,8 +54,9 @@ import org.mockito.Mock import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.never import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations +import java.io.File +import org.mockito.Mockito.`when` as whenever @SmallTest @RunWith(AndroidTestingRunner::class) @@ -84,7 +84,7 @@ class DndTileTest : SysuiTestCase() { private lateinit var qsLogger: QSLogger @Mock - private lateinit var uiEventLogger: UiEventLogger + private lateinit var uiEventLogger: QsEventLogger @Mock private lateinit var zenModeController: ZenModeController @@ -109,7 +109,6 @@ class DndTileTest : SysuiTestCase() { secureSettings = FakeSettings() whenever(qsHost.userId).thenReturn(DEFAULT_USER) - whenever(qsHost.uiEventLogger).thenReturn(uiEventLogger) val wrappedContext = object : ContextWrapper(context) { override fun getSharedPreferences(file: File?, mode: Int): SharedPreferences { @@ -120,6 +119,7 @@ class DndTileTest : SysuiTestCase() { tile = DndTile( qsHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java index 7d41aa6c3548..f231c6e56096 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DreamTileTest.java @@ -48,6 +48,7 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.settings.UserTracker; @@ -83,6 +84,8 @@ public class DreamTileTest extends SysuiTestCase { private BroadcastDispatcher mBroadcastDispatcher; @Mock private UserTracker mUserTracker; + @Mock + private QsEventLogger mUiEventLogger; private TestableLooper mTestableLooper; @@ -258,6 +261,7 @@ public class DreamTileTest extends SysuiTestCase { boolean dreamOnlyEnabledForSystemUser) { return new DreamTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt index 692a64422a7d..73aa6991c18a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt @@ -6,7 +6,6 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingManagerFake @@ -14,6 +13,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.FlashlightController @@ -45,7 +45,8 @@ class FlashlightTileTest : SysuiTestCase() { @Mock private lateinit var flashlightController: FlashlightController - private val uiEventLogger = UiEventLoggerFake() + @Mock private lateinit var uiEventLogger: QsEventLogger + private val falsingManager = FalsingManagerFake() private lateinit var testableLooper: TestableLooper private lateinit var tile: FlashlightTile @@ -56,11 +57,11 @@ class FlashlightTileTest : SysuiTestCase() { testableLooper = TestableLooper.get(this) Mockito.`when`(qsHost.context).thenReturn(mockContext) - Mockito.`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) tile = FlashlightTile( qsHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), falsingManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt index eeebd4fb7792..1d6f225dd0a3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt @@ -23,7 +23,6 @@ import android.testing.TestableLooper import android.view.View import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.animation.DialogLaunchAnimator import com.android.systemui.classifier.FalsingManagerFake @@ -31,7 +30,8 @@ import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.statusbar.StatusBarStateController -import com.android.systemui.qs.QSTileHost +import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq @@ -52,13 +52,13 @@ import org.mockito.MockitoAnnotations @TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest class FontScalingTileTest : SysuiTestCase() { - @Mock private lateinit var qsHost: QSTileHost + @Mock private lateinit var qsHost: QSHost @Mock private lateinit var metricsLogger: MetricsLogger @Mock private lateinit var statusBarStateController: StatusBarStateController @Mock private lateinit var activityStarter: ActivityStarter @Mock private lateinit var qsLogger: QSLogger @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator - @Mock private lateinit var uiEventLogger: UiEventLogger + @Mock private lateinit var uiEventLogger: QsEventLogger private lateinit var testableLooper: TestableLooper private lateinit var fontScalingTile: FontScalingTile @@ -70,11 +70,11 @@ class FontScalingTileTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) testableLooper = TestableLooper.get(this) `when`(qsHost.getContext()).thenReturn(mContext) - `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) fontScalingTile = FontScalingTile( qsHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java index 959e750ac5f4..73f61d0690e2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java @@ -38,6 +38,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.DataSaverController; @@ -66,6 +67,8 @@ public class HotspotTileTest extends SysuiTestCase { private HotspotController mHotspotController; @Mock private DataSaverController mDataSaverController; + @Mock + private QsEventLogger mUiEventLogger; private TestableLooper mTestableLooper; private HotspotTile mTile; @@ -80,6 +83,7 @@ public class HotspotTileTest extends SysuiTestCase { mTile = new HotspotTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java index adfd7f71e8f8..7957c6a7cfb6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileTest.java @@ -35,6 +35,7 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; @@ -63,6 +64,8 @@ public class InternetTileTest extends SysuiTestCase { private AccessPointController mAccessPointController; @Mock private InternetDialogFactory mInternetDialogFactory; + @Mock + private QsEventLogger mUiEventLogger; private TestableLooper mTestableLooper; private InternetTile mTile; @@ -76,6 +79,7 @@ public class InternetTileTest extends SysuiTestCase { mTile = new InternetTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt index 3642e874e7ae..0bf0b38f7471 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt @@ -22,7 +22,6 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingManagerFake @@ -30,6 +29,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor import com.android.systemui.qs.tileimpl.QSTileImpl @@ -43,8 +43,8 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito.`when` import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) @@ -71,8 +71,9 @@ class LocationTileTest : SysuiTestCase() { private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var panelInteractor: PanelInteractor + @Mock + private lateinit var uiEventLogger: QsEventLogger - private val uiEventLogger = UiEventLoggerFake() private lateinit var testableLooper: TestableLooper private lateinit var tile: LocationTile @@ -80,10 +81,11 @@ class LocationTileTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) testableLooper = TestableLooper.get(this) - `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) `when`(qsHost.context).thenReturn(mockContext) - tile = LocationTile(qsHost, + tile = LocationTile( + qsHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), falsingManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt index e2f64b2cc226..ceff546106f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt @@ -21,8 +21,6 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.UiEventLogger -import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingManagerFake @@ -30,6 +28,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController @@ -67,19 +66,22 @@ class MicrophoneToggleTileTest : SysuiTestCase() { private lateinit var privacyController: IndividualSensorPrivacyController @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock + private lateinit var uiEventLogger: QsEventLogger private lateinit var testableLooper: TestableLooper private lateinit var tile: MicrophoneToggleTile - private val uiEventLogger: UiEventLogger = UiEventLoggerFake() + @Before fun setUp() { MockitoAnnotations.initMocks(this) testableLooper = TestableLooper.get(this) whenever(host.context).thenReturn(mContext) - whenever(host.uiEventLogger).thenReturn(uiEventLogger) - tile = MicrophoneToggleTile(host, + tile = MicrophoneToggleTile( + host, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), metricsLogger, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java index c7dae83e2056..763a7e5e4e06 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java @@ -37,6 +37,7 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import org.junit.After; @@ -70,6 +71,8 @@ public class NfcTileTest extends SysuiTestCase { private QSLogger mQSLogger; @Mock private BroadcastDispatcher mBroadcastDispatcher; + @Mock + private QsEventLogger mUiEventLogger; private TestableLooper mTestableLooper; private NfcTile mNfcTile; @@ -84,6 +87,7 @@ public class NfcTileTest extends SysuiTestCase { mNfcTile = new NfcTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt index 04af69c84cf8..6c8f76b48f03 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt @@ -23,8 +23,6 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.UiEventLogger -import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingManagerFake @@ -33,6 +31,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.LocationController @@ -43,8 +42,8 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.anyInt -import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations +import org.mockito.Mockito.`when` as whenever @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) @@ -68,17 +67,18 @@ class NightDisplayTileTest : SysuiTestCase() { @Mock private lateinit var mNightDisplayListener: NightDisplayListener + @Mock private lateinit var mUiEventLogger: QsEventLogger + private lateinit var mTestableLooper: TestableLooper private lateinit var mTile: NightDisplayTile - private val mUiEventLogger: UiEventLogger = UiEventLoggerFake() + @Before fun setUp() { MockitoAnnotations.initMocks(this) mTestableLooper = TestableLooper.get(this) whenever(mHost.context).thenReturn(mContext) - whenever(mHost.uiEventLogger).thenReturn(mUiEventLogger) whenever(mHost.userContext).thenReturn(mContext) whenever(mNightDisplayListenerBuilder.setUser(anyInt())) .thenReturn(mNightDisplayListenerBuilder) @@ -87,6 +87,7 @@ class NightDisplayTileTest : SysuiTestCase() { mTile = NightDisplayTile( mHost, + mUiEventLogger, mTestableLooper.looper, Handler(mTestableLooper.looper), FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java index 652c138f6478..c391153fecc1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java @@ -33,6 +33,7 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.settings.UserTracker; import com.android.systemui.util.settings.SecureSettings; @@ -65,6 +66,8 @@ public class OneHandedModeTileTest extends SysuiTestCase { private UserTracker mUserTracker; @Mock private SecureSettings mSecureSettings; + @Mock + private QsEventLogger mUiEventLogger; private TestableLooper mTestableLooper; private OneHandedModeTile mTile; @@ -78,6 +81,7 @@ public class OneHandedModeTileTest extends SysuiTestCase { mTile = spy(new OneHandedModeTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java index 3125d455acfb..6f2d904dda64 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java @@ -30,8 +30,6 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.UiEventLogger; -import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; @@ -40,6 +38,7 @@ import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -64,7 +63,8 @@ public class QRCodeScannerTileTest extends SysuiTestCase { private ActivityStarter mActivityStarter; @Mock private QSLogger mQSLogger; - private UiEventLogger mUiEventLogger = new UiEventLoggerFake(); + @Mock + private QsEventLogger mUiEventLogger; @Mock private QRCodeScannerController mController; @@ -79,6 +79,7 @@ public class QRCodeScannerTileTest extends SysuiTestCase { mTile = new QRCodeScannerTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java index 596df7856ee1..b089e380304d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java @@ -58,8 +58,6 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; -import com.android.internal.logging.UiEventLogger; -import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; @@ -67,6 +65,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -109,7 +108,8 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { private ActivityStarter mActivityStarter; @Mock private QSLogger mQSLogger; - private UiEventLogger mUiEventLogger = new UiEventLoggerFake(); + @Mock + private QsEventLogger mUiEventLogger; @Mock private QuickAccessWalletClient mQuickAccessWalletClient; @Mock @@ -136,7 +136,6 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { doNothing().when(mSpiedContext).startActivity(any(Intent.class)); when(mHost.getContext()).thenReturn(mSpiedContext); - when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger); when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(LABEL); when(mQuickAccessWalletClient.getTileIcon()).thenReturn(mTileIcon); when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true); @@ -146,6 +145,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { mTile = new QuickAccessWalletTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java index 7913628c5693..d2445944c182 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java @@ -39,6 +39,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.ReduceBrightColorsController; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -69,6 +70,8 @@ public class ReduceBrightColorsTileTest extends SysuiTestCase { private UserTracker mUserTracker; @Mock private ReduceBrightColorsController mReduceBrightColorsController; + @Mock + private QsEventLogger mUiEventLogger; private TestableLooper mTestableLooper; private ReduceBrightColorsTile mTile; @@ -85,6 +88,7 @@ public class ReduceBrightColorsTileTest extends SysuiTestCase { true, mReduceBrightColorsController, mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java index 5b94cfedaedf..e106741499ab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java @@ -39,6 +39,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.BatteryController; @@ -87,6 +88,8 @@ public class RotationLockTileTest extends SysuiTestCase { DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingController; @Mock RotationPolicyWrapper mRotationPolicyWrapper; + @Mock + QsEventLogger mUiEventLogger; private RotationLockController mController; private TestableLooper mTestableLooper; @@ -105,6 +108,7 @@ public class RotationLockTileTest extends SysuiTestCase { mLockTile = new RotationLockTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java index d9ed1a299f51..fff2b8f5f8cd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java @@ -44,6 +44,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor; import com.android.systemui.qs.tileimpl.QSTileImpl; @@ -86,6 +87,8 @@ public class ScreenRecordTileTest extends SysuiTestCase { private DialogLaunchAnimator mDialogLaunchAnimator; @Mock private PanelInteractor mPanelInteractor; + @Mock + private QsEventLogger mUiEventLogger; private TestableLooper mTestableLooper; private ScreenRecordTile mTile; @@ -100,6 +103,7 @@ public class ScreenRecordTileTest extends SysuiTestCase { mTile = new ScreenRecordTile( mHost, + mUiEventLogger, mTestableLooper.getLooper(), new Handler(mTestableLooper.getLooper()), new FalsingManagerFake(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt index b55657163382..79147e7e66b4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt @@ -25,7 +25,6 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingManagerFake @@ -33,6 +32,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost +import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.statusbar.policy.BatteryController @@ -63,8 +63,8 @@ class UiModeNightTileTest : SysuiTestCase() { @Mock private lateinit var configurationController: ConfigurationController @Mock private lateinit var batteryController: BatteryController @Mock private lateinit var locationController: LocationController + @Mock private lateinit var uiEventLogger: QsEventLogger - private val uiEventLogger = UiEventLoggerFake() private val falsingManager = FalsingManagerFake() private lateinit var testableLooper: TestableLooper private lateinit var tile: UiModeNightTile @@ -81,11 +81,11 @@ class UiModeNightTileTest : SysuiTestCase() { `when`(qsHost.userContext).thenReturn(mContext) `when`(mockContext.resources).thenReturn(resources) `when`(resources.configuration).thenReturn(configuration) - `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) tile = UiModeNightTile( qsHost, + uiEventLogger, testableLooper.looper, Handler(testableLooper.looper), falsingManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index 7d022192f935..9186c35e2b47 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -100,7 +100,6 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { mNotificationTestHelper.setDefaultInflationFlags(FLAG_CONTENT_VIEW_ALL); FakeFeatureFlags fakeFeatureFlags = new FakeFeatureFlags(); - fakeFeatureFlags.set(Flags.NOTIFICATION_ANIMATE_BIG_PICTURE, true); fakeFeatureFlags.set(Flags.SENSITIVE_REVEAL_ANIM, false); mNotificationTestHelper.setFeatureFlags(fakeFeatureFlags); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt index ddb7f4d88d30..01bec879102d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt @@ -32,9 +32,8 @@ import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnec import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest @@ -69,14 +68,8 @@ class MobileIconsViewModelTest : SysuiTestCase() { FakeConnectivityRepository(), ) - val subscriptionIdsFlow = - interactor.filteredSubscriptions - .map { subs -> subs.map { it.subscriptionId } } - .stateIn(testScope.backgroundScope, SharingStarted.WhileSubscribed(), listOf()) - underTest = MobileIconsViewModel( - subscriptionIdsFlow, logger, verboseLogger, interactor, @@ -90,6 +83,32 @@ class MobileIconsViewModelTest : SysuiTestCase() { } @Test + fun subscriptionIdsFlow_matchesInteractor() = + testScope.runTest { + var latest: List<Int>? = null + val job = underTest.subscriptionIdsFlow.onEach { latest = it }.launchIn(this) + + interactor.filteredSubscriptions.value = + listOf( + SubscriptionModel(subscriptionId = 1, isOpportunistic = false), + ) + assertThat(latest).isEqualTo(listOf(1)) + + interactor.filteredSubscriptions.value = + listOf( + SubscriptionModel(subscriptionId = 2, isOpportunistic = false), + SubscriptionModel(subscriptionId = 5, isOpportunistic = true), + SubscriptionModel(subscriptionId = 7, isOpportunistic = true), + ) + assertThat(latest).isEqualTo(listOf(2, 5, 7)) + + interactor.filteredSubscriptions.value = emptyList() + assertThat(latest).isEmpty() + + job.cancel() + } + + @Test fun `caching - mobile icon view model is reused for same sub id`() = testScope.runTest { val model1 = underTest.viewModelForSub(1, StatusBarLocation.HOME) diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java new file mode 100644 index 000000000000..9cf3e443320d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/CsdWarningDialogTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2023 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.volume; + +import static android.media.AudioManager.CSD_WARNING_DOSE_REACHED_1X; +import static android.media.AudioManager.CSD_WARNING_DOSE_REPEATED_5X; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.app.Notification; +import android.app.NotificationManager; +import android.media.AudioManager; +import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import com.android.internal.messages.nano.SystemMessageProto; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class CsdWarningDialogTest extends SysuiTestCase { + + private NotificationManager mNotificationManager; + private AudioManager mAudioManager; + + @Before + public void setup() { + mNotificationManager = mock(NotificationManager.class); + getContext().addMockSystemService(NotificationManager.class, mNotificationManager); + + mAudioManager = mock(AudioManager.class); + getContext().addMockSystemService(AudioManager.class, mAudioManager); + } + + @Test + public void create1XCsdDialogAndWait_sendsNotification() { + FakeExecutor executor = new FakeExecutor(new FakeSystemClock()); + // instantiate directly instead of via factory; we don't want executor to be @Background + CsdWarningDialog dialog = new CsdWarningDialog(CSD_WARNING_DOSE_REACHED_1X, mContext, + mAudioManager, mNotificationManager, executor, null); + + dialog.show(); + executor.advanceClockToLast(); + executor.runAllReady(); + dialog.dismiss(); + + verify(mNotificationManager).notify( + eq(SystemMessageProto.SystemMessage.NOTE_CSD_LOWER_AUDIO), any(Notification.class)); + } + + @Test + public void create5XCsdDiSalogAndWait_willNotSendNotification() { + FakeExecutor executor = new FakeExecutor(new FakeSystemClock()); + CsdWarningDialog dialog = new CsdWarningDialog(CSD_WARNING_DOSE_REPEATED_5X, mContext, + mAudioManager, mNotificationManager, executor, null); + + dialog.show(); + executor.advanceClockToLast(); + executor.runAllReady(); + dialog.dismiss(); + + verify(mNotificationManager, never()).notify( + eq(SystemMessageProto.SystemMessage.NOTE_CSD_LOWER_AUDIO), any(Notification.class)); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index d419095921b8..eb2688894cb0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -102,6 +102,15 @@ public class VolumeDialogImplTest extends SysuiTestCase { InteractionJankMonitor mInteractionJankMonitor; @Mock private DumpManager mDumpManager; + @Mock CsdWarningDialog mCsdWarningDialog; + + private final CsdWarningDialog.Factory mCsdWarningDialogFactory = + new CsdWarningDialog.Factory() { + @Override + public CsdWarningDialog create(int warningType, Runnable onCleanup) { + return mCsdWarningDialog; + } + }; @Before public void setup() throws Exception { @@ -124,6 +133,7 @@ public class VolumeDialogImplTest extends SysuiTestCase { mInteractionJankMonitor, mDeviceConfigProxy, mExecutor, + mCsdWarningDialogFactory, mDumpManager ); mDialog.init(0, null); @@ -352,6 +362,14 @@ public class VolumeDialogImplTest extends SysuiTestCase { mDialog.getDialogView().animate().cancel(); } + @Test + public void showCsdWarning_dialogShown() { + mDialog.showCsdWarningH(AudioManager.CSD_WARNING_DOSE_REACHED_1X, + CsdWarningDialog.NO_ACTION_TIMEOUT_MS); + + verify(mCsdWarningDialog).show(); + } + /* @Test public void testContentDescriptions() { diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk index cbca3f03fb0f..a41d0e57cd21 100644 --- a/packages/overlays/Android.mk +++ b/packages/overlays/Android.mk @@ -32,6 +32,7 @@ LOCAL_REQUIRED_MODULES := \ NavigationBarModeGesturalOverlayWideBack \ NavigationBarModeGesturalOverlayExtraWideBack \ TransparentNavigationBarOverlay \ + NotesRoleEnabledOverlay \ preinstalled-packages-platform-overlays.xml include $(BUILD_PHONY_PACKAGE) diff --git a/core/tests/expresslog/Android.bp b/packages/overlays/NotesRoleEnabledOverlay/Android.bp index cab49a76a734..68ebd9652399 100644 --- a/core/tests/expresslog/Android.bp +++ b/packages/overlays/NotesRoleEnabledOverlay/Android.bp @@ -1,16 +1,18 @@ -// Copyright (C) 2023 The Android Open Source Project +// +// Copyright 2023, 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 +// 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 { // See: http://go/android-license-faq @@ -21,27 +23,8 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -android_test { - name: "ExpressLogTests", - - srcs: [ - "src/**/*.java", - ], - - static_libs: [ - "androidx.test.rules", - "modules-utils-build", - ], - - libs: [ - "android.test.base", - "android.test.runner", - ], - - platform_apis: true, - test_suites: [ - "general-tests", - ], - - certificate: "platform", +runtime_resource_overlay { + name: "NotesRoleEnabledOverlay", + theme: "NotesRoleEnabled", + product_specific: true, } diff --git a/packages/overlays/NotesRoleEnabledOverlay/AndroidManifest.xml b/packages/overlays/NotesRoleEnabledOverlay/AndroidManifest.xml new file mode 100644 index 000000000000..c01178d1727d --- /dev/null +++ b/packages/overlays/NotesRoleEnabledOverlay/AndroidManifest.xml @@ -0,0 +1,26 @@ +<!-- +/** + * Copyright (c) 2023, 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="com.android.role.notes.enabled" + android:versionCode="1" + android:versionName="1.0"> + <overlay android:targetPackage="android" + android:priority="1"/> + + <application android:label="@string/notes_role_enabled_overlay_title" android:hasCode="false"/> +</manifest>
\ No newline at end of file diff --git a/packages/overlays/NotesRoleEnabledOverlay/res/values/config.xml b/packages/overlays/NotesRoleEnabledOverlay/res/values/config.xml new file mode 100644 index 000000000000..f27f5f42ae6b --- /dev/null +++ b/packages/overlays/NotesRoleEnabledOverlay/res/values/config.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright (c) 2023, 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. + */ +--> +<resources> + <!-- Whether the default notes role should be enabled. In builds without + device-specific overlays, this can be controlled in developer options. --> + <bool name="config_enableDefaultNotes">true</bool> + + <!-- Whether the default notes role for work profile should be enabled. + In builds without device-specific overlays, this can be controlled in + developer options. --> + <bool name="config_enableDefaultNotesForWorkProfile">true</bool> +</resources> diff --git a/core/java/com/android/internal/expresslog/Utils.java b/packages/overlays/NotesRoleEnabledOverlay/res/values/strings.xml index d82192f51662..3edbb571c4d1 100644 --- a/core/java/com/android/internal/expresslog/Utils.java +++ b/packages/overlays/NotesRoleEnabledOverlay/res/values/strings.xml @@ -1,11 +1,13 @@ -/* - * Copyright (C) 2023 The Android Open Source Project +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright (c) 2019, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -13,9 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.internal.expresslog; - -final class Utils { - static native long hashString(String stringToHash); -} +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Name of overlay [CHAR LIMIT=64] --> + <string name="notes_role_enabled_overlay_title" translatable="false">Notes Role enabled</string> +</resources>
\ No newline at end of file diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto index 47027342974d..21d09792f1c7 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -402,5 +402,7 @@ message SystemMessage { // Package: android NOTE_ALL_MANAGED_SUBSCRIPTIONS_AND_MANAGED_PROFILE_OFF = 1006; + // Notify the user that audio was lowered based on Calculated Sound Dose (CSD) + NOTE_CSD_LOWER_AUDIO = 1007; } } diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java index 3ecf93328219..8fc30e43d1a0 100644 --- a/services/core/java/com/android/server/BinaryTransparencyService.java +++ b/services/core/java/com/android/server/BinaryTransparencyService.java @@ -80,7 +80,7 @@ import android.util.apk.ApkSignatureVerifier; import android.util.apk.ApkSigningBlockUtils; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.expresslog.Histogram; +import com.android.modules.expresslog.Histogram; import com.android.internal.os.IBinaryTransparencyService; import com.android.internal.util.FrameworkStatsLog; import com.android.server.pm.ApexManager; diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index 92889c05d9f4..d256aead97e8 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -426,7 +426,7 @@ public class PackageWatchdog { } int impact = registeredObserver.onHealthCheckFailed( versionedPackage, failureReason, mitigationCount); - if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE + if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0 && impact < currentObserverImpact) { currentObserverToNotify = registeredObserver; currentObserverImpact = impact; @@ -466,7 +466,7 @@ public class PackageWatchdog { if (registeredObserver != null) { int impact = registeredObserver.onHealthCheckFailed( failingPackage, failureReason, 1); - if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE + if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0 && impact < currentObserverImpact) { currentObserverToNotify = registeredObserver; currentObserverImpact = impact; @@ -494,7 +494,7 @@ public class PackageWatchdog { PackageHealthObserver registeredObserver = observer.registeredObserver; if (registeredObserver != null) { int impact = registeredObserver.onBootLoop(mitigationCount); - if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE + if (impact != PackageHealthObserverImpact.USER_IMPACT_LEVEL_0 && impact < currentObserverImpact) { currentObserverToNotify = registeredObserver; currentObserverImpact = impact; @@ -576,19 +576,23 @@ public class PackageWatchdog { /** Possible severity values of the user impact of a {@link PackageHealthObserver#execute}. */ @Retention(SOURCE) - @IntDef(value = {PackageHealthObserverImpact.USER_IMPACT_NONE, - PackageHealthObserverImpact.USER_IMPACT_LOW, - PackageHealthObserverImpact.USER_IMPACT_MEDIUM, - PackageHealthObserverImpact.USER_IMPACT_HIGH}) + @IntDef(value = {PackageHealthObserverImpact.USER_IMPACT_LEVEL_0, + PackageHealthObserverImpact.USER_IMPACT_LEVEL_10, + PackageHealthObserverImpact.USER_IMPACT_LEVEL_30, + PackageHealthObserverImpact.USER_IMPACT_LEVEL_50, + PackageHealthObserverImpact.USER_IMPACT_LEVEL_70, + PackageHealthObserverImpact.USER_IMPACT_LEVEL_100}) public @interface PackageHealthObserverImpact { /** No action to take. */ - int USER_IMPACT_NONE = 0; + int USER_IMPACT_LEVEL_0 = 0; /* Action has low user impact, user of a device will barely notice. */ - int USER_IMPACT_LOW = 1; - /* Action has medium user impact, user of a device will likely notice. */ - int USER_IMPACT_MEDIUM = 3; + int USER_IMPACT_LEVEL_10 = 10; + /* Actions having medium user impact, user of a device will likely notice. */ + int USER_IMPACT_LEVEL_30 = 30; + int USER_IMPACT_LEVEL_50 = 50; + int USER_IMPACT_LEVEL_70 = 70; /* Action has high user impact, a last resort, user of a device will be very frustrated. */ - int USER_IMPACT_HIGH = 5; + int USER_IMPACT_LEVEL_100 = 100; } /** Register instances of this interface to receive notifications on package failure. */ @@ -633,7 +637,7 @@ public class PackageWatchdog { * boot loop (including this time). */ default @PackageHealthObserverImpact int onBootLoop(int mitigationCount) { - return PackageHealthObserverImpact.USER_IMPACT_NONE; + return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; } /** diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java index 3de65f94decf..46d019b241b7 100644 --- a/services/core/java/com/android/server/RescueParty.java +++ b/services/core/java/com/android/server/RescueParty.java @@ -489,13 +489,14 @@ public class RescueParty { switch(rescueLevel) { case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS: case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES: - return PackageHealthObserverImpact.USER_IMPACT_LOW; + return PackageHealthObserverImpact.USER_IMPACT_LEVEL_10; case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS: case LEVEL_WARM_REBOOT: + return PackageHealthObserverImpact.USER_IMPACT_LEVEL_50; case LEVEL_FACTORY_RESET: - return PackageHealthObserverImpact.USER_IMPACT_HIGH; + return PackageHealthObserverImpact.USER_IMPACT_LEVEL_100; default: - return PackageHealthObserverImpact.USER_IMPACT_NONE; + return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; } } @@ -633,7 +634,7 @@ public class RescueParty { return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, mayPerformReboot(failedPackage))); } else { - return PackageHealthObserverImpact.USER_IMPACT_NONE; + return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; } } @@ -677,7 +678,7 @@ public class RescueParty { @Override public int onBootLoop(int mitigationCount) { if (isDisabled()) { - return PackageHealthObserverImpact.USER_IMPACT_NONE; + return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; } return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, true)); } diff --git a/services/core/java/com/android/server/am/DropboxRateLimiter.java b/services/core/java/com/android/server/am/DropboxRateLimiter.java index 9ff2cd0649d4..727d4df96c47 100644 --- a/services/core/java/com/android/server/am/DropboxRateLimiter.java +++ b/services/core/java/com/android/server/am/DropboxRateLimiter.java @@ -22,7 +22,7 @@ import android.util.ArrayMap; import android.util.Slog; import com.android.internal.annotations.GuardedBy; -import com.android.internal.expresslog.Counter; +import com.android.modules.expresslog.Counter; /** Rate limiter for adding errors into dropbox. */ public class DropboxRateLimiter { diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java index 70a696c72a9d..ca41f429a0de 100644 --- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java +++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java @@ -51,7 +51,7 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.CompositeRWLock; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.expresslog.Counter; +import com.android.modules.expresslog.Counter; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.TimeoutRecord; import com.android.internal.os.anr.AnrLatencyTracker; diff --git a/services/core/java/com/android/server/notification/GroupHelper.java b/services/core/java/com/android/server/notification/GroupHelper.java index 273afcc9f769..dff02bf711cd 100644 --- a/services/core/java/com/android/server/notification/GroupHelper.java +++ b/services/core/java/com/android/server/notification/GroupHelper.java @@ -15,44 +15,53 @@ */ package com.android.server.notification; +import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY; +import static android.app.Notification.FLAG_AUTO_CANCEL; +import static android.app.Notification.FLAG_GROUP_SUMMARY; +import static android.app.Notification.FLAG_LOCAL_ONLY; +import static android.app.Notification.FLAG_NO_CLEAR; +import static android.app.Notification.FLAG_ONGOING_EVENT; + +import android.annotation.NonNull; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Log; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; /** * NotificationManagerService helper for auto-grouping notifications. */ public class GroupHelper { private static final String TAG = "GroupHelper"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); protected static final String AUTOGROUP_KEY = "ranker_group"; + // Flags that all autogroup summaries have + protected static final int BASE_FLAGS = + FLAG_AUTOGROUP_SUMMARY | FLAG_GROUP_SUMMARY | FLAG_LOCAL_ONLY; + // Flag that autogroup summaries inherits if all children have the flag + private static final int ALL_CHILDREN_FLAG = FLAG_AUTO_CANCEL; + // Flags that autogroup summaries inherits if any child has them + private static final int ANY_CHILDREN_FLAGS = FLAG_ONGOING_EVENT | FLAG_NO_CLEAR; + private final Callback mCallback; private final int mAutoGroupAtCount; - // count the number of ongoing notifications per group - // userId|packageName -> (set of ongoing notifications that aren't in an app group) - final ArrayMap<String, ArraySet<String>> - mOngoingGroupCount = new ArrayMap<>(); - - // Map of user : <Map of package : notification keys>. Only contains notifications that are not - // grouped by the app (aka no group or sort key). - Map<Integer, Map<String, LinkedHashSet<String>>> mUngroupedNotifications = new HashMap<>(); + // Only contains notifications that are not explicitly grouped by the app (aka no group or + // sort key). + // userId|packageName -> (keys of notifications that aren't in an explicit app group -> flags) + @GuardedBy("mUngroupedNotifications") + private final ArrayMap<String, ArrayMap<String, Integer>> mUngroupedNotifications + = new ArrayMap<>(); public GroupHelper(int autoGroupAtCount, Callback callback) { mAutoGroupAtCount = autoGroupAtCount; - mCallback = callback; + mCallback = callback; } private String generatePackageKey(int userId, String pkg) { @@ -60,69 +69,30 @@ public class GroupHelper { } @VisibleForTesting - protected int getOngoingGroupCount(int userId, String pkg) { - String key = generatePackageKey(userId, pkg); - return mOngoingGroupCount.getOrDefault(key, new ArraySet<>(0)).size(); - } - - private void updateOngoingGroupCount(StatusBarNotification sbn, boolean add) { - if (sbn.getNotification().isGroupSummary()) { - return; - } - String key = generatePackageKey(sbn.getUserId(), sbn.getPackageName()); - ArraySet<String> notifications = mOngoingGroupCount.getOrDefault(key, new ArraySet<>(0)); - if (add) { - notifications.add(sbn.getKey()); - mOngoingGroupCount.put(key, notifications); - } else { - notifications.remove(sbn.getKey()); - // we don't need to put it back if it is default + @GuardedBy("mUngroupedNotifications") + protected int getAutogroupSummaryFlags(@NonNull final ArrayMap<String, Integer> children) { + boolean allChildrenHasFlag = children.size() > 0; + int anyChildFlagSet = 0; + for (int i = 0; i < children.size(); i++) { + if (!hasAnyFlag(children.valueAt(i), ALL_CHILDREN_FLAG)) { + allChildrenHasFlag = false; + } + if (hasAnyFlag(children.valueAt(i), ANY_CHILDREN_FLAGS)) { + anyChildFlagSet |= (children.valueAt(i) & ANY_CHILDREN_FLAGS); + } } - - boolean needsOngoingFlag = notifications.size() > 0; - mCallback.updateAutogroupSummary(sbn.getUserId(), sbn.getPackageName(), needsOngoingFlag); + return BASE_FLAGS | (allChildrenHasFlag ? ALL_CHILDREN_FLAG : 0) | anyChildFlagSet; } - public void onNotificationUpdated(StatusBarNotification childSbn) { - updateOngoingGroupCount(childSbn, childSbn.isOngoing() && !childSbn.isAppGroup()); + private boolean hasAnyFlag(int flags, int mask) { + return (flags & mask) != 0; } public void onNotificationPosted(StatusBarNotification sbn, boolean autogroupSummaryExists) { try { - updateOngoingGroupCount(sbn, sbn.isOngoing() && !sbn.isAppGroup()); - - List<String> notificationsToGroup = new ArrayList<>(); if (!sbn.isAppGroup()) { - // Not grouped by the app, add to the list of notifications for the app; - // send grouping update if app exceeds the autogrouping limit. - synchronized (mUngroupedNotifications) { - Map<String, LinkedHashSet<String>> ungroupedNotificationsByUser - = mUngroupedNotifications.get(sbn.getUserId()); - if (ungroupedNotificationsByUser == null) { - ungroupedNotificationsByUser = new HashMap<>(); - } - mUngroupedNotifications.put(sbn.getUserId(), ungroupedNotificationsByUser); - LinkedHashSet<String> notificationsForPackage - = ungroupedNotificationsByUser.get(sbn.getPackageName()); - if (notificationsForPackage == null) { - notificationsForPackage = new LinkedHashSet<>(); - } - - notificationsForPackage.add(sbn.getKey()); - ungroupedNotificationsByUser.put(sbn.getPackageName(), notificationsForPackage); - - if (notificationsForPackage.size() >= mAutoGroupAtCount - || autogroupSummaryExists) { - notificationsToGroup.addAll(notificationsForPackage); - } - } - if (notificationsToGroup.size() > 0) { - adjustAutogroupingSummary(sbn.getUserId(), sbn.getPackageName(), - notificationsToGroup.get(0), true); - adjustNotificationBundling(notificationsToGroup, true); - } + maybeGroup(sbn, autogroupSummaryExists); } else { - // Grouped, but not by us. Send updates to un-autogroup, if we grouped it. maybeUngroup(sbn, false, sbn.getUserId()); } @@ -133,7 +103,6 @@ public class GroupHelper { public void onNotificationRemoved(StatusBarNotification sbn) { try { - updateOngoingGroupCount(sbn, false); maybeUngroup(sbn, true, sbn.getUserId()); } catch (Exception e) { Slog.e(TAG, "Error processing canceled notification", e); @@ -141,70 +110,114 @@ public class GroupHelper { } /** - * Un-autogroups notifications that are now grouped by the app. + * A non-app grouped notification has been added or updated + * Evaluate if: + * (a) an existing autogroup summary needs updated flags + * (b) a new autogroup summary needs to be added with correct flags + * (c) other non-app grouped children need to be moved to the autogroup + * + * And stores the list of upgrouped notifications & their flags + */ + private void maybeGroup(StatusBarNotification sbn, boolean autogroupSummaryExists) { + int flags = 0; + List<String> notificationsToGroup = new ArrayList<>(); + synchronized (mUngroupedNotifications) { + String key = generatePackageKey(sbn.getUserId(), sbn.getPackageName()); + final ArrayMap<String, Integer> children = + mUngroupedNotifications.getOrDefault(key, new ArrayMap<>()); + + children.put(sbn.getKey(), sbn.getNotification().flags); + mUngroupedNotifications.put(key, children); + + if (children.size() >= mAutoGroupAtCount || autogroupSummaryExists) { + flags = getAutogroupSummaryFlags(children); + notificationsToGroup.addAll(children.keySet()); + } + } + if (notificationsToGroup.size() > 0) { + if (autogroupSummaryExists) { + mCallback.updateAutogroupSummary(sbn.getUserId(), sbn.getPackageName(), flags); + } else { + mCallback.addAutoGroupSummary( + sbn.getUserId(), sbn.getPackageName(), sbn.getKey(), flags); + } + for (String key : notificationsToGroup) { + mCallback.addAutoGroup(key); + } + } + } + + /** + * A notification was added that's app grouped, or a notification was removed. + * Evaluate whether: + * (a) an existing autogroup summary needs updated flags + * (b) if we need to remove our autogroup overlay for this notification + * (c) we need to remove the autogroup summary + * + * And updates the internal state of un-app-grouped notifications and their flags */ private void maybeUngroup(StatusBarNotification sbn, boolean notificationGone, int userId) { - List<String> notificationsToUnAutogroup = new ArrayList<>(); boolean removeSummary = false; + int summaryFlags = 0; + boolean updateSummaryFlags = false; + boolean removeAutogroupOverlay = false; synchronized (mUngroupedNotifications) { - Map<String, LinkedHashSet<String>> ungroupedNotificationsByUser - = mUngroupedNotifications.get(sbn.getUserId()); - if (ungroupedNotificationsByUser == null || ungroupedNotificationsByUser.size() == 0) { - return; - } - LinkedHashSet<String> notificationsForPackage - = ungroupedNotificationsByUser.get(sbn.getPackageName()); - if (notificationsForPackage == null || notificationsForPackage.size() == 0) { + String key = generatePackageKey(sbn.getUserId(), sbn.getPackageName()); + final ArrayMap<String, Integer> children = + mUngroupedNotifications.getOrDefault(key, new ArrayMap<>()); + if (children.size() == 0) { return; } - if (notificationsForPackage.remove(sbn.getKey())) { - if (!notificationGone) { - // Add the current notification to the ungrouping list if it still exists. - notificationsToUnAutogroup.add(sbn.getKey()); + + // if this notif was autogrouped and now isn't + if (children.containsKey(sbn.getKey())) { + // if this notification was contributing flags that aren't covered by other + // children to the summary, reevaluate flags for the summary + int flags = children.remove(sbn.getKey()); + // this + if (hasAnyFlag(flags, ANY_CHILDREN_FLAGS)) { + updateSummaryFlags = true; + summaryFlags = getAutogroupSummaryFlags(children); + } + // if this notification still exists and has an autogroup overlay, but is now + // grouped by the app, clear the overlay + if (!notificationGone && sbn.getOverrideGroupKey() != null) { + removeAutogroupOverlay = true; + } + + // If there are no more children left to autogroup, remove the summary + if (children.size() == 0) { + removeSummary = true; } - } - // If the status change of this notification has brought the number of loose - // notifications to zero, remove the summary and un-autogroup. - if (notificationsForPackage.size() == 0) { - ungroupedNotificationsByUser.remove(sbn.getPackageName()); - removeSummary = true; } } if (removeSummary) { - adjustAutogroupingSummary(userId, sbn.getPackageName(), null, false); - } - if (notificationsToUnAutogroup.size() > 0) { - adjustNotificationBundling(notificationsToUnAutogroup, false); - } - } - - private void adjustAutogroupingSummary(int userId, String packageName, String triggeringKey, - boolean summaryNeeded) { - if (summaryNeeded) { - mCallback.addAutoGroupSummary(userId, packageName, triggeringKey, - getOngoingGroupCount(userId, packageName) > 0); + mCallback.removeAutoGroupSummary(userId, sbn.getPackageName()); } else { - mCallback.removeAutoGroupSummary(userId, packageName); + if (updateSummaryFlags) { + mCallback.updateAutogroupSummary(userId, sbn.getPackageName(), summaryFlags); + } + } + if (removeAutogroupOverlay) { + mCallback.removeAutoGroup(sbn.getKey()); } } - private void adjustNotificationBundling(List<String> keys, boolean group) { - for (String key : keys) { - if (DEBUG) Log.i(TAG, "Sending grouping adjustment for: " + key + " group? " + group); - if (group) { - mCallback.addAutoGroup(key); - } else { - mCallback.removeAutoGroup(key); - } + @VisibleForTesting + int getNotGroupedByAppCount(int userId, String pkg) { + synchronized (mUngroupedNotifications) { + String key = generatePackageKey(userId, pkg); + final ArrayMap<String, Integer> children = + mUngroupedNotifications.getOrDefault(key, new ArrayMap<>()); + return children.size(); } } protected interface Callback { void addAutoGroup(String key); void removeAutoGroup(String key); - void addAutoGroupSummary(int userId, String pkg, String triggeringKey, - boolean needsOngoingFlag); + void addAutoGroupSummary(int userId, String pkg, String triggeringKey, int flags); void removeAutoGroupSummary(int user, String pkg); - void updateAutogroupSummary(int userId, String pkg, boolean needsOngoingFlag); + void updateAutogroupSummary(int userId, String pkg, int flags); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 5d81dda5f5eb..1301cd476c26 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -319,6 +319,7 @@ import com.android.server.pm.PackageManagerService; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.permission.PermissionManagerServiceInternal; import com.android.server.policy.PermissionPolicyInternal; +import com.android.server.powerstats.StatsPullAtomCallbackImpl; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.utils.Slogf; @@ -902,11 +903,11 @@ public class NotificationManagerService extends SystemService { * has the same flag. It will delete the flag otherwise * @param userId user id of the autogroup summary * @param pkg package of the autogroup summary - * @param needsOngoingFlag true if the group has at least one ongoing notification + * @param flags the new flags for this summary * @param isAppForeground true if the app is currently in the foreground. */ @GuardedBy("mNotificationLock") - protected void updateAutobundledSummaryFlags(int userId, String pkg, boolean needsOngoingFlag, + protected void updateAutobundledSummaryFlags(int userId, String pkg, int flags, boolean isAppForeground) { ArrayMap<String, String> summaries = mAutobundledSummaries.get(userId); if (summaries == null) { @@ -921,13 +922,8 @@ public class NotificationManagerService extends SystemService { return; } int oldFlags = summary.getSbn().getNotification().flags; - if (needsOngoingFlag) { - summary.getSbn().getNotification().flags |= FLAG_ONGOING_EVENT; - } else { - summary.getSbn().getNotification().flags &= ~FLAG_ONGOING_EVENT; - } - - if (summary.getSbn().getNotification().flags != oldFlags) { + if (oldFlags != flags) { + summary.getSbn().getNotification().flags = flags; mHandler.post(new EnqueueNotificationRunnable(userId, summary, isAppForeground, SystemClock.elapsedRealtime())); } @@ -2684,9 +2680,14 @@ public class NotificationManagerService extends SystemService { @Override public void addAutoGroupSummary(int userId, String pkg, String triggeringKey, - boolean needsOngoingFlag) { - NotificationManagerService.this.addAutoGroupSummary( - userId, pkg, triggeringKey, needsOngoingFlag); + int flags) { + NotificationRecord r = createAutoGroupSummary(userId, pkg, triggeringKey, flags); + if (r != null) { + final boolean isAppForeground = + mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND; + mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground, + SystemClock.elapsedRealtime())); + } } @Override @@ -2697,11 +2698,11 @@ public class NotificationManagerService extends SystemService { } @Override - public void updateAutogroupSummary(int userId, String pkg, boolean needsOngoingFlag) { + public void updateAutogroupSummary(int userId, String pkg, int flags) { boolean isAppForeground = pkg != null && mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND; synchronized (mNotificationLock) { - updateAutobundledSummaryFlags(userId, pkg, needsOngoingFlag, isAppForeground); + updateAutobundledSummaryFlags(userId, pkg, flags, isAppForeground); } } }); @@ -5961,19 +5962,6 @@ public class NotificationManagerService extends SystemService { r.addAdjustment(adjustment); } - @VisibleForTesting - void addAutoGroupSummary(int userId, String pkg, String triggeringKey, - boolean needsOngoingFlag) { - NotificationRecord r = createAutoGroupSummary( - userId, pkg, triggeringKey, needsOngoingFlag); - if (r != null) { - final boolean isAppForeground = - mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND; - mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground, - SystemClock.elapsedRealtime())); - } - } - // Clears the 'fake' auto-group summary. @VisibleForTesting @GuardedBy("mNotificationLock") @@ -5997,7 +5985,7 @@ public class NotificationManagerService extends SystemService { // Creates a 'fake' summary for a package that has exceeded the solo-notification limit. NotificationRecord createAutoGroupSummary(int userId, String pkg, String triggeringKey, - boolean needsOngoingFlag) { + int flagsToSet) { NotificationRecord summaryRecord = null; boolean isPermissionFixed = mPermissionHelper.isPermissionFixed(pkg, userId); synchronized (mNotificationLock) { @@ -6007,7 +5995,6 @@ public class NotificationManagerService extends SystemService { // adjustment will post a summary if needed. return null; } - NotificationChannel channel = notificationRecord.getChannel(); final StatusBarNotification adjustedSbn = notificationRecord.getSbn(); userId = adjustedSbn.getUser().getIdentifier(); int uid = adjustedSbn.getUid(); @@ -6030,11 +6017,8 @@ public class NotificationManagerService extends SystemService { .setGroupSummary(true) .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN) .setGroup(GroupHelper.AUTOGROUP_KEY) - .setFlag(FLAG_AUTOGROUP_SUMMARY, true) - .setFlag(Notification.FLAG_GROUP_SUMMARY, true) - .setFlag(FLAG_ONGOING_EVENT, needsOngoingFlag) + .setFlag(flagsToSet, true) .setColor(adjustedSbn.getNotification().color) - .setLocalOnly(true) .build(); summaryNotification.extras.putAll(extras); Intent appIntent = getContext().getPackageManager().getLaunchIntentForPackage(pkg); @@ -6372,6 +6356,7 @@ public class NotificationManagerService extends SystemService { * The private API only accessible to the system process. */ private final NotificationManagerInternal mInternalService = new NotificationManagerInternal() { + @Override public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId) { @@ -7827,18 +7812,17 @@ public class NotificationManagerService extends SystemService { if (notification.getSmallIcon() != null) { StatusBarNotification oldSbn = (old != null) ? old.getSbn() : null; mListeners.notifyPostedLocked(r, old); - if ((oldSbn == null || !Objects.equals(oldSbn.getGroup(), n.getGroup())) - && !isCritical(r)) { - mHandler.post(() -> { - synchronized (mNotificationLock) { - mGroupHelper.onNotificationPosted( - n, hasAutoGroupSummaryLocked(n)); - } - }); - } else if (oldSbn != null) { - final NotificationRecord finalRecord = r; - mHandler.post(() -> - mGroupHelper.onNotificationUpdated(finalRecord.getSbn())); + if (oldSbn == null + || !Objects.equals(oldSbn.getGroup(), n.getGroup()) + || oldSbn.getNotification().flags != n.getNotification().flags) { + if (!isCritical(r)) { + mHandler.post(() -> { + synchronized (mNotificationLock) { + mGroupHelper.onNotificationPosted( + n, hasAutoGroupSummaryLocked(n)); + } + }); + } } } else { Slog.e(TAG, "Not posting notification without small icon: " + notification); diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 596e9b964643..69ef3f780172 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -994,7 +994,7 @@ final class InstallPackageHelper { reconciledPackages = ReconcilePackageUtils.reconcilePackages( requests, Collections.unmodifiableMap(mPm.mPackages), versionInfos, mSharedLibraries, mPm.mSettings.getKeySetManagerService(), - mPm.mSettings); + mPm.mSettings, mContext); } catch (ReconcileFailure e) { for (InstallRequest request : requests) { request.setError("Reconciliation failed...", e); @@ -3930,7 +3930,7 @@ final class InstallPackageHelper { mPm.mPackages, Collections.singletonMap(pkgName, mPm.getSettingsVersionForPackage(parsedPackage)), mSharedLibraries, mPm.mSettings.getKeySetManagerService(), - mPm.mSettings); + mPm.mSettings, mContext); if ((scanFlags & SCAN_AS_APEX) == 0) { appIdCreated = optimisticallyRegisterAppId(installRequest); } else { diff --git a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java index 5312ae6ca84c..e3c97e933ad1 100644 --- a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java +++ b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java @@ -16,6 +16,7 @@ package com.android.server.pm; +import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; import static android.content.pm.SigningDetails.CapabilityMergeRule.MERGE_RESTRICTED_CAPABILITY; @@ -23,19 +24,24 @@ import static android.content.pm.SigningDetails.CapabilityMergeRule.MERGE_RESTRI import static com.android.server.pm.PackageManagerService.SCAN_BOOTING; import static com.android.server.pm.PackageManagerService.SCAN_DONT_KILL_APP; +import android.content.Context; import android.content.pm.PackageManager; +import android.content.pm.PermissionInfo; import android.content.pm.SharedLibraryInfo; import android.content.pm.SigningDetails; import android.os.SystemProperties; +import android.permission.PermissionManager; import android.util.ArrayMap; import android.util.Log; import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.pm.pkg.AndroidPackage; +import com.android.server.pm.pkg.component.ParsedUsesPermission; import com.android.server.pm.pkg.parsing.ParsingPackageUtils; import com.android.server.utils.WatchedLongSparseArray; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -54,7 +60,7 @@ final class ReconcilePackageUtils { Map<String, AndroidPackage> allPackages, Map<String, Settings.VersionInfo> versionInfos, SharedLibrariesImpl sharedLibraries, - KeySetManagerService ksms, Settings settings) + KeySetManagerService ksms, Settings settings, Context context) throws ReconcileFailure { final List<ReconciledPackage> result = new ArrayList<>(installRequests.size()); @@ -143,11 +149,11 @@ final class ReconcilePackageUtils { } else { if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) { throw new ReconcileFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, - "Package " + parsedPackage.getPackageName() + "Package " + installPackageName + " upgrade keys do not match the previously installed" + " version"); } else { - String msg = "System package " + parsedPackage.getPackageName() + String msg = "System package " + installPackageName + " signature changed; retaining data."; PackageManagerService.reportSettingsProblem(Log.WARN, msg); } @@ -168,11 +174,42 @@ final class ReconcilePackageUtils { removeAppKeySetData = true; } - // if this is is a sharedUser, check to see if the new package is signed by a - // newer - // signing certificate than the existing one, and if so, copy over the new + // if this is a sharedUser, check to see if the new package is signed by a + // newer signing certificate than the existing one, and if so, copy over the new // details if (sharedUserSetting != null) { + if (!parsedPackage.isTestOnly() && sharedUserSetting.isPrivileged() + && !signatureCheckPs.isSystem()) { + final List<ParsedUsesPermission> usesPermissions = + parsedPackage.getUsesPermissions(); + final List<String> usesPrivilegedPermissions = new ArrayList<>(); + final PermissionManager permissionManager = context.getSystemService( + PermissionManager.class); + // Check if the app requests any privileged permissions because that + // violates the privapp-permissions allowlist check during boot. + if (permissionManager != null) { + for (int i = 0; i < usesPermissions.size(); i++) { + final String permissionName = usesPermissions.get(i).getName(); + final PermissionInfo permissionInfo = + permissionManager.getPermissionInfo(permissionName, 0); + if (permissionInfo != null + && (permissionInfo.getProtectionFlags() + & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) { + usesPrivilegedPermissions.add(permissionName); + } + } + } + + if (!usesPrivilegedPermissions.isEmpty()) { + throw new ReconcileFailure(INSTALL_FAILED_INVALID_APK, + "Non-system package: " + installPackageName + + " shares signature and sharedUserId with" + + " a privileged package but requests" + + " privileged permissions that are not" + + " allowed: " + Arrays.toString( + usesPrivilegedPermissions.toArray())); + } + } // Attempt to merge the existing lineage for the shared SigningDetails with // the lineage of the new package; if the shared SigningDetails are not // returned this indicates the new package added new signers to the lineage @@ -189,7 +226,7 @@ final class ReconcilePackageUtils { for (AndroidPackage androidPackage : sharedUserSetting.getPackages()) { if (androidPackage.getPackageName() != null && !androidPackage.getPackageName().equals( - parsedPackage.getPackageName())) { + installPackageName)) { mergedDetails = mergedDetails.mergeLineageWith( androidPackage.getSigningDetails(), MERGE_RESTRICTED_CAPABILITY); @@ -219,7 +256,7 @@ final class ReconcilePackageUtils { if (sharedUserSetting != null) { if (sharedUserSetting.signaturesChanged != null && !PackageManagerServiceUtils.canJoinSharedUserId( - parsedPackage.getPackageName(), parsedPackage.getSigningDetails(), + installPackageName, parsedPackage.getSigningDetails(), sharedUserSetting, PackageManagerServiceUtils.SHARED_USER_ID_JOIN_TYPE_SYSTEM)) { if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 29) { @@ -240,7 +277,7 @@ final class ReconcilePackageUtils { // whichever package happened to be scanned later. throw new IllegalStateException( "Signature mismatch on system package " - + parsedPackage.getPackageName() + + installPackageName + " for shared user " + sharedUserSetting); } @@ -252,7 +289,7 @@ final class ReconcilePackageUtils { sharedUserSetting.signaturesChanged = Boolean.TRUE; } // File a report about this. - String msg = "System package " + parsedPackage.getPackageName() + String msg = "System package " + installPackageName + " signature changed; retaining data."; PackageManagerService.reportSettingsProblem(Log.WARN, msg); } catch (IllegalArgumentException e) { diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index e5e32f0a9690..4d2b119d7800 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -206,8 +206,6 @@ final class DefaultPermissionGrantPolicy { static { SENSORS_PERMISSIONS.add(Manifest.permission.BODY_SENSORS); SENSORS_PERMISSIONS.add(Manifest.permission.BODY_SENSORS_BACKGROUND); - SENSORS_PERMISSIONS.add(Manifest.permission.BODY_SENSORS_WRIST_TEMPERATURE); - SENSORS_PERMISSIONS.add(Manifest.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND); } private static final Set<String> STORAGE_PERMISSIONS = new ArraySet<>(); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index c5f939a2a66e..297ad73e054b 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1332,9 +1332,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Bg location is one-off runtime modifier permission and has no app op if (sPlatformPermissions.containsKey(permission) && !Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission) - && !Manifest.permission.BODY_SENSORS_BACKGROUND.equals(permission) - && !Manifest.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND - .equals(permission)) { + && !Manifest.permission.BODY_SENSORS_BACKGROUND.equals(permission)) { Slog.wtf(LOG_TAG, "Platform runtime permission " + permission + " with no app op defined!"); } diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 7beb1edfe51f..e437be8e01b5 100644 --- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java @@ -105,36 +105,46 @@ final class RollbackPackageHealthObserver implements PackageHealthObserver { @Override public int onHealthCheckFailed(@Nullable VersionedPackage failedPackage, @FailureReasons int failureReason, int mitigationCount) { - // For native crashes, we will roll back any available rollbacks + boolean anyRollbackAvailable = !mContext.getSystemService(RollbackManager.class) + .getAvailableRollbacks().isEmpty(); + int impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; + if (failureReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH - && !mContext.getSystemService(RollbackManager.class) - .getAvailableRollbacks().isEmpty()) { - return PackageHealthObserverImpact.USER_IMPACT_MEDIUM; - } - if (getAvailableRollback(failedPackage) == null) { - // Don't handle the notification, no rollbacks available for the package - return PackageHealthObserverImpact.USER_IMPACT_NONE; - } else { + && anyRollbackAvailable) { + // For native crashes, we will directly roll back any available rollbacks + // Note: For non-native crashes the rollback-all step has higher impact + impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30; + } else if (mitigationCount == 1 && getAvailableRollback(failedPackage) != null) { // Rollback is available, we may get a callback into #execute - return PackageHealthObserverImpact.USER_IMPACT_MEDIUM; + impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30; + } else if (mitigationCount > 1 && anyRollbackAvailable) { + // If any rollbacks are available, we will commit them + impact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_70; } + + return impact; } @Override public boolean execute(@Nullable VersionedPackage failedPackage, @FailureReasons int rollbackReason, int mitigationCount) { if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) { - mHandler.post(() -> rollbackAll()); + mHandler.post(() -> rollbackAll(rollbackReason)); return true; } - RollbackInfo rollback = getAvailableRollback(failedPackage); - if (rollback == null) { - Slog.w(TAG, "Expected rollback but no valid rollback found for " + failedPackage); - return false; + if (mitigationCount == 1) { + RollbackInfo rollback = getAvailableRollback(failedPackage); + if (rollback == null) { + Slog.w(TAG, "Expected rollback but no valid rollback found for " + failedPackage); + return false; + } + mHandler.post(() -> rollbackPackage(rollback, failedPackage, rollbackReason)); + } else if (mitigationCount > 1) { + mHandler.post(() -> rollbackAll(rollbackReason)); } - mHandler.post(() -> rollbackPackage(rollback, failedPackage, rollbackReason)); - // Assume rollback executed successfully + + // Assume rollbacks executed successfully return true; } @@ -468,7 +478,7 @@ final class RollbackPackageHealthObserver implements PackageHealthObserver { } @WorkerThread - private void rollbackAll() { + private void rollbackAll(@FailureReasons int rollbackReason) { assertInWorkerThread(); RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class); List<RollbackInfo> rollbacks = rollbackManager.getAvailableRollbacks(); @@ -487,7 +497,7 @@ final class RollbackPackageHealthObserver implements PackageHealthObserver { for (RollbackInfo rollback : rollbacks) { VersionedPackage sample = rollback.getPackages().get(0).getVersionRolledBackFrom(); - rollbackPackage(rollback, sample, PackageWatchdog.FAILURE_REASON_NATIVE_CRASH); + rollbackPackage(rollback, sample, rollbackReason); } } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java index f111a9541303..926c7e400144 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java @@ -27,6 +27,7 @@ import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PAREN import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.BroadcastOptions; import android.app.admin.DevicePolicyIdentifiers; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyState; @@ -353,6 +354,7 @@ final class DevicePolicyEngine { policyDefinition, userId); } + sendDevicePolicyChangedToSystem(userId); } /** @@ -478,6 +480,8 @@ final class DevicePolicyEngine { enforcingAdmin, policyDefinition, UserHandle.USER_ALL); + + sendDevicePolicyChangedToSystem(UserHandle.USER_ALL); } /** @@ -699,7 +703,7 @@ final class DevicePolicyEngine { if (policyDefinition.isGlobalOnlyPolicy()) { throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a global only" - + "policy."); + + " policy."); } if (!mLocalPolicies.contains(userId)) { @@ -724,7 +728,7 @@ final class DevicePolicyEngine { private <V> PolicyState<V> getGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) { if (policyDefinition.isLocalOnlyPolicy()) { throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a local only" - + "policy."); + + " policy."); } if (!mGlobalPolicies.containsKey(policyDefinition.getPolicyKey())) { @@ -761,6 +765,20 @@ final class DevicePolicyEngine { policyValue == null ? null : policyValue.getValue(), mContext, userId); } + private void sendDevicePolicyChangedToSystem(int userId) { + Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); + intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + Bundle options = new BroadcastOptions() + .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) + .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE) + .toBundle(); + Binder.withCleanCallingIdentity(() -> mContext.sendBroadcastAsUser( + intent, + new UserHandle(userId), + /* receiverPermissions= */ null, + options)); + } + private <V> void sendPolicyResultToAdmin( EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int result, int userId) { Intent intent = new Intent(PolicyUpdateReceiver.ACTION_DEVICE_POLICY_SET_RESULT); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 94e6e732dd76..93fbb845f534 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -441,7 +441,6 @@ import android.util.AtomicFile; import android.util.DebugUtils; import android.util.IndentingPrintWriter; import android.util.IntArray; -import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -13131,19 +13130,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } int userId = caller.getUserId(); - if (!UserRestrictionsUtils.isValidRestriction(key)) { - return; - } checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_USER_RESTRICTION); if (isPolicyEngineForFinanceFlagEnabled()) { - int affectedUserId = parent ? getProfileParentId(userId) : userId; - EnforcingAdmin admin = enforcePermissionForUserRestriction( - who, - key, - caller.getPackageName(), - affectedUserId); - if (mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, callerPackage, userId)) { + if (!isDeviceOwner(caller) && !isProfileOwner(caller)) { + if (!mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, callerPackage, userId)) { + throw new IllegalStateException("Calling package is not targeting Android U."); + } + if (!UserRestrictionsUtils.isValidRestriction(key)) { + throw new IllegalArgumentException("Invalid restriction key: " + key); + } + int affectedUserId = parent ? getProfileParentId(userId) : userId; + EnforcingAdmin admin = enforcePermissionForUserRestriction( + who, + key, + caller.getPackageName(), + affectedUserId); PolicyDefinition<Boolean> policyDefinition = PolicyDefinition.getPolicyDefinitionForUserRestriction(key); if (enabledFromThisOwner) { @@ -13155,7 +13157,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { setGlobalUserRestrictionInternal(admin, key, /* enabled= */ false); } if (!policyDefinition.isGlobalOnlyPolicy()) { - setLocalUserRestrictionInternal(admin, key, /* enabled= */ false, userId); + setLocalUserRestrictionInternal(admin, key, /* enabled= */ false, + userId); int parentUserId = getProfileParentId(userId); if (parentUserId != userId) { @@ -13165,49 +13168,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } else { + if (!UserRestrictionsUtils.isValidRestriction(key)) { + return; + } + Objects.requireNonNull(who, "ComponentName is null"); + EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackage); + checkAdminCanSetRestriction(caller, parent, key); setBackwardCompatibleUserRestriction( caller, admin, key, enabledFromThisOwner, parent); } } else { - Objects.requireNonNull(who, "ComponentName is null"); - if (parent) { - Preconditions.checkCallAuthorization( - isProfileOwnerOfOrganizationOwnedDevice(caller)); - } else { - Preconditions.checkCallAuthorization( - isDeviceOwner(caller) || isProfileOwner(caller)); - } - synchronized (getLockObject()) { - if (isDefaultDeviceOwner(caller)) { - if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) { - throw new SecurityException("Device owner cannot set user restriction " - + key); - } - Preconditions.checkArgument(!parent, - "Cannot use the parent instance in Device Owner mode"); - } else if (isFinancedDeviceOwner(caller)) { - if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(key)) { - throw new SecurityException("Cannot set user restriction " + key - + " when managing a financed device"); - } - Preconditions.checkArgument(!parent, - "Cannot use the parent instance in Financed Device Owner" - + " mode"); - } else { - boolean profileOwnerCanChangeOnItself = !parent - && UserRestrictionsUtils.canProfileOwnerChange( - key, userId == getMainUserId()); - boolean orgOwnedProfileOwnerCanChangeGlobally = parent - && isProfileOwnerOfOrganizationOwnedDevice(caller) - && UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange( - key); - - if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangeGlobally) { - throw new SecurityException("Profile owner cannot set user restriction " - + key); - } - } + if (!UserRestrictionsUtils.isValidRestriction(key)) { + return; } + Objects.requireNonNull(who, "ComponentName is null"); + checkAdminCanSetRestriction(caller, parent, key); synchronized (getLockObject()) { final ActiveAdmin activeAdmin = getParentOfAdminIfRequired( getProfileOwnerOrDeviceOwnerLocked(userId), parent); @@ -13224,6 +13199,46 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { logUserRestrictionCall(key, enabledFromThisOwner, parent, caller); } + private void checkAdminCanSetRestriction(CallerIdentity caller, boolean parent, String key) { + if (parent) { + Preconditions.checkCallAuthorization( + isProfileOwnerOfOrganizationOwnedDevice(caller)); + } else { + Preconditions.checkCallAuthorization( + isDeviceOwner(caller) || isProfileOwner(caller)); + } + synchronized (getLockObject()) { + if (isDefaultDeviceOwner(caller)) { + if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) { + throw new SecurityException("Device owner cannot set user restriction " + + key); + } + Preconditions.checkArgument(!parent, + "Cannot use the parent instance in Device Owner mode"); + } else if (isFinancedDeviceOwner(caller)) { + if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(key)) { + throw new SecurityException("Cannot set user restriction " + key + + " when managing a financed device"); + } + Preconditions.checkArgument(!parent, + "Cannot use the parent instance in Financed Device Owner" + + " mode"); + } else { + boolean profileOwnerCanChangeOnItself = !parent + && UserRestrictionsUtils.canProfileOwnerChange( + key, caller.getUserId() == getMainUserId()); + boolean orgOwnedProfileOwnerCanChangeGlobally = parent + && isProfileOwnerOfOrganizationOwnedDevice(caller) + && UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange( + key); + + if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangeGlobally) { + throw new SecurityException("Profile owner cannot set user restriction " + + key); + } + } + } + } private void setBackwardCompatibleUserRestriction( CallerIdentity caller, EnforcingAdmin admin, String key, boolean enabled, boolean parent) { @@ -13252,20 +13267,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public void setUserRestrictionGlobally(String callerPackage, String key) { final CallerIdentity caller = getCallerIdentity(callerPackage); - if (!UserRestrictionsUtils.isValidRestriction(key)) { - return; - } checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_USER_RESTRICTION); if (!isPolicyEngineForFinanceFlagEnabled()) { throw new IllegalStateException("Feature flag is not enabled."); } - + if (isDeviceOwner(caller) || isProfileOwner(caller)) { + throw new IllegalStateException("Admins are not allowed to call this API."); + } if (!mInjector.isChangeEnabled( ENABLE_COEXISTENCE_CHANGE, callerPackage, caller.getUserId())) { throw new IllegalStateException("Calling package is not targeting Android U."); } + if (!UserRestrictionsUtils.isValidRestriction(key)) { + throw new IllegalArgumentException("Invalid restriction key: " + key); + } EnforcingAdmin admin = enforcePermissionForUserRestriction( /* who= */ null, @@ -13416,14 +13433,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int targetUserId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId(); EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackage); - Bundle restrictions = getUserRestrictionsFromPolicyEngine(admin, targetUserId); - // Add global restrictions set by the admin as well if admin is not targeting Android U. - if (!mInjector.isChangeEnabled( - ENABLE_COEXISTENCE_CHANGE, callerPackage, caller.getUserId())) { + if (isDeviceOwner(caller) || isProfileOwner(caller)) { + Objects.requireNonNull(who, "ComponentName is null"); + Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) + || isFinancedDeviceOwner(caller) + || isProfileOwner(caller) + || (parent && isProfileOwnerOfOrganizationOwnedDevice(caller))); + + Bundle restrictions = getUserRestrictionsFromPolicyEngine(admin, targetUserId); + // Add global restrictions set by the admin as well. restrictions.putAll( getUserRestrictionsFromPolicyEngine(admin, UserHandle.USER_ALL)); + return restrictions; + } else { + if (!mInjector.isChangeEnabled( + ENABLE_COEXISTENCE_CHANGE, callerPackage, caller.getUserId())) { + throw new IllegalStateException("Calling package is not targeting Android U."); + } + return getUserRestrictionsFromPolicyEngine(admin, targetUserId); } - return restrictions; } else { Objects.requireNonNull(who, "ComponentName is null"); Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) @@ -16626,10 +16654,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { SENSOR_PERMISSIONS.add(Manifest.permission.BACKGROUND_CAMERA); SENSOR_PERMISSIONS.add(Manifest.permission.RECORD_BACKGROUND_AUDIO); SENSOR_PERMISSIONS.add(Manifest.permission.BODY_SENSORS_BACKGROUND); - SENSOR_PERMISSIONS.add( - Manifest.permission.BODY_SENSORS_WRIST_TEMPERATURE); - SENSOR_PERMISSIONS.add( - Manifest.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND); } private boolean canGrantPermission(CallerIdentity caller, String permission, diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java index 509a66b4f8f7..8c2468af1146 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java @@ -284,6 +284,7 @@ final class PolicyDefinition<V> { private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>(); private static Map<String, Integer> USER_RESTRICTION_FLAGS = new HashMap<>(); + // TODO(b/277218360): Revisit policies that should be marked as global-only. static { POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY, AUTO_TIMEZONE); POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMISSION_GRANT_POLICY, @@ -312,8 +313,9 @@ final class PolicyDefinition<V> { USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_WIFI_TETHERING, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_GRANT_ADMIN, /* flags= */ 0); + // TODO: set as global only once we get rid of the mapping USER_RESTRICTION_FLAGS.put( - UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, POLICY_FLAG_GLOBAL_ONLY_POLICY); + UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, /* flags= */ 0); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_WIFI_DIRECT, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put( @@ -333,8 +335,10 @@ final class PolicyDefinition<V> { USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_BLUETOOTH, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BLUETOOTH, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BLUETOOTH_SHARING, /* flags= */ 0); + // This effectively always applies globally, but it can be set on the profile + // parent, check the javadocs on the restriction for more info. USER_RESTRICTION_FLAGS.put( - UserManager.DISALLOW_USB_FILE_TRANSFER, POLICY_FLAG_GLOBAL_ONLY_POLICY); + UserManager.DISALLOW_USB_FILE_TRANSFER, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_CREDENTIALS, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_REMOVE_USER, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, /* flags= */ 0); @@ -344,8 +348,10 @@ final class PolicyDefinition<V> { USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CONFIG_DATE_TIME, /* flags= */ 0); USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_CONFIG_TETHERING, /* flags= */ 0); + // This effectively always applies globally, but it can be set on the profile + // parent, check the javadocs on the restriction for more info. USER_RESTRICTION_FLAGS.put( - UserManager.DISALLOW_NETWORK_RESET, POLICY_FLAG_GLOBAL_ONLY_POLICY); + UserManager.DISALLOW_NETWORK_RESET, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_FACTORY_RESET, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_USER, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_ADD_MANAGED_PROFILE, /* flags= */ 0); @@ -376,8 +382,7 @@ final class PolicyDefinition<V> { USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNMUTE_DEVICE, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_DATA_ROAMING, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_SET_USER_ICON, /* flags= */ 0); - // TODO: double check flags - USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OEM_UNLOCK, POLICY_FLAG_GLOBAL_ONLY_POLICY); + USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_OEM_UNLOCK, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_UNIFIED_PASSWORD, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.ALLOW_PARENT_PROFILE_APP_LINKING, /* flags= */ 0); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_AUTOFILL, /* flags= */ 0); @@ -390,6 +395,7 @@ final class PolicyDefinition<V> { USER_RESTRICTION_FLAGS.put( UserManager.DISALLOW_CONFIG_PRIVATE_DNS, POLICY_FLAG_GLOBAL_ONLY_POLICY); USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MICROPHONE_TOGGLE, /* flags= */ 0); + // TODO: According the UserRestrictionsUtils, this is global only, need to confirm. USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_CAMERA_TOGGLE, /* flags= */ 0); // TODO: check if its global only USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_BIOMETRIC, /* flags= */ 0); diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java index 1a7517098d18..7b771aff0055 100644 --- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java @@ -567,36 +567,36 @@ public class RescuePartyTest { // Ensure that no action is taken for cases where the failure reason is unknown assertEquals(observer.onHealthCheckFailed(null, PackageWatchdog.FAILURE_REASON_UNKNOWN, 1), - PackageHealthObserverImpact.USER_IMPACT_NONE); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_0); // Ensure the correct user impact is returned for each mitigation count. assertEquals(observer.onHealthCheckFailed(null, PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 1), - PackageHealthObserverImpact.USER_IMPACT_LOW); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_10); assertEquals(observer.onHealthCheckFailed(null, PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 2), - PackageHealthObserverImpact.USER_IMPACT_LOW); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_10); assertEquals(observer.onHealthCheckFailed(null, PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 3), - PackageHealthObserverImpact.USER_IMPACT_HIGH); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_50); assertEquals(observer.onHealthCheckFailed(null, PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4), - PackageHealthObserverImpact.USER_IMPACT_HIGH); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_50); } @Test public void testBootLoopLevels() { RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); - assertEquals(observer.onBootLoop(0), PackageHealthObserverImpact.USER_IMPACT_NONE); - assertEquals(observer.onBootLoop(1), PackageHealthObserverImpact.USER_IMPACT_LOW); - assertEquals(observer.onBootLoop(2), PackageHealthObserverImpact.USER_IMPACT_LOW); - assertEquals(observer.onBootLoop(3), PackageHealthObserverImpact.USER_IMPACT_HIGH); - assertEquals(observer.onBootLoop(4), PackageHealthObserverImpact.USER_IMPACT_HIGH); - assertEquals(observer.onBootLoop(5), PackageHealthObserverImpact.USER_IMPACT_HIGH); + assertEquals(observer.onBootLoop(0), PackageHealthObserverImpact.USER_IMPACT_LEVEL_0); + assertEquals(observer.onBootLoop(1), PackageHealthObserverImpact.USER_IMPACT_LEVEL_10); + assertEquals(observer.onBootLoop(2), PackageHealthObserverImpact.USER_IMPACT_LEVEL_10); + assertEquals(observer.onBootLoop(3), PackageHealthObserverImpact.USER_IMPACT_LEVEL_50); + assertEquals(observer.onBootLoop(4), PackageHealthObserverImpact.USER_IMPACT_LEVEL_50); + assertEquals(observer.onBootLoop(5), PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); } @Test diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java index 0be678af12dc..541b07782b29 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/rollback/RollbackPackageHealthObserverTest.java @@ -16,31 +16,65 @@ package com.android.server.rollback; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; + import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; import android.content.pm.VersionedPackage; +import android.content.rollback.PackageRollbackInfo; +import android.content.rollback.RollbackInfo; +import android.content.rollback.RollbackManager; import android.util.Log; import android.util.Xml; import androidx.test.runner.AndroidJUnit4; +import com.android.dx.mockito.inline.extended.ExtendedMockito; +import com.android.server.PackageWatchdog; import com.android.server.SystemConfig; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoSession; +import org.mockito.quality.Strictness; +import org.mockito.stubbing.Answer; import org.xmlpull.v1.XmlPullParser; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.List; import java.util.Scanner; + @RunWith(AndroidJUnit4.class) public class RollbackPackageHealthObserverTest { + @Mock + private Context mMockContext; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private PackageWatchdog mMockPackageWatchdog; + @Mock + RollbackManager mRollbackManager; + @Mock + RollbackInfo mRollbackInfo; + @Mock + PackageRollbackInfo mPackageRollbackInfo; + + private MockitoSession mSession; + private static final String APP_A = "com.package.a"; + private static final long VERSION_CODE = 1L; private static final String LOG_TAG = "RollbackPackageHealthObserverTest"; private SystemConfig mSysConfig; @@ -50,17 +84,74 @@ public class RollbackPackageHealthObserverTest { @Before public void setup() { mSysConfig = new SystemConfigTestClass(); + + mSession = ExtendedMockito.mockitoSession() + .initMocks(this) + .strictness(Strictness.LENIENT) + .spyStatic(PackageWatchdog.class) + .startMocking(); + + // Mock PackageWatchdog + doAnswer((Answer<PackageWatchdog>) invocationOnMock -> mMockPackageWatchdog) + .when(() -> PackageWatchdog.getInstance(mMockContext)); + + } + + @After + public void tearDown() throws Exception { + mSession.finishMocking(); } /** - * Subclass of SystemConfig without running the constructor. - */ + * Subclass of SystemConfig without running the constructor. + */ private class SystemConfigTestClass extends SystemConfig { SystemConfigTestClass() { - super(false); + super(false); } } + @Test + public void testHealthCheckLevels() { + RollbackPackageHealthObserver observer = + spy(new RollbackPackageHealthObserver(mMockContext)); + VersionedPackage testFailedPackage = new VersionedPackage(APP_A, VERSION_CODE); + + + when(mMockContext.getSystemService(RollbackManager.class)).thenReturn(mRollbackManager); + + // Crashes with no rollbacks available + assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0, + observer.onHealthCheckFailed(null, + PackageWatchdog.FAILURE_REASON_NATIVE_CRASH, 1)); + assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0, + observer.onHealthCheckFailed(null, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1)); + + // Make the rollbacks available + when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of(mRollbackInfo)); + when(mRollbackInfo.getPackages()).thenReturn(List.of(mPackageRollbackInfo)); + when(mPackageRollbackInfo.getVersionRolledBackFrom()).thenReturn(testFailedPackage); + + // native crash + assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_30, + observer.onHealthCheckFailed(null, + PackageWatchdog.FAILURE_REASON_NATIVE_CRASH, 1)); + // non-native crash + assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_30, + observer.onHealthCheckFailed(testFailedPackage, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 1)); + // Second non-native crash again + assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_70, + observer.onHealthCheckFailed(testFailedPackage, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 2)); + // Subsequent crashes when rollbacks have completed + when(mRollbackManager.getAvailableRollbacks()).thenReturn(List.of()); + assertEquals(PackageWatchdog.PackageHealthObserverImpact.USER_IMPACT_LEVEL_0, + observer.onHealthCheckFailed(testFailedPackage, + PackageWatchdog.FAILURE_REASON_APP_CRASH, 3)); + } + /** * Test that isAutomaticRollbackDenied works correctly when packages that are not * denied are sent. @@ -77,7 +168,7 @@ public class RollbackPackageHealthObserverTest { readPermissions(folder, /* Grant all permission flags */ ~0); assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig, - new VersionedPackage("com.test.package", 1))).isEqualTo(false); + new VersionedPackage("com.test.package", 1))).isEqualTo(false); } /** @@ -96,7 +187,7 @@ public class RollbackPackageHealthObserverTest { readPermissions(folder, /* Grant all permission flags */ ~0); assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig, - new VersionedPackage("com.android.vending", 1))).isEqualTo(true); + new VersionedPackage("com.android.vending", 1))).isEqualTo(true); } /** @@ -109,7 +200,7 @@ public class RollbackPackageHealthObserverTest { readPermissions(folder, /* Grant all permission flags */ ~0); assertThat(RollbackPackageHealthObserver.isAutomaticRollbackDenied(mSysConfig, - new VersionedPackage("com.android.vending", 1))).isEqualTo(false); + new VersionedPackage("com.android.vending", 1))).isEqualTo(false); } /** diff --git a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java index ff6c9769b69f..516fb4aa40c6 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/GroupHelperTest.java @@ -15,23 +15,31 @@ */ package com.android.server.notification; -import static com.android.server.notification.GroupHelper.AUTOGROUP_KEY; +import static android.app.Notification.FLAG_AUTO_CANCEL; +import static android.app.Notification.FLAG_BUBBLE; +import static android.app.Notification.FLAG_CAN_COLORIZE; +import static android.app.Notification.FLAG_FOREGROUND_SERVICE; +import static android.app.Notification.FLAG_NO_CLEAR; +import static android.app.Notification.FLAG_ONGOING_EVENT; + +import static com.android.server.notification.GroupHelper.BASE_FLAGS; import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import android.annotation.SuppressLint; import android.app.Notification; import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.test.suitebuilder.annotation.SmallTest; +import android.util.ArrayMap; import androidx.test.runner.AndroidJUnit4; @@ -45,11 +53,10 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; @SmallTest +@SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the class. @RunWith(AndroidJUnit4.class) public class GroupHelperTest extends UiServiceTestCase { private @Mock GroupHelper.Callback mCallback; @@ -82,21 +89,104 @@ public class GroupHelperTest extends UiServiceTestCase { } @Test - public void testNoGroup_postingUnderLimit() throws Exception { + public void testGetAutogroupSummaryFlags_noChildren() { + ArrayMap<String, Integer> children = new ArrayMap<>(); + + assertEquals(BASE_FLAGS, mGroupHelper.getAutogroupSummaryFlags(children)); + } + + @Test + public void testGetAutogroupSummaryFlags_oneOngoing() { + ArrayMap<String, Integer> children = new ArrayMap<>(); + children.put("a", 0); + children.put("b", FLAG_ONGOING_EVENT); + children.put("c", FLAG_BUBBLE); + + assertEquals(FLAG_ONGOING_EVENT | BASE_FLAGS, + mGroupHelper.getAutogroupSummaryFlags(children)); + } + + @Test + public void testGetAutogroupSummaryFlags_oneOngoingNoClear() { + ArrayMap<String, Integer> children = new ArrayMap<>(); + children.put("a", 0); + children.put("b", FLAG_ONGOING_EVENT|FLAG_NO_CLEAR); + children.put("c", FLAG_BUBBLE); + + assertEquals(FLAG_NO_CLEAR | FLAG_ONGOING_EVENT | BASE_FLAGS, + mGroupHelper.getAutogroupSummaryFlags(children)); + } + + @Test + public void testGetAutogroupSummaryFlags_oneOngoingBubble() { + ArrayMap<String, Integer> children = new ArrayMap<>(); + children.put("a", 0); + children.put("b", FLAG_ONGOING_EVENT | FLAG_BUBBLE); + children.put("c", FLAG_BUBBLE); + + assertEquals(FLAG_ONGOING_EVENT | BASE_FLAGS, + mGroupHelper.getAutogroupSummaryFlags(children)); + } + + @Test + public void testGetAutogroupSummaryFlags_multipleOngoing() { + ArrayMap<String, Integer> children = new ArrayMap<>(); + children.put("a", 0); + children.put("b", FLAG_ONGOING_EVENT); + children.put("c", FLAG_BUBBLE); + children.put("d", FLAG_ONGOING_EVENT); + + assertEquals(FLAG_ONGOING_EVENT | BASE_FLAGS, + mGroupHelper.getAutogroupSummaryFlags(children)); + } + + @Test + public void testGetAutogroupSummaryFlags_oneAutoCancel() { + ArrayMap<String, Integer> children = new ArrayMap<>(); + children.put("a", 0); + children.put("b", FLAG_AUTO_CANCEL); + children.put("c", FLAG_BUBBLE); + + assertEquals(BASE_FLAGS, + mGroupHelper.getAutogroupSummaryFlags(children)); + } + + @Test + public void testGetAutogroupSummaryFlags_allAutoCancel() { + ArrayMap<String, Integer> children = new ArrayMap<>(); + children.put("a", FLAG_AUTO_CANCEL); + children.put("b", FLAG_AUTO_CANCEL | FLAG_CAN_COLORIZE); + children.put("c", FLAG_AUTO_CANCEL); + children.put("d", FLAG_AUTO_CANCEL | FLAG_FOREGROUND_SERVICE); + + assertEquals(FLAG_AUTO_CANCEL | BASE_FLAGS, + mGroupHelper.getAutogroupSummaryFlags(children)); + } + + @Test + public void testGetAutogroupSummaryFlags_allAutoCancelOneOngoing() { + ArrayMap<String, Integer> children = new ArrayMap<>(); + children.put("a", FLAG_AUTO_CANCEL); + children.put("b", FLAG_AUTO_CANCEL | FLAG_CAN_COLORIZE); + children.put("c", FLAG_AUTO_CANCEL); + children.put("d", FLAG_AUTO_CANCEL | FLAG_FOREGROUND_SERVICE | FLAG_ONGOING_EVENT); + + assertEquals(FLAG_AUTO_CANCEL| FLAG_ONGOING_EVENT | BASE_FLAGS, + mGroupHelper.getAutogroupSummaryFlags(children)); + } + + @Test + public void testNoGroup_postingUnderLimit() { final String pkg = "package"; for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) { mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM), false); } - verify(mCallback, never()).addAutoGroupSummary( - eq(UserHandle.USER_SYSTEM), eq(pkg), anyString(), anyBoolean()); - verify(mCallback, never()).addAutoGroup(anyString()); - verify(mCallback, never()).removeAutoGroup(anyString()); - verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + verifyZeroInteractions(mCallback); } @Test - public void testNoGroup_multiPackage() throws Exception { + public void testNoGroup_multiPackage() { final String pkg = "package"; final String pkg2 = "package2"; for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) { @@ -105,31 +195,23 @@ public class GroupHelperTest extends UiServiceTestCase { } mGroupHelper.onNotificationPosted( getSbn(pkg2, AUTOGROUP_AT_COUNT, "four", UserHandle.SYSTEM), false); - verify(mCallback, never()).addAutoGroupSummary( - eq(UserHandle.USER_SYSTEM), eq(pkg), anyString(), anyBoolean()); - verify(mCallback, never()).addAutoGroup(anyString()); - verify(mCallback, never()).removeAutoGroup(anyString()); - verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + verifyZeroInteractions(mCallback); } @Test - public void testNoGroup_multiUser() throws Exception { + public void testNoGroup_multiUser() { final String pkg = "package"; for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) { mGroupHelper.onNotificationPosted(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM), false); } mGroupHelper.onNotificationPosted( - getSbn(pkg, AUTOGROUP_AT_COUNT, "four", UserHandle.ALL), false); - verify(mCallback, never()).addAutoGroupSummary( - anyInt(), eq(pkg), anyString(), anyBoolean()); - verify(mCallback, never()).addAutoGroup(anyString()); - verify(mCallback, never()).removeAutoGroup(anyString()); - verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + getSbn(pkg, AUTOGROUP_AT_COUNT, "four", UserHandle.of(7)), false); + verifyZeroInteractions(mCallback); } @Test - public void testNoGroup_someAreGrouped() throws Exception { + public void testNoGroup_someAreGrouped() { final String pkg = "package"; for (int i = 0; i < AUTOGROUP_AT_COUNT - 1; i++) { mGroupHelper.onNotificationPosted( @@ -137,233 +219,344 @@ public class GroupHelperTest extends UiServiceTestCase { } mGroupHelper.onNotificationPosted( getSbn(pkg, AUTOGROUP_AT_COUNT, "four", UserHandle.SYSTEM, "a"), false); - verify(mCallback, never()).addAutoGroupSummary( - eq(UserHandle.USER_SYSTEM), eq(pkg), anyString(), anyBoolean()); - verify(mCallback, never()).addAutoGroup(anyString()); - verify(mCallback, never()).removeAutoGroup(anyString()); - verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + verifyZeroInteractions(mCallback); } @Test - public void testPostingOverLimit() throws Exception { + public void testAddSummary() { final String pkg = "package"; for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { mGroupHelper.onNotificationPosted( getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM), false); } - verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), eq(false)); + verify(mCallback, times(1)).addAutoGroupSummary( + anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); } @Test - public void testPostingOverLimit_addsOngoingFlag() throws Exception { + public void testAddSummary_oneChildOngoing_summaryOngoing() { final String pkg = "package"; for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); if (i == 0) { - sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; + sbn.getNotification().flags |= FLAG_ONGOING_EVENT; } mGroupHelper.onNotificationPosted(sbn, false); } - verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), eq(true)); + verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), + eq(BASE_FLAGS | FLAG_ONGOING_EVENT)); verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); } @Test - public void testAutoGroupCount_addingNoGroupSBN() { + public void testAddSummary_oneChildAutoCancel_summaryNotAutoCancel() { final String pkg = "package"; - ArrayList<StatusBarNotification> notifications = new ArrayList<>(); - for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) { - notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM)); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + if (i == 0) { + sbn.getNotification().flags |= FLAG_AUTO_CANCEL; + } + mGroupHelper.onNotificationPosted(sbn, false); } + verify(mCallback, times(1)).addAutoGroupSummary( + anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); + verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); + verify(mCallback, never()).removeAutoGroup(anyString()); + verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); + } - for (StatusBarNotification sbn: notifications) { - sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; - sbn.setOverrideGroupKey(AUTOGROUP_KEY); + @Test + public void testAddSummary_allChildrenAutoCancel_summaryAutoCancel() { + final String pkg = "package"; + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + sbn.getNotification().flags |= FLAG_AUTO_CANCEL; + mGroupHelper.onNotificationPosted(sbn, false); } + verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), + eq(BASE_FLAGS | FLAG_AUTO_CANCEL)); + verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); + verify(mCallback, never()).removeAutoGroup(anyString()); + verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); + } - for (StatusBarNotification sbn: notifications) { - mGroupHelper.onNotificationPosted(sbn, true); + @Test + public void testAddSummary_summaryAutoCancelNoClear() { + final String pkg = "package"; + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + sbn.getNotification().flags |= FLAG_AUTO_CANCEL; + if (i == 0) { + sbn.getNotification().flags |= FLAG_NO_CLEAR; + } + mGroupHelper.onNotificationPosted(sbn, false); } - - verify(mCallback, times(AUTOGROUP_AT_COUNT + 1)) - .updateAutogroupSummary(anyInt(), anyString(), eq(true)); - - int userId = UserHandle.SYSTEM.getIdentifier(); - assertEquals(mGroupHelper.getOngoingGroupCount( - userId, pkg), AUTOGROUP_AT_COUNT + 1); + verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), + eq(BASE_FLAGS | FLAG_AUTO_CANCEL | FLAG_NO_CLEAR)); + verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); + verify(mCallback, never()).removeAutoGroup(anyString()); + verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); } @Test - public void testAutoGroupCount_UpdateNotification() { + public void testAutoGrouped_allOngoing_updateChildNotOngoing() { final String pkg = "package"; - ArrayList<StatusBarNotification> notifications = new ArrayList<>(); - for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) { - notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM)); - } - for (StatusBarNotification sbn: notifications) { - sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; - sbn.setOverrideGroupKey(AUTOGROUP_KEY); + // Post AUTOGROUP_AT_COUNT ongoing notifications + ArrayList<StatusBarNotification> notifications = new ArrayList<>(); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + sbn.getNotification().flags |= FLAG_ONGOING_EVENT; + notifications.add(sbn); } for (StatusBarNotification sbn: notifications) { - mGroupHelper.onNotificationPosted(sbn, true); + mGroupHelper.onNotificationPosted(sbn, false); } - notifications.get(0).getNotification().flags &= ~Notification.FLAG_ONGOING_EVENT; - mGroupHelper.onNotificationUpdated(notifications.get(0)); + // One notification is no longer ongoing + notifications.get(0).getNotification().flags &= ~FLAG_ONGOING_EVENT; + mGroupHelper.onNotificationPosted(notifications.get(0), true); - verify(mCallback, times(AUTOGROUP_AT_COUNT + 2)) - .updateAutogroupSummary(anyInt(), anyString(), eq(true)); - - int userId = UserHandle.SYSTEM.getIdentifier(); - assertEquals(mGroupHelper.getOngoingGroupCount( - userId, pkg), AUTOGROUP_AT_COUNT); + // Summary should keep FLAG_ONGOING_EVENT if any child has it + verify(mCallback).updateAutogroupSummary( + anyInt(), anyString(), eq(BASE_FLAGS | FLAG_ONGOING_EVENT)); } @Test - public void testAutoGroupCount_UpdateNotificationAfterChanges() { + public void testAutoGrouped_singleOngoing_removeOngoingChild() { final String pkg = "package"; + + // Post AUTOGROUP_AT_COUNT ongoing notifications ArrayList<StatusBarNotification> notifications = new ArrayList<>(); - for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) { - notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM)); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + if (i == 0) { + sbn.getNotification().flags |= FLAG_ONGOING_EVENT; + } + notifications.add(sbn); } for (StatusBarNotification sbn: notifications) { - sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; - sbn.setOverrideGroupKey(AUTOGROUP_KEY); + mGroupHelper.onNotificationPosted(sbn, false); } - for (StatusBarNotification sbn: notifications) { - mGroupHelper.onNotificationPosted(sbn, true); - } + // remove ongoing + mGroupHelper.onNotificationRemoved(notifications.get(0)); - notifications.get(0).getNotification().flags &= ~Notification.FLAG_ONGOING_EVENT; + // Summary is no longer ongoing + verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), eq(BASE_FLAGS)); + } - mGroupHelper.onNotificationUpdated(notifications.get(0)); + @Test + public void testAutoGrouped_noOngoing_updateOngoingChild() { + final String pkg = "package"; - notifications.get(0).getNotification().flags |= Notification.FLAG_ONGOING_EVENT; + // Post AUTOGROUP_AT_COUNT ongoing notifications + ArrayList<StatusBarNotification> notifications = new ArrayList<>(); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + notifications.add(sbn); + } - mGroupHelper.onNotificationUpdated(notifications.get(0)); + for (StatusBarNotification sbn: notifications) { + mGroupHelper.onNotificationPosted(sbn, false); + } - verify(mCallback, times(AUTOGROUP_AT_COUNT + 3)) - .updateAutogroupSummary(anyInt(), anyString(), eq(true)); + // update to ongoing + notifications.get(0).getNotification().flags |= FLAG_ONGOING_EVENT; + mGroupHelper.onNotificationPosted(notifications.get(0), true); - int userId = UserHandle.SYSTEM.getIdentifier(); - assertEquals(mGroupHelper.getOngoingGroupCount( - userId, pkg), AUTOGROUP_AT_COUNT + 1); + // Summary is now ongoing + verify(mCallback).updateAutogroupSummary( + anyInt(), anyString(), eq(BASE_FLAGS | FLAG_ONGOING_EVENT)); } @Test - public void testAutoGroupCount_RemoveNotification() { + public void testAutoGrouped_noOngoing_addOngoingChild() { final String pkg = "package"; + + // Post AUTOGROUP_AT_COUNT ongoing notifications ArrayList<StatusBarNotification> notifications = new ArrayList<>(); - for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) { - notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM)); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + notifications.add(sbn); } for (StatusBarNotification sbn: notifications) { - sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; - sbn.setOverrideGroupKey(AUTOGROUP_KEY); + mGroupHelper.onNotificationPosted(sbn, false); } - for (StatusBarNotification sbn: notifications) { - mGroupHelper.onNotificationPosted(sbn, true); + // add ongoing + StatusBarNotification sbn = getSbn(pkg, AUTOGROUP_AT_COUNT + 1, null, UserHandle.SYSTEM); + sbn.getNotification().flags |= FLAG_ONGOING_EVENT; + mGroupHelper.onNotificationPosted(sbn, true); + + // Summary is now ongoing + verify(mCallback).updateAutogroupSummary( + anyInt(), anyString(), eq(BASE_FLAGS | FLAG_ONGOING_EVENT)); + } + + @Test + public void testAutoGrouped_singleOngoing_appGroupOngoingChild() { + final String pkg = "package"; + + // Post AUTOGROUP_AT_COUNT ongoing notifications + ArrayList<StatusBarNotification> notifications = new ArrayList<>(); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + if (i == 0) { + sbn.getNotification().flags |= FLAG_ONGOING_EVENT; + } + notifications.add(sbn); } - mGroupHelper.onNotificationRemoved(notifications.get(0)); + for (StatusBarNotification sbn: notifications) { + mGroupHelper.onNotificationPosted(sbn, false); + } - verify(mCallback, times(AUTOGROUP_AT_COUNT + 2)) - .updateAutogroupSummary(anyInt(), anyString(), eq(true)); + // app group the ongoing child + StatusBarNotification sbn = getSbn(pkg, 0, "0", UserHandle.SYSTEM, "app group now"); + mGroupHelper.onNotificationPosted(sbn, true); - int userId = UserHandle.SYSTEM.getIdentifier(); - assertEquals(mGroupHelper.getOngoingGroupCount( - userId, pkg), AUTOGROUP_AT_COUNT); + // Summary is no longer ongoing + verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), eq(BASE_FLAGS)); } - @Test - public void testAutoGroupCount_UpdateToNoneOngoingNotification() { + public void testAutoGrouped_singleOngoing_removeNonOngoingChild() { final String pkg = "package"; + + // Post AUTOGROUP_AT_COUNT ongoing notifications ArrayList<StatusBarNotification> notifications = new ArrayList<>(); - for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) { - notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM)); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + if (i == 0) { + sbn.getNotification().flags |= FLAG_ONGOING_EVENT; + } + notifications.add(sbn); } for (StatusBarNotification sbn: notifications) { - sbn.setOverrideGroupKey(AUTOGROUP_KEY); + mGroupHelper.onNotificationPosted(sbn, false); } - for (StatusBarNotification sbn: notifications) { - mGroupHelper.onNotificationPosted(sbn, true); + // remove ongoing + mGroupHelper.onNotificationRemoved(notifications.get(1)); + + // Summary is still ongoing + verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); + } + + @Test + public void testAutoGrouped_allAutoCancel_updateChildNotAutoCancel() { + final String pkg = "package"; + + // Post AUTOGROUP_AT_COUNT ongoing notifications + ArrayList<StatusBarNotification> notifications = new ArrayList<>(); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + sbn.getNotification().flags |= FLAG_AUTO_CANCEL; + notifications.add(sbn); } - notifications.get(0).getNotification().flags |= Notification.FLAG_ONGOING_EVENT; - mGroupHelper.onNotificationUpdated(notifications.get(0)); + for (StatusBarNotification sbn: notifications) { + mGroupHelper.onNotificationPosted(sbn, false); + } - verify(mCallback, times(1)) - .updateAutogroupSummary(anyInt(), anyString(), eq(true)); + // One notification is no longer autocancelable + notifications.get(0).getNotification().flags &= ~FLAG_AUTO_CANCEL; + mGroupHelper.onNotificationPosted(notifications.get(0), true); - int userId = UserHandle.SYSTEM.getIdentifier(); - assertEquals(mGroupHelper.getOngoingGroupCount( - userId, pkg), 1); + // Summary should no longer be autocancelable + verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), eq(BASE_FLAGS)); } @Test - public void testAutoGroupCount_AddOneOngoingNotification() { + public void testAutoGrouped_almostAllAutoCancel_updateChildAutoCancel() { final String pkg = "package"; + + // Post AUTOGROUP_AT_COUNT ongoing notifications ArrayList<StatusBarNotification> notifications = new ArrayList<>(); - for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) { - notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM)); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + if (i != 0) { + sbn.getNotification().flags |= FLAG_AUTO_CANCEL; + } + notifications.add(sbn); } - StatusBarNotification sbn = notifications.get(AUTOGROUP_AT_COUNT); - sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; - sbn.setOverrideGroupKey(AUTOGROUP_KEY); - - for (StatusBarNotification current: notifications) { - mGroupHelper.onNotificationPosted(current, true); + for (StatusBarNotification sbn: notifications) { + mGroupHelper.onNotificationPosted(sbn, false); } - verify(mCallback, times(1)) - .updateAutogroupSummary(anyInt(), anyString(), eq(true)); + // Missing notification is now autocancelable + notifications.get(0).getNotification().flags |= FLAG_AUTO_CANCEL; + mGroupHelper.onNotificationPosted(notifications.get(0), true); - int userId = UserHandle.SYSTEM.getIdentifier(); - assertEquals(mGroupHelper.getOngoingGroupCount( - userId, pkg), 1); + // Summary should now autocancelable + verify(mCallback).updateAutogroupSummary( + anyInt(), anyString(), eq(BASE_FLAGS | FLAG_AUTO_CANCEL)); } @Test - public void testAutoGroupCount_UpdateNoneOngoing() { + public void testAutoGrouped_allAutoCancel_updateChildAppGrouped() { final String pkg = "package"; + + // Post AUTOGROUP_AT_COUNT ongoing notifications ArrayList<StatusBarNotification> notifications = new ArrayList<>(); - for (int i = 0; i < AUTOGROUP_AT_COUNT + 1; i++) { - notifications.add(getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM)); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + sbn.getNotification().flags |= FLAG_AUTO_CANCEL; + notifications.add(sbn); } for (StatusBarNotification sbn: notifications) { - sbn.setOverrideGroupKey(AUTOGROUP_KEY); + mGroupHelper.onNotificationPosted(sbn, false); + } + + // One notification is now grouped by app + StatusBarNotification sbn = getSbn(pkg, 0, "0", UserHandle.SYSTEM, "app group now"); + mGroupHelper.onNotificationPosted(sbn, true); + + // Summary should be still be autocancelable + verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); + } + + @Test + public void testAutoGrouped_allAutoCancel_removeChild() { + final String pkg = "package"; + + // Post AUTOGROUP_AT_COUNT ongoing notifications + ArrayList<StatusBarNotification> notifications = new ArrayList<>(); + for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { + StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM); + sbn.getNotification().flags |= FLAG_AUTO_CANCEL; + notifications.add(sbn); } for (StatusBarNotification sbn: notifications) { - mGroupHelper.onNotificationPosted(sbn, true); + mGroupHelper.onNotificationPosted(sbn, false); } - verify(mCallback, times(0)) - .updateAutogroupSummary(anyInt(), anyString(), eq(true)); + mGroupHelper.onNotificationRemoved(notifications.get(0)); - int userId = UserHandle.SYSTEM.getIdentifier(); - assertEquals(mGroupHelper.getOngoingGroupCount(userId, pkg), 0); + // Summary should still be autocancelable + verify(mCallback, never()).updateAutogroupSummary(anyInt(), anyString(), anyInt()); } - @Test - public void testDropToZeroRemoveGroup() throws Exception { + public void testDropToZeroRemoveGroup() { final String pkg = "package"; List<StatusBarNotification> posted = new ArrayList<>(); for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { @@ -371,7 +564,8 @@ public class GroupHelperTest extends UiServiceTestCase { posted.add(sbn); mGroupHelper.onNotificationPosted(sbn, false); } - verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), eq(false)); + verify(mCallback, times(1)).addAutoGroupSummary( + anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); @@ -390,7 +584,7 @@ public class GroupHelperTest extends UiServiceTestCase { } @Test - public void testAppStartsGrouping() throws Exception { + public void testAppStartsGrouping() { final String pkg = "package"; List<StatusBarNotification> posted = new ArrayList<>(); for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { @@ -399,7 +593,7 @@ public class GroupHelperTest extends UiServiceTestCase { mGroupHelper.onNotificationPosted(sbn, false); } verify(mCallback, times(1)).addAutoGroupSummary( - anyInt(), eq(pkg), anyString(), anyBoolean()); + anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); @@ -408,9 +602,10 @@ public class GroupHelperTest extends UiServiceTestCase { for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { final StatusBarNotification sbn = getSbn(pkg, i, String.valueOf(i), UserHandle.SYSTEM, "app group"); - mGroupHelper.onNotificationPosted(sbn, false); + sbn.setOverrideGroupKey("autogrouped"); + mGroupHelper.onNotificationPosted(sbn, true); verify(mCallback, times(1)).removeAutoGroup(sbn.getKey()); - if (i < AUTOGROUP_AT_COUNT -1) { + if (i < AUTOGROUP_AT_COUNT - 1) { verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); } } @@ -418,8 +613,7 @@ public class GroupHelperTest extends UiServiceTestCase { } @Test - public void testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled() - throws Exception { + public void testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled() { final String pkg = "package"; List<StatusBarNotification> posted = new ArrayList<>(); for (int i = 0; i < AUTOGROUP_AT_COUNT; i++) { @@ -427,7 +621,8 @@ public class GroupHelperTest extends UiServiceTestCase { posted.add(sbn); mGroupHelper.onNotificationPosted(sbn, false); } - verify(mCallback, times(1)).addAutoGroupSummary(anyInt(), eq(pkg), anyString(), eq(false)); + verify(mCallback, times(1)).addAutoGroupSummary( + anyInt(), eq(pkg), anyString(), eq(BASE_FLAGS)); verify(mCallback, times(AUTOGROUP_AT_COUNT)).addAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); @@ -441,10 +636,7 @@ public class GroupHelperTest extends UiServiceTestCase { Mockito.reset(mCallback); // only one child remains - Map<String, LinkedHashSet<String>> ungroupedForUser = - mGroupHelper.mUngroupedNotifications.get(UserHandle.USER_SYSTEM); - assertNotNull(ungroupedForUser); - assertEquals(1, ungroupedForUser.get(pkg).size()); + assertEquals(1, mGroupHelper.getNotGroupedByAppCount(UserHandle.USER_SYSTEM, pkg)); // Add new notification; it should be autogrouped even though the total count is // < AUTOGROUP_AT_COUNT @@ -454,5 +646,8 @@ public class GroupHelperTest extends UiServiceTestCase { verify(mCallback, times(1)).addAutoGroup(sbn.getKey()); verify(mCallback, never()).removeAutoGroup(anyString()); verify(mCallback, never()).removeAutoGroupSummary(anyInt(), anyString()); + verify(mCallback).updateAutogroupSummary(anyInt(), anyString(), eq(BASE_FLAGS)); + verify(mCallback, never()).addAutoGroupSummary( + anyInt(), anyString(), anyString(), anyInt()); } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index eceb589bba76..9cfdaa7cad0c 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -754,13 +754,19 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, String groupKey, boolean isSummary) { + return generateNotificationRecord(channel, id, "tag" + System.currentTimeMillis(), groupKey, + isSummary); + } + + private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id, + String tag, String groupKey, boolean isSummary) { Notification.Builder nb = new Notification.Builder(mContext, channel.getId()) .setContentTitle("foo") .setSmallIcon(android.R.drawable.sym_def_app_icon) .setGroup(groupKey) .setGroupSummary(isSummary); StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, - "tag" + System.currentTimeMillis(), mUid, 0, + tag, mUid, 0, nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); return new NotificationRecord(mContext, sbn, channel); } @@ -1899,7 +1905,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.mSummaryByGroupKey.put("pkg", summary); mService.mAutobundledSummaries.put(0, new ArrayMap<>()); mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey()); - mService.updateAutobundledSummaryFlags(0, "pkg", true, false); + mService.updateAutobundledSummaryFlags( + 0, "pkg", GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT, false); assertTrue(summary.getSbn().isOngoing()); } @@ -1915,7 +1922,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.mAutobundledSummaries.get(0).put("pkg", summary.getKey()); mService.mSummaryByGroupKey.put("pkg", summary); - mService.updateAutobundledSummaryFlags(0, "pkg", false, false); + mService.updateAutobundledSummaryFlags(0, "pkg", GroupHelper.BASE_FLAGS, false); assertFalse(summary.getSbn().isOngoing()); } @@ -2897,7 +2904,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mPermissionHelper.isPermissionFixed(PKG, temp.getUserId())).thenReturn(true); NotificationRecord r = mService.createAutoGroupSummary( - temp.getUserId(), temp.getSbn().getPackageName(), temp.getKey(), false); + temp.getUserId(), temp.getSbn().getPackageName(), temp.getKey(), 0); assertThat(r.isImportanceFixed()).isTrue(); } @@ -4213,7 +4220,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test - public void testOnlyAutogroupIfGroupChanged_noPriorNoti_autogroups() throws Exception { + public void testOnlyAutogroupIfNeeded_newNotification_ghUpdate() { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); mService.addEnqueuedNotification(r); NotificationManagerService.PostNotificationRunnable runnable = @@ -4226,17 +4233,18 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test - public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups() - throws Exception { - NotificationRecord r = - generateNotificationRecord(mTestNotificationChannel, 0, "group", false); + public void testOnlyAutogroupIfNeeded_groupChanged_ghUpdate() { + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, + "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", "group", false); mService.addNotification(r); - r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); - mService.addEnqueuedNotification(r); + NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0, + "testOnlyAutogroupIfNeeded_groupChanged_ghUpdate", null, false); + mService.addEnqueuedNotification(update); NotificationManagerService.PostNotificationRunnable runnable = - mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), - r.getUid(), SystemClock.elapsedRealtime()); + mService.new PostNotificationRunnable(update.getKey(), + update.getSbn().getPackageName(), update.getUid(), + SystemClock.elapsedRealtime()); runnable.run(); waitForIdle(); @@ -4244,16 +4252,39 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test - public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups() - throws Exception { - NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group", - false); + public void testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate() { + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, + "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", "group", false); mService.addNotification(r); - mService.addEnqueuedNotification(r); + NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0, + "testOnlyAutogroupIfNeeded_flagsChanged_ghUpdate", null, false); + update.getNotification().flags = FLAG_AUTO_CANCEL; + mService.addEnqueuedNotification(update); NotificationManagerService.PostNotificationRunnable runnable = - mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), - r.getUid(), SystemClock.elapsedRealtime()); + mService.new PostNotificationRunnable(update.getKey(), + update.getSbn().getPackageName(), update.getUid(), + SystemClock.elapsedRealtime()); + runnable.run(); + waitForIdle(); + + verify(mGroupHelper, times(1)).onNotificationPosted(any(), anyBoolean()); + } + + @Test + public void testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate() { + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, + "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false); + mService.addNotification(r); + NotificationRecord update = generateNotificationRecord(mTestNotificationChannel, 0, + "testOnlyAutogroupIfGroupChanged_noValidChange_noGhUpdate", null, false); + update.getNotification().color = Color.BLACK; + mService.addEnqueuedNotification(update); + + NotificationManagerService.PostNotificationRunnable runnable = + mService.new PostNotificationRunnable(update.getKey(), + update.getSbn().getPackageName(), + update.getUid(), SystemClock.elapsedRealtime()); runnable.run(); waitForIdle(); @@ -10220,10 +10251,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // grouphelper is a mock here, so make the calls it would make - // add summary; wait for it to be posted - mService.addAutoGroupSummary(nr1.getUserId(), nr1.getSbn().getPackageName(), nr1.getKey(), - true); - waitForIdle(); + // add summary + mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(), + nr1.getSbn().getPackageName(), nr1.getKey(), + GroupHelper.BASE_FLAGS | FLAG_ONGOING_EVENT)); // cancel both children mBinderService.cancelNotificationWithTag(PKG, PKG, nr0.getSbn().getTag(), @@ -10232,9 +10263,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { nr1.getSbn().getId(), nr1.getSbn().getUserId()); waitForIdle(); - // group helper would send 'remove flag' and then 'remove summary' events - mService.updateAutobundledSummaryFlags(nr1.getUserId(), nr1.getSbn().getPackageName(), - false, false); + // group helper would send 'remove summary' event mService.clearAutogroupSummaryLocked(nr1.getUserId(), nr1.getSbn().getPackageName()); waitForIdle(); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java index e6569f7e0ce2..9fe0e49c4ab8 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordExtractorDataTest.java @@ -98,6 +98,41 @@ public class NotificationRecordExtractorDataTest extends UiServiceTestCase { } @Test + public void testHasDiffs_autoBundled() { + NotificationRecord r = generateRecord(); + + NotificationRecordExtractorData extractorData = new NotificationRecordExtractorData( + 1, + r.getPackageVisibilityOverride(), + r.canShowBadge(), + r.canBubble(), + r.getNotification().isBubbleNotification(), + r.getChannel(), + r.getGroupKey(), + r.getPeopleOverride(), + r.getSnoozeCriteria(), + r.getUserSentiment(), + r.getSuppressedVisualEffects(), + r.getSystemGeneratedSmartActions(), + r.getSmartReplies(), + r.getImportance(), + r.getRankingScore(), + r.isConversation(), + r.getProposedImportance(), + r.hasSensitiveContent()); + + Bundle signals = new Bundle(); + signals.putString(Adjustment.KEY_GROUP_KEY, "ranker_group"); + Adjustment adjustment = new Adjustment("pkg", r.getKey(), signals, "", 0); + r.addAdjustment(adjustment); + NotificationAdjustmentExtractor adjustmentExtractor = new NotificationAdjustmentExtractor(); + adjustmentExtractor.process(r); + + assertTrue(extractorData.hasDiffForRankingLocked(r, 1)); + assertTrue(extractorData.hasDiffForLoggingLocked(r, 1)); + } + + @Test public void testHasDiffs_sensitiveContentChange() { NotificationRecord r = generateRecord(); diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml index f2ffc19f2a4e..7272abba897d 100644 --- a/tests/FlickerTests/AndroidTest.xml +++ b/tests/FlickerTests/AndroidTest.xml @@ -29,6 +29,7 @@ <option name="teardown-command" value="settings delete secure show_ime_with_hard_keyboard" /> <option name="teardown-command" value="settings delete system show_touches" /> <option name="teardown-command" value="settings delete system pointer_location" /> + <option name="teardown-command" value="cmd overlay enable com.android.internal.systemui.navbar.gestural" /> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> <option name="cleanup-apks" value="true"/> diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java index f8d885ae3faf..d7fa124623ce 100644 --- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java @@ -417,9 +417,9 @@ public class PackageWatchdogTest { int failureReason, int mitigationCount) { if (versionedPackage.getVersionCode() == VERSION_CODE) { // Only rollback for specific versionCode - return PackageHealthObserverImpact.USER_IMPACT_MEDIUM; + return PackageHealthObserverImpact.USER_IMPACT_LEVEL_30; } - return PackageHealthObserverImpact.USER_IMPACT_NONE; + return PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; } }; @@ -442,13 +442,13 @@ public class PackageWatchdogTest { public void testPackageFailureNotifyAllDifferentImpacts() throws Exception { PackageWatchdog watchdog = createWatchdog(); TestObserver observerNone = new TestObserver(OBSERVER_NAME_1, - PackageHealthObserverImpact.USER_IMPACT_NONE); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_0); TestObserver observerHigh = new TestObserver(OBSERVER_NAME_2, - PackageHealthObserverImpact.USER_IMPACT_HIGH); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); TestObserver observerMid = new TestObserver(OBSERVER_NAME_3, - PackageHealthObserverImpact.USER_IMPACT_MEDIUM); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_30); TestObserver observerLow = new TestObserver(OBSERVER_NAME_4, - PackageHealthObserverImpact.USER_IMPACT_LOW); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_10); // Start observing for all impact observers watchdog.startObservingHealth(observerNone, Arrays.asList(APP_A, APP_B, APP_C, APP_D), @@ -499,9 +499,9 @@ public class PackageWatchdogTest { public void testPackageFailureNotifyLeastImpactSuccessively() throws Exception { PackageWatchdog watchdog = createWatchdog(); TestObserver observerFirst = new TestObserver(OBSERVER_NAME_1, - PackageHealthObserverImpact.USER_IMPACT_LOW); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_10); TestObserver observerSecond = new TestObserver(OBSERVER_NAME_2, - PackageHealthObserverImpact.USER_IMPACT_MEDIUM); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_30); // Start observing for observerFirst and observerSecond with failure handling watchdog.startObservingHealth(observerFirst, Arrays.asList(APP_A), LONG_DURATION); @@ -517,7 +517,7 @@ public class PackageWatchdogTest { assertThat(observerSecond.mMitigatedPackages).isEmpty(); // After observerFirst handles failure, next action it has is high impact - observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_HIGH; + observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_100; observerFirst.mMitigatedPackages.clear(); observerSecond.mMitigatedPackages.clear(); @@ -531,7 +531,7 @@ public class PackageWatchdogTest { assertThat(observerFirst.mMitigatedPackages).isEmpty(); // After observerSecond handles failure, it has no further actions - observerSecond.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE; + observerSecond.mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; observerFirst.mMitigatedPackages.clear(); observerSecond.mMitigatedPackages.clear(); @@ -545,7 +545,7 @@ public class PackageWatchdogTest { assertThat(observerSecond.mMitigatedPackages).isEmpty(); // After observerFirst handles failure, it too has no further actions - observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE; + observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_0; observerFirst.mMitigatedPackages.clear(); observerSecond.mMitigatedPackages.clear(); @@ -566,9 +566,9 @@ public class PackageWatchdogTest { public void testPackageFailureNotifyOneSameImpact() throws Exception { PackageWatchdog watchdog = createWatchdog(); TestObserver observer1 = new TestObserver(OBSERVER_NAME_1, - PackageHealthObserverImpact.USER_IMPACT_HIGH); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); TestObserver observer2 = new TestObserver(OBSERVER_NAME_2, - PackageHealthObserverImpact.USER_IMPACT_HIGH); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); // Start observing for observer1 and observer2 with failure handling watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION); @@ -592,11 +592,11 @@ public class PackageWatchdogTest { TestController controller = new TestController(); PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */); TestObserver observer1 = new TestObserver(OBSERVER_NAME_1, - PackageHealthObserverImpact.USER_IMPACT_HIGH); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); TestObserver observer2 = new TestObserver(OBSERVER_NAME_2, - PackageHealthObserverImpact.USER_IMPACT_HIGH); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); TestObserver observer3 = new TestObserver(OBSERVER_NAME_3, - PackageHealthObserverImpact.USER_IMPACT_HIGH); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); // Start observing with explicit health checks for APP_A and APP_B respectively @@ -645,7 +645,7 @@ public class PackageWatchdogTest { TestController controller = new TestController(); PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */); TestObserver observer = new TestObserver(OBSERVER_NAME_1, - PackageHealthObserverImpact.USER_IMPACT_MEDIUM); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_30); // Start observing with explicit health checks for APP_A and APP_B controller.setSupportedPackages(Arrays.asList(APP_A, APP_B, APP_C)); @@ -711,7 +711,7 @@ public class PackageWatchdogTest { TestController controller = new TestController(); PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */); TestObserver observer = new TestObserver(OBSERVER_NAME_1, - PackageHealthObserverImpact.USER_IMPACT_MEDIUM); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_30); // Start observing with explicit health checks for APP_A and // package observation duration == LONG_DURATION @@ -742,7 +742,7 @@ public class PackageWatchdogTest { TestController controller = new TestController(); PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */); TestObserver observer = new TestObserver(OBSERVER_NAME_1, - PackageHealthObserverImpact.USER_IMPACT_MEDIUM); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_30); // Start observing with explicit health checks for APP_A and // package observation duration == SHORT_DURATION / 2 @@ -818,7 +818,7 @@ public class PackageWatchdogTest { // Start observing with failure handling TestObserver observer = new TestObserver(OBSERVER_NAME_1, - PackageHealthObserverImpact.USER_IMPACT_HIGH); + PackageHealthObserverImpact.USER_IMPACT_LEVEL_100); wd.startObservingHealth(observer, Collections.singletonList(APP_A), SHORT_DURATION); // Notify of NetworkStack failure @@ -1073,9 +1073,9 @@ public class PackageWatchdogTest { public void testBootLoopMitigationDoneForLowestUserImpact() { PackageWatchdog watchdog = createWatchdog(); TestObserver bootObserver1 = new TestObserver(OBSERVER_NAME_1); - bootObserver1.setImpact(PackageHealthObserverImpact.USER_IMPACT_LOW); + bootObserver1.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_10); TestObserver bootObserver2 = new TestObserver(OBSERVER_NAME_2); - bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_MEDIUM); + bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_30); watchdog.registerHealthObserver(bootObserver1); watchdog.registerHealthObserver(bootObserver2); for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) { @@ -1446,7 +1446,7 @@ public class PackageWatchdogTest { TestObserver(String name) { mName = name; - mImpact = PackageHealthObserverImpact.USER_IMPACT_MEDIUM; + mImpact = PackageHealthObserverImpact.USER_IMPACT_LEVEL_30; } TestObserver(String name, int impact) { diff --git a/tests/testables/tests/AndroidManifest.xml b/tests/testables/tests/AndroidManifest.xml index 2bfb04fdb765..1731f6be4bf2 100644 --- a/tests/testables/tests/AndroidManifest.xml +++ b/tests/testables/tests/AndroidManifest.xml @@ -21,7 +21,7 @@ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.MANAGE_USERS" /> - <application android:debuggable="true"> + <application android:debuggable="true" android:testOnly="true"> <uses-library android:name="android.test.runner" /> </application> diff --git a/tests/testables/tests/AndroidTest.xml b/tests/testables/tests/AndroidTest.xml new file mode 100644 index 000000000000..6d2979423efa --- /dev/null +++ b/tests/testables/tests/AndroidTest.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. + --> +<configuration description="Runs Testable Tests."> + <option name="test-tag" value="TestablesTests" /> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="install-arg" value="-t" /> + <option name="test-file-name" value="TestablesTests.apk" /> + </target_preparer> + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="com.android.testables"/> + </test> +</configuration> |