From 2014b71f4abf6f9b61bd815f6a1f8923f8694def Mon Sep 17 00:00:00 2001 From: Vincent Wang Date: Tue, 3 May 2022 13:07:17 +0800 Subject: [PATCH 01/45] DO NOT MERGE: Fix Budget bakers wallet app's fingerprint icon doesn't line up with sensor This issue is caused by side effect of CL Ib95d090729b1561a70a853b17a4e17cdcbb71fbd. Description height should be used when its visibility is GONE. BUG: 230665942 Test: Check budget bakers wallet app's fingerprint icon Change-Id: Id8d3e4a203ca012ab42ca8f984e8a09df1a77c85 (cherry picked from commit 29f4d11428ee58d9583765293618a93d13f84957) Merged-In: Id8d3e4a203ca012ab42ca8f984e8a09df1a77c85 --- .../systemui/biometrics/UdfpsDialogMeasureAdapter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java index 2f097924817e9..8de7213520695 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java @@ -154,7 +154,9 @@ public class UdfpsDialogMeasureAdapter { //re-calculate the height of description View description = mView.findViewById(R.id.description); - totalHeight += measureDescription(description, displayHeight, width, totalHeight); + if (description != null && description.getVisibility() != View.GONE) { + totalHeight += measureDescription(description, displayHeight, width, totalHeight); + } return new AuthDialog.LayoutParams(width, totalHeight); } From 75e706ed69708404b2684a5849f9f2ba791c5304 Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Tue, 10 May 2022 16:09:13 +0000 Subject: [PATCH 02/45] Fix IME callback not being re-registered on screen off / on. Bug:231917948 Bug:229355440 Test: atest InputMethodServiceLifecycleTest Test: atest CtsInputMethodTestCases:InputMethodServiceTest Test atest CtsInputMethodTestCases:KeyboardVisibilityControlTest Change-Id: I8dc1425aa9338b37128d308bf58fd15c39d04a88 (cherry picked from commit c16b5740556d39e9cb2323ffdc164475bd757883) Merged-In: I8dc1425aa9338b37128d308bf58fd15c39d04a88 --- .../java/android/inputmethodservice/InputMethodService.java | 6 +++++- core/java/android/window/ImeOnBackInvokedDispatcher.java | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 25296bc0a8b91..200fe22edaadd 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1625,7 +1625,6 @@ public class InputMethodService extends AbstractInputMethodService { // when IME developers are doing something unsupported. InputMethodPrivilegedOperationsRegistry.remove(mToken); } - unregisterCompatOnBackInvokedCallback(); mImeDispatcher = null; } @@ -2788,6 +2787,11 @@ public class InputMethodService extends AbstractInputMethodService { if (mInkWindow != null) { finishStylusHandwriting(); } + // Back callback is typically unregistered in {@link #hideWindow()}, but it's possible + // for {@link #doFinishInput()} to be called without {@link #hideWindow()} so we also + // unregister here. + // TODO(b/232341407): Add CTS to verify back behavior after screen on / off. + unregisterCompatOnBackInvokedCallback(); } void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) { diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java index d5763aa25884f..8bdf233b81c8a 100644 --- a/core/java/android/window/ImeOnBackInvokedDispatcher.java +++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java @@ -158,6 +158,12 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc /** Clears all registered callbacks on the instance. */ public void clear() { + // Unregister previously registered callbacks if there's any. + if (getReceivingDispatcher() != null) { + for (OnBackInvokedCallback callback : mImeCallbackMap.values()) { + getReceivingDispatcher().unregisterOnBackInvokedCallback(callback); + } + } mImeCallbackMap.clear(); } From 4ec3d70014764f71b3687303af48b90722a6752e Mon Sep 17 00:00:00 2001 From: Chavi Weingarten Date: Thu, 23 Jun 2022 16:44:06 +0000 Subject: [PATCH 03/45] Set mAlreadyRequestedSync only when in a BLASTSync WindowState#useBLASTSync returns true if in a blast sync but also if there are mDrawHandlers. In that case, we only want to mark mAlreadyRequestedSync to true if we know it's a blast sync since the unmark is done when the sync is complete. Test: Pip expand no delay Fixes: 236882306 Change-Id: Ifb5785b93888a0fb3e27180005ea1b3940a293b7 (cherry picked from commit 5ef2940b89606257cd848d25d6263f496096b4e7) Merged-In: Ifb5785b93888a0fb3e27180005ea1b3940a293b7 --- .../java/com/android/server/wm/WindowManagerService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index ae616551958c1..326ce81fd8b1a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -122,6 +122,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; +import static com.android.server.wm.WindowContainer.SYNC_STATE_NONE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; @@ -2557,7 +2558,11 @@ public class WindowManagerService extends IWindowManager.Stub win.mLastSeqIdSentToRelayout = win.mSyncSeqId; outSyncIdBundle.putInt("seqid", win.mSyncSeqId); - win.mAlreadyRequestedSync = true; + // Only mark mAlreadyRequestedSync if there's an explicit sync request, and not if + // we're syncing due to mDrawHandlers + if (win.mSyncState != SYNC_STATE_NONE) { + win.mAlreadyRequestedSync = true; + } } else { outSyncIdBundle.putInt("seqid", -1); } From f1d4ce353e89841ac25de4bd6a3cc1ac6f9fc49c Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Tue, 28 Jun 2022 21:16:23 +0000 Subject: [PATCH 04/45] Revert "Removes left/right buttons from bottom area." This reverts commit 0fc5c393afc4133f5b3cc45fbc0e6d20ef6d255f. Reason for revert: Droidfood Blocking bug: 237349230 Change-Id: Ia0fa18ba1a72bc57f45b11f5954b6d8eada076ab (cherry picked from commit 03e0b8e0a7d1fbde2baba05ec8a8c7efaef4c4c9) Merged-In: Ia0fa18ba1a72bc57f45b11f5954b6d8eada076ab --- .../res/layout/keyguard_bottom_area.xml | 20 + packages/SystemUI/res/values/config.xml | 6 + packages/SystemUI/res/values/dimens.xml | 3 + packages/SystemUI/res/values/strings.xml | 7 + .../statusbar/phone/CentralSurfaces.java | 6 + .../CentralSurfacesCommandQueueCallbacks.java | 3 +- .../statusbar/phone/CentralSurfacesImpl.java | 36 +- .../phone/KeyguardAffordanceHelper.java | 587 +++++++++++++++++ .../phone/KeyguardBottomAreaView.java | 610 +++++++++++++++++- .../NotificationPanelViewController.java | 244 ++++++- .../statusbar/phone/PanelViewController.java | 4 +- .../statusbar/policy/PreviewInflater.java | 150 +++++ .../phone/CentralSurfacesImplTest.java | 2 + .../statusbar/phone/KeyguardBottomAreaTest.kt | 5 +- .../NotificationPanelViewControllerTest.java | 3 + 15 files changed, 1648 insertions(+), 38 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index 12dfa1042dd7d..8f8993f3c8d98 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -59,6 +59,26 @@ + + + + 400 + + false + + + false + 333 333 diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 7f7b8716d27c4..4d365412828ed 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -676,6 +676,9 @@ 30dp + + 120dp + 60dp diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index ef672f3a62135..343ec4f67964b 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -313,6 +313,13 @@ Scanning face Send + + + open phone + + open voice assist + + open camera Cancel diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index d25bbbd2a591f..2c22bc68c1981 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -427,6 +427,12 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn void onHintFinished(); + void onCameraHintStarted(); + + void onVoiceAssistHintStarted(); + + void onPhoneHintStarted(); + void onTrackingStopped(boolean expand); // TODO: Figure out way to remove these. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java index 38c37f03f6431..9060d5f67913a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java @@ -388,7 +388,8 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba if (mStatusBarKeyguardViewManager.isBouncerShowing()) { mStatusBarKeyguardViewManager.reset(true /* hide */); } - mNotificationPanelViewController.launchCamera(source); + mNotificationPanelViewController.launchCamera( + mCentralSurfaces.isDeviceInteractive() /* animate */, source); mCentralSurfaces.updateScrimController(); } else { // We need to defer the camera launch until the screen comes on, since otherwise diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 4f99deaaf7995..5181af773d9a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -1285,6 +1285,8 @@ public class CentralSurfacesImpl extends CoreStartable implements backdrop.setScaleY(scale); }); + mNotificationPanelViewController.setUserSetupComplete(mUserSetup); + // Set up the quick settings tile panel final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame); if (container != null) { @@ -3022,7 +3024,8 @@ public class CentralSurfacesImpl extends CoreStartable implements @Override public boolean isInLaunchTransition() { - return mNotificationPanelViewController.isLaunchTransitionFinished(); + return mNotificationPanelViewController.isLaunchTransitionRunning() + || mNotificationPanelViewController.isLaunchTransitionFinished(); } /** @@ -3054,7 +3057,11 @@ public class CentralSurfacesImpl extends CoreStartable implements mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(), LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); }; - hideRunnable.run(); + if (mNotificationPanelViewController.isLaunchTransitionRunning()) { + mNotificationPanelViewController.setLaunchTransitionEndRunnable(hideRunnable); + } else { + hideRunnable.run(); + } } private void cancelAfterLaunchTransitionRunnables() { @@ -3063,6 +3070,7 @@ public class CentralSurfacesImpl extends CoreStartable implements } mLaunchTransitionEndRunnable = null; mLaunchTransitionCancelRunnable = null; + mNotificationPanelViewController.setLaunchTransitionEndRunnable(null); } /** @@ -3490,6 +3498,24 @@ public class CentralSurfacesImpl extends CoreStartable implements mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS); } + @Override + public void onCameraHintStarted() { + mFalsingCollector.onCameraHintStarted(); + mKeyguardIndicationController.showTransientIndication(R.string.camera_hint); + } + + @Override + public void onVoiceAssistHintStarted() { + mFalsingCollector.onLeftAffordanceHintStarted(); + mKeyguardIndicationController.showTransientIndication(R.string.voice_hint); + } + + @Override + public void onPhoneHintStarted() { + mFalsingCollector.onLeftAffordanceHintStarted(); + mKeyguardIndicationController.showTransientIndication(R.string.phone_hint); + } + @Override public void onTrackingStopped(boolean expand) { } @@ -3674,7 +3700,8 @@ public class CentralSurfacesImpl extends CoreStartable implements mWakeUpCoordinator.setFullyAwake(true); mWakeUpCoordinator.setWakingUp(false); if (mLaunchCameraWhenFinishedWaking) { - mNotificationPanelViewController.launchCamera(mLastCameraLaunchSource); + mNotificationPanelViewController.launchCamera( + false /* animate */, mLastCameraLaunchSource); mLaunchCameraWhenFinishedWaking = false; } if (mLaunchEmergencyActionWhenFinishedWaking) { @@ -4316,6 +4343,9 @@ public class CentralSurfacesImpl extends CoreStartable implements if (!mUserSetup) { animateCollapseQuickSettings(); } + if (mNotificationPanelViewController != null) { + mNotificationPanelViewController.setUserSetupComplete(mUserSetup); + } updateQsExpansionEnabled(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java new file mode 100644 index 0000000000000..2922b4c98d347 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java @@ -0,0 +1,587 @@ +/* + * Copyright (C) 2014 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.statusbar.phone; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; + +import com.android.systemui.R; +import com.android.systemui.animation.Interpolators; +import com.android.systemui.classifier.Classifier; +import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.statusbar.KeyguardAffordanceView; +import com.android.wm.shell.animation.FlingAnimationUtils; + +/** + * A touch handler of the keyguard which is responsible for launching phone and camera affordances. + */ +public class KeyguardAffordanceHelper { + + public static final long HINT_PHASE1_DURATION = 200; + private static final long HINT_PHASE2_DURATION = 350; + private static final float BACKGROUND_RADIUS_SCALE_FACTOR = 0.25f; + private static final int HINT_CIRCLE_OPEN_DURATION = 500; + + private final Context mContext; + private final Callback mCallback; + + private FlingAnimationUtils mFlingAnimationUtils; + private VelocityTracker mVelocityTracker; + private boolean mSwipingInProgress; + private float mInitialTouchX; + private float mInitialTouchY; + private float mTranslation; + private float mTranslationOnDown; + private int mTouchSlop; + private int mMinTranslationAmount; + private int mMinFlingVelocity; + private int mHintGrowAmount; + private KeyguardAffordanceView mLeftIcon; + private KeyguardAffordanceView mRightIcon; + private Animator mSwipeAnimator; + private final FalsingManager mFalsingManager; + private int mMinBackgroundRadius; + private boolean mMotionCancelled; + private int mTouchTargetSize; + private View mTargetedView; + private boolean mTouchSlopExeeded; + private AnimatorListenerAdapter mFlingEndListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mSwipeAnimator = null; + mSwipingInProgress = false; + mTargetedView = null; + } + }; + private Runnable mAnimationEndRunnable = new Runnable() { + @Override + public void run() { + mCallback.onAnimationToSideEnded(); + } + }; + + KeyguardAffordanceHelper(Callback callback, Context context, FalsingManager falsingManager) { + mContext = context; + mCallback = callback; + initIcons(); + updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false); + updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false); + mFalsingManager = falsingManager; + initDimens(); + } + + private void initDimens() { + final ViewConfiguration configuration = ViewConfiguration.get(mContext); + mTouchSlop = configuration.getScaledPagingTouchSlop(); + mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity(); + mMinTranslationAmount = mContext.getResources().getDimensionPixelSize( + R.dimen.keyguard_min_swipe_amount); + mMinBackgroundRadius = mContext.getResources().getDimensionPixelSize( + R.dimen.keyguard_affordance_min_background_radius); + mTouchTargetSize = mContext.getResources().getDimensionPixelSize( + R.dimen.keyguard_affordance_touch_target_size); + mHintGrowAmount = + mContext.getResources().getDimensionPixelSize(R.dimen.hint_grow_amount_sideways); + mFlingAnimationUtils = new FlingAnimationUtils(mContext.getResources().getDisplayMetrics(), + 0.4f); + } + + private void initIcons() { + mLeftIcon = mCallback.getLeftIcon(); + mRightIcon = mCallback.getRightIcon(); + updatePreviews(); + } + + public void updatePreviews() { + mLeftIcon.setPreviewView(mCallback.getLeftPreview()); + mRightIcon.setPreviewView(mCallback.getRightPreview()); + } + + public boolean onTouchEvent(MotionEvent event) { + int action = event.getActionMasked(); + if (mMotionCancelled && action != MotionEvent.ACTION_DOWN) { + return false; + } + final float y = event.getY(); + final float x = event.getX(); + + boolean isUp = false; + switch (action) { + case MotionEvent.ACTION_DOWN: + View targetView = getIconAtPosition(x, y); + if (targetView == null || (mTargetedView != null && mTargetedView != targetView)) { + mMotionCancelled = true; + return false; + } + if (mTargetedView != null) { + cancelAnimation(); + } else { + mTouchSlopExeeded = false; + } + startSwiping(targetView); + mInitialTouchX = x; + mInitialTouchY = y; + mTranslationOnDown = mTranslation; + initVelocityTracker(); + trackMovement(event); + mMotionCancelled = false; + break; + case MotionEvent.ACTION_POINTER_DOWN: + mMotionCancelled = true; + endMotion(true /* forceSnapBack */, x, y); + break; + case MotionEvent.ACTION_MOVE: + trackMovement(event); + float xDist = x - mInitialTouchX; + float yDist = y - mInitialTouchY; + float distance = (float) Math.hypot(xDist, yDist); + if (!mTouchSlopExeeded && distance > mTouchSlop) { + mTouchSlopExeeded = true; + } + if (mSwipingInProgress) { + if (mTargetedView == mRightIcon) { + distance = mTranslationOnDown - distance; + distance = Math.min(0, distance); + } else { + distance = mTranslationOnDown + distance; + distance = Math.max(0, distance); + } + setTranslation(distance, false /* isReset */, false /* animateReset */); + } + break; + + case MotionEvent.ACTION_UP: + isUp = true; + case MotionEvent.ACTION_CANCEL: + boolean hintOnTheRight = mTargetedView == mRightIcon; + trackMovement(event); + endMotion(!isUp, x, y); + if (!mTouchSlopExeeded && isUp) { + mCallback.onIconClicked(hintOnTheRight); + } + break; + } + return true; + } + + private void startSwiping(View targetView) { + mCallback.onSwipingStarted(targetView == mRightIcon); + mSwipingInProgress = true; + mTargetedView = targetView; + } + + private View getIconAtPosition(float x, float y) { + if (leftSwipePossible() && isOnIcon(mLeftIcon, x, y)) { + return mLeftIcon; + } + if (rightSwipePossible() && isOnIcon(mRightIcon, x, y)) { + return mRightIcon; + } + return null; + } + + public boolean isOnAffordanceIcon(float x, float y) { + return isOnIcon(mLeftIcon, x, y) || isOnIcon(mRightIcon, x, y); + } + + private boolean isOnIcon(View icon, float x, float y) { + float iconX = icon.getX() + icon.getWidth() / 2.0f; + float iconY = icon.getY() + icon.getHeight() / 2.0f; + double distance = Math.hypot(x - iconX, y - iconY); + return distance <= mTouchTargetSize / 2; + } + + private void endMotion(boolean forceSnapBack, float lastX, float lastY) { + if (mSwipingInProgress) { + flingWithCurrentVelocity(forceSnapBack, lastX, lastY); + } else { + mTargetedView = null; + } + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private boolean rightSwipePossible() { + return mRightIcon.getVisibility() == View.VISIBLE; + } + + private boolean leftSwipePossible() { + return mLeftIcon.getVisibility() == View.VISIBLE; + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + return false; + } + + public void startHintAnimation(boolean right, + Runnable onFinishedListener) { + cancelAnimation(); + startHintAnimationPhase1(right, onFinishedListener); + } + + private void startHintAnimationPhase1(final boolean right, final Runnable onFinishedListener) { + final KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon; + ValueAnimator animator = getAnimatorToRadius(right, mHintGrowAmount); + animator.addListener(new AnimatorListenerAdapter() { + private boolean mCancelled; + + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mCancelled) { + mSwipeAnimator = null; + mTargetedView = null; + onFinishedListener.run(); + } else { + startUnlockHintAnimationPhase2(right, onFinishedListener); + } + } + }); + animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); + animator.setDuration(HINT_PHASE1_DURATION); + animator.start(); + mSwipeAnimator = animator; + mTargetedView = targetView; + } + + /** + * Phase 2: Move back. + */ + private void startUnlockHintAnimationPhase2(boolean right, final Runnable onFinishedListener) { + ValueAnimator animator = getAnimatorToRadius(right, 0); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mSwipeAnimator = null; + mTargetedView = null; + onFinishedListener.run(); + } + }); + animator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); + animator.setDuration(HINT_PHASE2_DURATION); + animator.setStartDelay(HINT_CIRCLE_OPEN_DURATION); + animator.start(); + mSwipeAnimator = animator; + } + + private ValueAnimator getAnimatorToRadius(final boolean right, int radius) { + final KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon; + ValueAnimator animator = ValueAnimator.ofFloat(targetView.getCircleRadius(), radius); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float newRadius = (float) animation.getAnimatedValue(); + targetView.setCircleRadiusWithoutAnimation(newRadius); + float translation = getTranslationFromRadius(newRadius); + mTranslation = right ? -translation : translation; + updateIconsFromTranslation(targetView); + } + }); + return animator; + } + + private void cancelAnimation() { + if (mSwipeAnimator != null) { + mSwipeAnimator.cancel(); + } + } + + private void flingWithCurrentVelocity(boolean forceSnapBack, float lastX, float lastY) { + float vel = getCurrentVelocity(lastX, lastY); + + // We snap back if the current translation is not far enough + boolean snapBack = false; + if (mCallback.needsAntiFalsing()) { + snapBack = snapBack || mFalsingManager.isFalseTouch( + mTargetedView == mRightIcon + ? Classifier.RIGHT_AFFORDANCE : Classifier.LEFT_AFFORDANCE); + } + snapBack = snapBack || isBelowFalsingThreshold(); + + // or if the velocity is in the opposite direction. + boolean velIsInWrongDirection = vel * mTranslation < 0; + snapBack |= Math.abs(vel) > mMinFlingVelocity && velIsInWrongDirection; + vel = snapBack ^ velIsInWrongDirection ? 0 : vel; + fling(vel, snapBack || forceSnapBack, mTranslation < 0); + } + + private boolean isBelowFalsingThreshold() { + return Math.abs(mTranslation) < Math.abs(mTranslationOnDown) + getMinTranslationAmount(); + } + + private int getMinTranslationAmount() { + float factor = mCallback.getAffordanceFalsingFactor(); + return (int) (mMinTranslationAmount * factor); + } + + private void fling(float vel, final boolean snapBack, boolean right) { + float target = right ? -mCallback.getMaxTranslationDistance() + : mCallback.getMaxTranslationDistance(); + target = snapBack ? 0 : target; + + ValueAnimator animator = ValueAnimator.ofFloat(mTranslation, target); + mFlingAnimationUtils.apply(animator, mTranslation, target, vel); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mTranslation = (float) animation.getAnimatedValue(); + } + }); + animator.addListener(mFlingEndListener); + if (!snapBack) { + startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable, right); + mCallback.onAnimationToSideStarted(right, mTranslation, vel); + } else { + reset(true); + } + animator.start(); + mSwipeAnimator = animator; + if (snapBack) { + mCallback.onSwipingAborted(); + } + } + + private void startFinishingCircleAnimation(float velocity, Runnable animationEndRunnable, + boolean right) { + KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon; + targetView.finishAnimation(velocity, animationEndRunnable); + } + + private void setTranslation(float translation, boolean isReset, boolean animateReset) { + translation = rightSwipePossible() ? translation : Math.max(0, translation); + translation = leftSwipePossible() ? translation : Math.min(0, translation); + float absTranslation = Math.abs(translation); + if (translation != mTranslation || isReset) { + KeyguardAffordanceView targetView = translation > 0 ? mLeftIcon : mRightIcon; + KeyguardAffordanceView otherView = translation > 0 ? mRightIcon : mLeftIcon; + float alpha = absTranslation / getMinTranslationAmount(); + + // We interpolate the alpha of the other icons to 0 + float fadeOutAlpha = 1.0f - alpha; + fadeOutAlpha = Math.max(fadeOutAlpha, 0.0f); + + boolean animateIcons = isReset && animateReset; + boolean forceNoCircleAnimation = isReset && !animateReset; + float radius = getRadiusFromTranslation(absTranslation); + boolean slowAnimation = isReset && isBelowFalsingThreshold(); + if (!isReset) { + updateIcon(targetView, radius, alpha + fadeOutAlpha * targetView.getRestingAlpha(), + false, false, false, false); + } else { + updateIcon(targetView, 0.0f, fadeOutAlpha * targetView.getRestingAlpha(), + animateIcons, slowAnimation, true /* isReset */, forceNoCircleAnimation); + } + updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(), + animateIcons, slowAnimation, isReset, forceNoCircleAnimation); + + mTranslation = translation; + } + } + + private void updateIconsFromTranslation(KeyguardAffordanceView targetView) { + float absTranslation = Math.abs(mTranslation); + float alpha = absTranslation / getMinTranslationAmount(); + + // We interpolate the alpha of the other icons to 0 + float fadeOutAlpha = 1.0f - alpha; + fadeOutAlpha = Math.max(0.0f, fadeOutAlpha); + + // We interpolate the alpha of the targetView to 1 + KeyguardAffordanceView otherView = targetView == mRightIcon ? mLeftIcon : mRightIcon; + updateIconAlpha(targetView, alpha + fadeOutAlpha * targetView.getRestingAlpha(), false); + updateIconAlpha(otherView, fadeOutAlpha * otherView.getRestingAlpha(), false); + } + + private float getTranslationFromRadius(float circleSize) { + float translation = (circleSize - mMinBackgroundRadius) + / BACKGROUND_RADIUS_SCALE_FACTOR; + return translation > 0.0f ? translation + mTouchSlop : 0.0f; + } + + private float getRadiusFromTranslation(float translation) { + if (translation <= mTouchSlop) { + return 0.0f; + } + return (translation - mTouchSlop) * BACKGROUND_RADIUS_SCALE_FACTOR + mMinBackgroundRadius; + } + + public void animateHideLeftRightIcon() { + cancelAnimation(); + updateIcon(mRightIcon, 0f, 0f, true, false, false, false); + updateIcon(mLeftIcon, 0f, 0f, true, false, false, false); + } + + private void updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha, + boolean animate, boolean slowRadiusAnimation, boolean force, + boolean forceNoCircleAnimation) { + if (view.getVisibility() != View.VISIBLE && !force) { + return; + } + if (forceNoCircleAnimation) { + view.setCircleRadiusWithoutAnimation(circleRadius); + } else { + view.setCircleRadius(circleRadius, slowRadiusAnimation); + } + updateIconAlpha(view, alpha, animate); + } + + private void updateIconAlpha(KeyguardAffordanceView view, float alpha, boolean animate) { + float scale = getScale(alpha, view); + alpha = Math.min(1.0f, alpha); + view.setImageAlpha(alpha, animate); + view.setImageScale(scale, animate); + } + + private float getScale(float alpha, KeyguardAffordanceView icon) { + float scale = alpha / icon.getRestingAlpha() * 0.2f + + KeyguardAffordanceView.MIN_ICON_SCALE_AMOUNT; + return Math.min(scale, KeyguardAffordanceView.MAX_ICON_SCALE_AMOUNT); + } + + private void trackMovement(MotionEvent event) { + if (mVelocityTracker != null) { + mVelocityTracker.addMovement(event); + } + } + + private void initVelocityTracker() { + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + } + mVelocityTracker = VelocityTracker.obtain(); + } + + private float getCurrentVelocity(float lastX, float lastY) { + if (mVelocityTracker == null) { + return 0; + } + mVelocityTracker.computeCurrentVelocity(1000); + float aX = mVelocityTracker.getXVelocity(); + float aY = mVelocityTracker.getYVelocity(); + float bX = lastX - mInitialTouchX; + float bY = lastY - mInitialTouchY; + float bLen = (float) Math.hypot(bX, bY); + // Project the velocity onto the distance vector: a * b / |b| + float projectedVelocity = (aX * bX + aY * bY) / bLen; + if (mTargetedView == mRightIcon) { + projectedVelocity = -projectedVelocity; + } + return projectedVelocity; + } + + public void onConfigurationChanged() { + initDimens(); + initIcons(); + } + + public void onRtlPropertiesChanged() { + initIcons(); + } + + public void reset(boolean animate) { + cancelAnimation(); + setTranslation(0.0f, true /* isReset */, animate); + mMotionCancelled = true; + if (mSwipingInProgress) { + mCallback.onSwipingAborted(); + mSwipingInProgress = false; + } + } + + public boolean isSwipingInProgress() { + return mSwipingInProgress; + } + + public void launchAffordance(boolean animate, boolean left) { + if (mSwipingInProgress) { + // We don't want to mess with the state if the user is actually swiping already. + return; + } + KeyguardAffordanceView targetView = left ? mLeftIcon : mRightIcon; + KeyguardAffordanceView otherView = left ? mRightIcon : mLeftIcon; + startSwiping(targetView); + + // Do not animate the circle expanding if the affordance isn't visible, + // otherwise the circle will be meaningless. + if (targetView.getVisibility() != View.VISIBLE) { + animate = false; + } + + if (animate) { + fling(0, false, !left); + updateIcon(otherView, 0.0f, 0, true, false, true, false); + } else { + mCallback.onAnimationToSideStarted(!left, mTranslation, 0); + mTranslation = left ? mCallback.getMaxTranslationDistance() + : mCallback.getMaxTranslationDistance(); + updateIcon(otherView, 0.0f, 0.0f, false, false, true, false); + targetView.instantFinishAnimation(); + mFlingEndListener.onAnimationEnd(null); + mAnimationEndRunnable.run(); + } + } + + public interface Callback { + + /** + * Notifies the callback when an animation to a side page was started. + * + * @param rightPage Is the page animated to the right page? + */ + void onAnimationToSideStarted(boolean rightPage, float translation, float vel); + + /** + * Notifies the callback the animation to a side page has ended. + */ + void onAnimationToSideEnded(); + + float getMaxTranslationDistance(); + + void onSwipingStarted(boolean rightIcon); + + void onSwipingAborted(); + + void onIconClicked(boolean rightIcon); + + KeyguardAffordanceView getLeftIcon(); + + KeyguardAffordanceView getRightIcon(); + + View getLeftPreview(); + + View getRightPreview(); + + /** + * @return The factor the minimum swipe amount should be multiplied with. + */ + float getAffordanceFalsingFactor(); + + boolean needsAntiFalsing(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 61113a05af164..93b2e41e595b6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -16,30 +16,47 @@ package com.android.systemui.statusbar.phone; +import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; +import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; + import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; +import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON; +import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK; +import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON; +import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK; import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE; import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE; +import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; import android.service.quickaccesswallet.GetWalletCardsError; import android.service.quickaccesswallet.GetWalletCardsResponse; import android.service.quickaccesswallet.QuickAccessWalletClient; +import android.telecom.TelecomManager; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -47,35 +64,81 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.Utils; +import com.android.systemui.ActivityIntentHelper; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.Interpolators; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.camera.CameraIntents; +import com.android.systemui.controls.ControlsServiceInfo; import com.android.systemui.controls.dagger.ControlsComponent; import com.android.systemui.controls.management.ControlsListingController; import com.android.systemui.controls.ui.ControlsActivity; import com.android.systemui.controls.ui.ControlsUiController; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.plugins.IntentButtonProvider; +import com.android.systemui.plugins.IntentButtonProvider.IntentButton; +import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState; import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; +import com.android.systemui.statusbar.KeyguardAffordanceView; +import com.android.systemui.statusbar.policy.AccessibilityController; +import com.android.systemui.statusbar.policy.ExtensionController; +import com.android.systemui.statusbar.policy.ExtensionController.Extension; +import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.policy.PreviewInflater; +import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory; +import com.android.systemui.tuner.TunerService; import com.android.systemui.wallet.controller.QuickAccessWalletController; +import java.util.List; + /** * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status * text. */ -public class KeyguardBottomAreaView extends FrameLayout { +public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener, + KeyguardStateController.Callback, + AccessibilityController.AccessibilityStateChangedCallback { - private static final String TAG = "CentralSurfaces/KeyguardBottomAreaView"; + final static String TAG = "CentralSurfaces/KeyguardBottomAreaView"; + + public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance"; + public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture"; + public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap"; + public static final String CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = "lift_to_launch_ml"; + + public static final String EXTRA_CAMERA_LAUNCH_SOURCE + = "com.android.systemui.camera_launch_source"; + + private static final String LEFT_BUTTON_PLUGIN + = "com.android.systemui.action.PLUGIN_LOCKSCREEN_LEFT_BUTTON"; + private static final String RIGHT_BUTTON_PLUGIN + = "com.android.systemui.action.PLUGIN_LOCKSCREEN_RIGHT_BUTTON"; + + private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL); + private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; + // TODO(b/179494051): May no longer be needed + private final boolean mShowLeftAffordance; + private final boolean mShowCameraAffordance; + + private KeyguardAffordanceView mRightAffordanceView; + private KeyguardAffordanceView mLeftAffordanceView; + private ImageView mWalletButton; private ImageView mQRCodeScannerButton; private ImageView mControlsButton; private boolean mHasCard = false; - private final WalletCardRetriever mCardRetriever = new WalletCardRetriever(); + private WalletCardRetriever mCardRetriever = new WalletCardRetriever(); private QuickAccessWalletController mQuickAccessWalletController; private QRCodeScannerController mQRCodeScannerController; private ControlsComponent mControlsComponent; @@ -85,42 +148,54 @@ public class KeyguardBottomAreaView extends FrameLayout { private ViewGroup mIndicationArea; private TextView mIndicationText; private TextView mIndicationTextBottom; + private ViewGroup mPreviewContainer; private ViewGroup mOverlayContainer; + private View mLeftPreview; + private View mCameraPreview; + private ActivityStarter mActivityStarter; private KeyguardStateController mKeyguardStateController; + private FlashlightController mFlashlightController; + private PreviewInflater mPreviewInflater; + private AccessibilityController mAccessibilityController; private CentralSurfaces mCentralSurfaces; + private KeyguardAffordanceHelper mAffordanceHelper; private FalsingManager mFalsingManager; + private boolean mUserSetupComplete; + private boolean mLeftIsVoiceAssist; + private Drawable mLeftAssistIcon; + + private IntentButton mRightButton = new DefaultRightButton(); + private Extension mRightExtension; + private String mRightButtonStr; + private IntentButton mLeftButton = new DefaultLeftButton(); + private Extension mLeftExtension; + private String mLeftButtonStr; private boolean mDozing; private int mIndicationBottomMargin; private int mIndicationPadding; private float mDarkAmount; private int mBurnInXOffset; private int mBurnInYOffset; + private ActivityIntentHelper mActivityIntentHelper; + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final ControlsListingController.ControlsListingCallback mListingCallback = - serviceInfos -> post(() -> { - boolean available = !serviceInfos.isEmpty(); + private ControlsListingController.ControlsListingCallback mListingCallback = + new ControlsListingController.ControlsListingCallback() { + public void onServicesUpdated(List serviceInfos) { + post(() -> { + boolean available = !serviceInfos.isEmpty(); - if (available != mControlServicesAvailable) { - mControlServicesAvailable = available; - updateControlsVisibility(); - updateAffordanceColors(); + if (available != mControlServicesAvailable) { + mControlServicesAvailable = available; + updateControlsVisibility(); + updateAffordanceColors(); + } + }); } - }); - - private final KeyguardStateController.Callback mKeyguardStateCallback = - new KeyguardStateController.Callback() { - @Override - public void onKeyguardShowingChanged() { - if (mKeyguardStateController.isShowing()) { - if (mQuickAccessWalletController != null) { - mQuickAccessWalletController.queryWalletCards(mCardRetriever); - } - } - } - }; + }; public KeyguardBottomAreaView(Context context) { this(context, null); @@ -137,8 +212,43 @@ public class KeyguardBottomAreaView extends FrameLayout { public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + mShowLeftAffordance = getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance); + mShowCameraAffordance = getResources() + .getBoolean(R.bool.config_keyguardShowCameraAffordance); } + private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() { + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + String label = null; + if (host == mRightAffordanceView) { + label = getResources().getString(R.string.camera_label); + } else if (host == mLeftAffordanceView) { + if (mLeftIsVoiceAssist) { + label = getResources().getString(R.string.voice_assist_label); + } else { + label = getResources().getString(R.string.phone_label); + } + } + info.addAction(new AccessibilityAction(ACTION_CLICK, label)); + } + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (action == ACTION_CLICK) { + if (host == mRightAffordanceView) { + launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE); + return true; + } else if (host == mLeftAffordanceView) { + launchLeftAffordance(); + return true; + } + } + return super.performAccessibilityAction(host, action, args); + } + }; + public void initFrom(KeyguardBottomAreaView oldBottomArea) { setCentralSurfaces(oldBottomArea.mCentralSurfaces); @@ -169,7 +279,11 @@ public class KeyguardBottomAreaView extends FrameLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); + mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext), + new ActivityIntentHelper(mContext)); mOverlayContainer = findViewById(R.id.overlay_container); + mRightAffordanceView = findViewById(R.id.camera_button); + mLeftAffordanceView = findViewById(R.id.left_button); mWalletButton = findViewById(R.id.wallet_button); mQRCodeScannerButton = findViewById(R.id.qr_code_scanner_button); mControlsButton = findViewById(R.id.controls_button); @@ -181,11 +295,18 @@ public class KeyguardBottomAreaView extends FrameLayout { R.dimen.keyguard_indication_margin_bottom); mBurnInYOffset = getResources().getDimensionPixelSize( R.dimen.default_burn_in_prevention_offset); + updateCameraVisibility(); mKeyguardStateController = Dependency.get(KeyguardStateController.class); - mKeyguardStateController.addCallback(mKeyguardStateCallback); + mKeyguardStateController.addCallback(this); setClipChildren(false); setClipToPadding(false); + mRightAffordanceView.setOnClickListener(this); + mLeftAffordanceView.setOnClickListener(this); + initAccessibility(); mActivityStarter = Dependency.get(ActivityStarter.class); + mFlashlightController = Dependency.get(FlashlightController.class); + mAccessibilityController = Dependency.get(AccessibilityController.class); + mActivityIntentHelper = new ActivityIntentHelper(getContext()); mIndicationPadding = getResources().getDimensionPixelSize( R.dimen.keyguard_indication_area_padding); @@ -194,18 +315,51 @@ public class KeyguardBottomAreaView extends FrameLayout { updateControlsVisibility(); } + /** + * Set the container where the previews are rendered. + */ + public void setPreviewContainer(ViewGroup previewContainer) { + mPreviewContainer = previewContainer; + inflateCameraPreview(); + updateLeftAffordance(); + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + mAccessibilityController.addStateChangedCallback(this); + mRightExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class) + .withPlugin(IntentButtonProvider.class, RIGHT_BUTTON_PLUGIN, + p -> p.getIntentButton()) + .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_RIGHT_BUTTON)) + .withDefault(() -> new DefaultRightButton()) + .withCallback(button -> setRightButton(button)) + .build(); + mLeftExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class) + .withPlugin(IntentButtonProvider.class, LEFT_BUTTON_PLUGIN, + p -> p.getIntentButton()) + .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_LEFT_BUTTON)) + .withDefault(() -> new DefaultLeftButton()) + .withCallback(button -> setLeftButton(button)) + .build(); final IntentFilter filter = new IntentFilter(); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); - mKeyguardStateController.addCallback(mKeyguardStateCallback); + getContext().registerReceiverAsUser(mDevicePolicyReceiver, + UserHandle.ALL, filter, null, null); + mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class); + mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback); + mKeyguardStateController.addCallback(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - mKeyguardStateController.removeCallback(mKeyguardStateCallback); + mKeyguardStateController.removeCallback(this); + mAccessibilityController.removeStateChangedCallback(this); + mRightExtension.destroy(); + mLeftExtension.destroy(); + getContext().unregisterReceiver(mDevicePolicyReceiver); + mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback); if (mQuickAccessWalletController != null) { mQuickAccessWalletController.unregisterWalletChangeObservers( @@ -224,6 +378,11 @@ public class KeyguardBottomAreaView extends FrameLayout { } } + private void initAccessibility() { + mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate); + mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate); + } + @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -245,7 +404,19 @@ public class KeyguardBottomAreaView extends FrameLayout { getResources().getDimensionPixelSize( com.android.internal.R.dimen.text_size_small_material)); - ViewGroup.LayoutParams lp = mWalletButton.getLayoutParams(); + ViewGroup.LayoutParams lp = mRightAffordanceView.getLayoutParams(); + lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width); + lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height); + mRightAffordanceView.setLayoutParams(lp); + updateRightAffordanceIcon(); + + lp = mLeftAffordanceView.getLayoutParams(); + lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width); + lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height); + mLeftAffordanceView.setLayoutParams(lp); + updateLeftAffordanceIcon(); + + lp = mWalletButton.getLayoutParams(); lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width); lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height); mWalletButton.setLayoutParams(lp); @@ -268,8 +439,74 @@ public class KeyguardBottomAreaView extends FrameLayout { updateAffordanceColors(); } + private void updateRightAffordanceIcon() { + IconState state = mRightButton.getIcon(); + mRightAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE); + if (state.drawable != mRightAffordanceView.getDrawable() + || state.tint != mRightAffordanceView.shouldTint()) { + mRightAffordanceView.setImageDrawable(state.drawable, state.tint); + } + mRightAffordanceView.setContentDescription(state.contentDescription); + } + public void setCentralSurfaces(CentralSurfaces centralSurfaces) { mCentralSurfaces = centralSurfaces; + updateCameraVisibility(); // in case onFinishInflate() was called too early + } + + public void setAffordanceHelper(KeyguardAffordanceHelper affordanceHelper) { + mAffordanceHelper = affordanceHelper; + } + + public void setUserSetupComplete(boolean userSetupComplete) { + mUserSetupComplete = userSetupComplete; + updateCameraVisibility(); + updateLeftAffordanceIcon(); + } + + private Intent getCameraIntent() { + return mRightButton.getIntent(); + } + + /** + * Resolves the intent to launch the camera application. + */ + public ResolveInfo resolveCameraIntent() { + return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(), + PackageManager.MATCH_DEFAULT_ONLY, + KeyguardUpdateMonitor.getCurrentUser()); + } + + private void updateCameraVisibility() { + if (mRightAffordanceView == null) { + // Things are not set up yet; reply hazy, ask again later + return; + } + mRightAffordanceView.setVisibility(!mDozing && mShowCameraAffordance + && mRightButton.getIcon().isVisible ? View.VISIBLE : View.GONE); + } + + /** + * Set an alternate icon for the left assist affordance (replace the mic icon) + */ + public void setLeftAssistIcon(Drawable drawable) { + mLeftAssistIcon = drawable; + updateLeftAffordanceIcon(); + } + + private void updateLeftAffordanceIcon() { + if (!mShowLeftAffordance || mDozing) { + mLeftAffordanceView.setVisibility(GONE); + return; + } + + IconState state = mLeftButton.getIcon(); + mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE); + if (state.drawable != mLeftAffordanceView.getDrawable() + || state.tint != mLeftAffordanceView.shouldTint()) { + mLeftAffordanceView.setImageDrawable(state.drawable, state.tint); + } + mLeftAffordanceView.setContentDescription(state.contentDescription); } private void updateWalletVisibility() { @@ -315,6 +552,73 @@ public class KeyguardBottomAreaView extends FrameLayout { } } + public boolean isLeftVoiceAssist() { + return mLeftIsVoiceAssist; + } + + private boolean isPhoneVisible() { + PackageManager pm = mContext.getPackageManager(); + return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) + && pm.resolveActivity(PHONE_INTENT, 0) != null; + } + + @Override + public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) { + mRightAffordanceView.setClickable(touchExplorationEnabled); + mLeftAffordanceView.setClickable(touchExplorationEnabled); + mRightAffordanceView.setFocusable(accessibilityEnabled); + mLeftAffordanceView.setFocusable(accessibilityEnabled); + } + + @Override + public void onClick(View v) { + if (v == mRightAffordanceView) { + launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE); + } else if (v == mLeftAffordanceView) { + launchLeftAffordance(); + } + } + + public void launchCamera(String source) { + final Intent intent = getCameraIntent(); + intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source); + boolean wouldLaunchResolverActivity = mActivityIntentHelper.wouldLaunchResolverActivity( + intent, KeyguardUpdateMonitor.getCurrentUser()); + if (CameraIntents.isSecureCameraIntent(intent) && !wouldLaunchResolverActivity) { + AsyncTask.execute(new Runnable() { + @Override + public void run() { + // Normally an activity will set it's requested rotation + // animation on its window. However when launching an activity + // causes the orientation to change this is too late. In these cases + // the default animation is used. This doesn't look good for + // the camera (as it rotates the camera contents out of sync + // with physical reality). So, we ask the WindowManager to + // force the crossfade animation if an orientation change + // happens to occur during the launch. + ActivityOptions o = ActivityOptions.makeBasic(); + o.setDisallowEnterPictureInPictureWhileLaunching(true); + o.setRotationAnimationHint( + WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); + try { + ActivityTaskManager.getService().startActivityAsUser( + null, getContext().getBasePackageName(), + getContext().getAttributionTag(), intent, + intent.resolveTypeIfNeeded(getContext().getContentResolver()), + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, o.toBundle(), + UserHandle.CURRENT.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, "Unable to start camera activity", e); + } + } + }); + } else { + // We need to delay starting the activity because ResolverActivity finishes itself if + // launched behind lockscreen. + mActivityStarter.startActivity(intent, false /* dismissShade */); + } + } + public void setDarkAmount(float darkAmount) { if (darkAmount == mDarkAmount) { return; @@ -323,6 +627,77 @@ public class KeyguardBottomAreaView extends FrameLayout { dozeTimeTick(); } + public void launchLeftAffordance() { + if (mLeftIsVoiceAssist) { + launchVoiceAssist(); + } else { + launchPhone(); + } + } + + @VisibleForTesting + void launchVoiceAssist() { + Runnable runnable = new Runnable() { + @Override + public void run() { + Dependency.get(AssistManager.class).launchVoiceAssistFromKeyguard(); + } + }; + if (!mKeyguardStateController.canDismissLockScreen()) { + Dependency.get(Dependency.BACKGROUND_EXECUTOR).execute(runnable); + } else { + boolean dismissShade = !TextUtils.isEmpty(mRightButtonStr) + && Dependency.get(TunerService.class).getValue(LOCKSCREEN_RIGHT_UNLOCK, 1) != 0; + mCentralSurfaces.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */, + dismissShade, false /* afterKeyguardGone */, true /* deferred */); + } + } + + private boolean canLaunchVoiceAssist() { + return Dependency.get(AssistManager.class).canVoiceAssistBeLaunchedFromKeyguard(); + } + + private void launchPhone() { + final TelecomManager tm = TelecomManager.from(mContext); + if (tm.isInCall()) { + AsyncTask.execute(new Runnable() { + @Override + public void run() { + tm.showInCallScreen(false /* showDialpad */); + } + }); + } else { + boolean dismissShade = !TextUtils.isEmpty(mLeftButtonStr) + && Dependency.get(TunerService.class).getValue(LOCKSCREEN_LEFT_UNLOCK, 1) != 0; + mActivityStarter.startActivity(mLeftButton.getIntent(), dismissShade); + } + } + + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + if (changedView == this && visibility == VISIBLE) { + updateCameraVisibility(); + } + } + + public KeyguardAffordanceView getLeftView() { + return mLeftAffordanceView; + } + + public KeyguardAffordanceView getRightView() { + return mRightAffordanceView; + } + + public View getLeftPreview() { + return mLeftPreview; + } + + public View getRightPreview() { + return mCameraPreview; + } + public View getIndicationArea() { return mIndicationArea; } @@ -332,6 +707,66 @@ public class KeyguardBottomAreaView extends FrameLayout { return false; } + @Override + public void onUnlockedChanged() { + updateCameraVisibility(); + } + + @Override + public void onKeyguardShowingChanged() { + if (mKeyguardStateController.isShowing()) { + if (mQuickAccessWalletController != null) { + mQuickAccessWalletController.queryWalletCards(mCardRetriever); + } + } + } + + private void inflateCameraPreview() { + if (mPreviewContainer == null) { + return; + } + View previewBefore = mCameraPreview; + boolean visibleBefore = false; + if (previewBefore != null) { + mPreviewContainer.removeView(previewBefore); + visibleBefore = previewBefore.getVisibility() == View.VISIBLE; + } + mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent()); + if (mCameraPreview != null) { + mPreviewContainer.addView(mCameraPreview); + mCameraPreview.setVisibility(visibleBefore ? View.VISIBLE : View.INVISIBLE); + } + if (mAffordanceHelper != null) { + mAffordanceHelper.updatePreviews(); + } + } + + private void updateLeftPreview() { + if (mPreviewContainer == null) { + return; + } + View previewBefore = mLeftPreview; + if (previewBefore != null) { + mPreviewContainer.removeView(previewBefore); + } + + if (mLeftIsVoiceAssist) { + if (Dependency.get(AssistManager.class).getVoiceInteractorComponentName() != null) { + mLeftPreview = mPreviewInflater.inflatePreviewFromService( + Dependency.get(AssistManager.class).getVoiceInteractorComponentName()); + } + } else { + mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent()); + } + if (mLeftPreview != null) { + mPreviewContainer.addView(mLeftPreview); + mLeftPreview.setVisibility(View.INVISIBLE); + } + if (mAffordanceHelper != null) { + mAffordanceHelper.updatePreviews(); + } + } + public void startFinishDozeAnimation() { long delay = 0; if (mWalletButton.getVisibility() == View.VISIBLE) { @@ -343,6 +778,13 @@ public class KeyguardBottomAreaView extends FrameLayout { if (mControlsButton.getVisibility() == View.VISIBLE) { startFinishDozeAnimationElement(mControlsButton, delay); } + if (mLeftAffordanceView.getVisibility() == View.VISIBLE) { + startFinishDozeAnimationElement(mLeftAffordanceView, delay); + delay += DOZE_ANIMATION_STAGGER_DELAY; + } + if (mRightAffordanceView.getVisibility() == View.VISIBLE) { + startFinishDozeAnimationElement(mRightAffordanceView, delay); + } } private void startFinishDozeAnimationElement(View element, long delay) { @@ -356,9 +798,58 @@ public class KeyguardBottomAreaView extends FrameLayout { .setDuration(DOZE_ANIMATION_ELEMENT_DURATION); } + private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + post(new Runnable() { + @Override + public void run() { + updateCameraVisibility(); + } + }); + } + }; + + private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = + new KeyguardUpdateMonitorCallback() { + @Override + public void onUserSwitchComplete(int userId) { + updateCameraVisibility(); + } + + @Override + public void onUserUnlocked() { + inflateCameraPreview(); + updateCameraVisibility(); + updateLeftAffordance(); + } + }; + + public void updateLeftAffordance() { + updateLeftAffordanceIcon(); + updateLeftPreview(); + } + + private void setRightButton(IntentButton button) { + mRightButton = button; + updateRightAffordanceIcon(); + updateCameraVisibility(); + inflateCameraPreview(); + } + + private void setLeftButton(IntentButton button) { + mLeftButton = button; + if (!(mLeftButton instanceof DefaultLeftButton)) { + mLeftIsVoiceAssist = false; + } + updateLeftAffordance(); + } + public void setDozing(boolean dozing, boolean animate) { mDozing = dozing; + updateCameraVisibility(); + updateLeftAffordanceIcon(); updateWalletVisibility(); updateControlsVisibility(); updateQRCodeButtonVisibility(); @@ -397,12 +888,77 @@ public class KeyguardBottomAreaView extends FrameLayout { * Sets the alpha of the indication areas and affordances, excluding the lock icon. */ public void setAffordanceAlpha(float alpha) { + mLeftAffordanceView.setAlpha(alpha); + mRightAffordanceView.setAlpha(alpha); mIndicationArea.setAlpha(alpha); mWalletButton.setAlpha(alpha); mQRCodeScannerButton.setAlpha(alpha); mControlsButton.setAlpha(alpha); } + private class DefaultLeftButton implements IntentButton { + + private IconState mIconState = new IconState(); + + @Override + public IconState getIcon() { + mLeftIsVoiceAssist = canLaunchVoiceAssist(); + if (mLeftIsVoiceAssist) { + mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance; + if (mLeftAssistIcon == null) { + mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp); + } else { + mIconState.drawable = mLeftAssistIcon; + } + mIconState.contentDescription = mContext.getString( + R.string.accessibility_voice_assist_button); + } else { + mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance + && isPhoneVisible(); + mIconState.drawable = mContext.getDrawable( + com.android.internal.R.drawable.ic_phone); + mIconState.contentDescription = mContext.getString( + R.string.accessibility_phone_button); + } + return mIconState; + } + + @Override + public Intent getIntent() { + return PHONE_INTENT; + } + } + + private class DefaultRightButton implements IntentButton { + + private IconState mIconState = new IconState(); + + @Override + public IconState getIcon() { + boolean isCameraDisabled = (mCentralSurfaces != null) + && !mCentralSurfaces.isCameraAllowedByAdmin(); + mIconState.isVisible = !isCameraDisabled + && mShowCameraAffordance + && mUserSetupComplete + && resolveCameraIntent() != null; + mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp); + mIconState.contentDescription = + mContext.getString(R.string.accessibility_camera_button); + return mIconState; + } + + @Override + public Intent getIntent() { + boolean canDismissLs = mKeyguardStateController.canDismissLockScreen(); + boolean secure = mKeyguardStateController.isMethodSecure(); + if (secure && !canDismissLs) { + return CameraIntents.getSecureCameraIntent(getContext()); + } else { + return CameraIntents.getInsecureCameraIntent(getContext()); + } + } + } + @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { int bottom = insets.getDisplayCutout() != null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index c757cba319672..fbbb587872b45 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -50,6 +50,8 @@ import android.app.ActivityManager; import android.app.Fragment; import android.app.StatusBarManager; import android.content.ContentResolver; +import android.content.pm.ResolveInfo; +import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Canvas; @@ -143,6 +145,7 @@ import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.GestureRecorder; +import com.android.systemui.statusbar.KeyguardAffordanceView; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -249,6 +252,9 @@ public class NotificationPanelViewController extends PanelViewController { private final OnOverscrollTopChangedListener mOnOverscrollTopChangedListener = new OnOverscrollTopChangedListener(); + private final KeyguardAffordanceHelperCallback + mKeyguardAffordanceHelperCallback = + new KeyguardAffordanceHelperCallback(); private final OnEmptySpaceClickListener mOnEmptySpaceClickListener = new OnEmptySpaceClickListener(); @@ -332,6 +338,8 @@ public class NotificationPanelViewController extends PanelViewController { // Current max allowed keyguard notifications determined by measuring the panel private int mMaxAllowedKeyguardNotifications; + private ViewGroup mPreviewContainer; + private KeyguardAffordanceHelper mAffordanceHelper; private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController; private KeyguardUserSwitcherController mKeyguardUserSwitcherController; private KeyguardStatusBarView mKeyguardStatusBar; @@ -429,6 +437,8 @@ public class NotificationPanelViewController extends PanelViewController { */ private boolean mQsAnimatorExpand; private boolean mIsLaunchTransitionFinished; + private boolean mIsLaunchTransitionRunning; + private Runnable mLaunchAnimationEndRunnable; private boolean mOnlyAffordanceInThisMotion; private ValueAnimator mQsSizeChangeAnimator; @@ -445,8 +455,10 @@ public class NotificationPanelViewController extends PanelViewController { private boolean mClosingWithAlphaFadeOut; private boolean mHeadsUpAnimatingAway; private boolean mLaunchingAffordance; + private boolean mAffordanceHasPreview; private final FalsingManager mFalsingManager; private final FalsingCollector mFalsingCollector; + private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE; private Runnable mHeadsUpExistenceChangedRunnable = () -> { setHeadsUpAnimatingAway(false); @@ -479,6 +491,7 @@ public class NotificationPanelViewController extends PanelViewController { private float mLinearDarkAmount; private boolean mPulsing; + private boolean mUserSetupComplete; private boolean mHideIconsDuringLaunchAnimation = true; private int mStackScrollerMeasuringPass; /** @@ -995,6 +1008,8 @@ public class NotificationPanelViewController extends PanelViewController { mOnEmptySpaceClickListener); addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp); mKeyguardBottomArea = mView.findViewById(R.id.keyguard_bottom_area); + mPreviewContainer = mView.findViewById(R.id.preview_container); + mKeyguardBottomArea.setPreviewContainer(mPreviewContainer); initBottomArea(); @@ -1018,6 +1033,7 @@ public class NotificationPanelViewController extends PanelViewController { mView.setRtlChangeListener(layoutDirection -> { if (layoutDirection != mOldLayoutDirection) { + mAffordanceHelper.onRtlPropertiesChanged(); mOldLayoutDirection = layoutDirection; } }); @@ -1251,6 +1267,7 @@ public class NotificationPanelViewController extends PanelViewController { mKeyguardBottomArea = (KeyguardBottomAreaView) mLayoutInflater.inflate( R.layout.keyguard_bottom_area, mView, false); mKeyguardBottomArea.initFrom(oldBottomArea); + mKeyguardBottomArea.setPreviewContainer(mPreviewContainer); mView.addView(mKeyguardBottomArea, index); initBottomArea(); mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea); @@ -1287,7 +1304,11 @@ public class NotificationPanelViewController extends PanelViewController { } private void initBottomArea() { + mAffordanceHelper = new KeyguardAffordanceHelper( + mKeyguardAffordanceHelperCallback, mView.getContext(), mFalsingManager); + mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper); mKeyguardBottomArea.setCentralSurfaces(mCentralSurfaces); + mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete); mKeyguardBottomArea.setFalsingManager(mFalsingManager); mKeyguardBottomArea.initWallet(mQuickAccessWalletController); mKeyguardBottomArea.initControls(mControlsComponent); @@ -1652,6 +1673,10 @@ public class NotificationPanelViewController extends PanelViewController { public void resetViews(boolean animate) { mIsLaunchTransitionFinished = false; mBlockTouches = false; + if (!mLaunchingAffordance) { + mAffordanceHelper.reset(false); + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE; + } mCentralSurfaces.getGutsManager().closeAndSaveGuts(true /* leavebehind */, true /* force */, true /* controls */, -1 /* x */, -1 /* y */, true /* resetMenu */); if (animate && !isFullyCollapsed()) { @@ -2194,6 +2219,11 @@ public class NotificationPanelViewController extends PanelViewController { return isFullyCollapsed() || mBarState != StatusBarState.SHADE; } + @Override + protected boolean shouldGestureIgnoreXTouchSlop(float x, float y) { + return !mAffordanceHelper.isOnAffordanceIcon(x, y); + } + private void onQsTouch(MotionEvent event) { int pointerIndex = event.findPointerIndex(mTrackingPointer); if (pointerIndex < 0) { @@ -3358,6 +3388,9 @@ public class NotificationPanelViewController extends PanelViewController { mQsExpandImmediate = true; setShowShelfOnly(true); } + if (mBarState == KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) { + mAffordanceHelper.animateHideLeftRightIcon(); + } mNotificationStackScrollLayoutController.onPanelTrackingStarted(); cancelPendingPanelCollapse(); } @@ -3371,6 +3404,12 @@ public class NotificationPanelViewController extends PanelViewController { true /* animate */); } mNotificationStackScrollLayoutController.onPanelTrackingStopped(); + if (expand && (mBarState == KEYGUARD + || mBarState == StatusBarState.SHADE_LOCKED)) { + if (!mHintAnimationRunning) { + mAffordanceHelper.reset(true); + } + } // If we unlocked from a swipe, the user's finger might still be down after the // unlock animation ends. We need to wait until ACTION_UP to enable blurs again. @@ -3443,6 +3482,10 @@ public class NotificationPanelViewController extends PanelViewController { return mIsLaunchTransitionFinished; } + public boolean isLaunchTransitionRunning() { + return mIsLaunchTransitionRunning; + } + @Override public void setIsLaunchAnimationRunning(boolean running) { boolean wasRunning = mIsLaunchAnimationRunning; @@ -3461,6 +3504,10 @@ public class NotificationPanelViewController extends PanelViewController { } } + public void setLaunchTransitionEndRunnable(Runnable r) { + mLaunchAnimationEndRunnable = r; + } + private void updateDozingVisibilities(boolean animate) { mKeyguardBottomArea.setDozing(mDozing, animate); if (!mDozing && animate) { @@ -3639,8 +3686,30 @@ public class NotificationPanelViewController extends PanelViewController { && mBarState == StatusBarState.SHADE; } - /** Launches the camera. */ - public void launchCamera(int source) { + public void launchCamera(boolean animate, int source) { + if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) { + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP; + } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) { + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE; + } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER) { + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER; + } else { + + // Default. + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE; + } + + // If we are launching it when we are occluded already we don't want it to animate, + // nor setting these flags, since the occluded state doesn't change anymore, hence it's + // never reset. + if (!isFullyCollapsed()) { + setLaunchingAffordance(true); + } else { + animate = false; + } + mAffordanceHasPreview = mKeyguardBottomArea.getRightPreview() != null; + mAffordanceHelper.launchAffordance( + animate, mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); } public void onAffordanceLaunchEnded() { @@ -3653,6 +3722,9 @@ public class NotificationPanelViewController extends PanelViewController { */ private void setLaunchingAffordance(boolean launchingAffordance) { mLaunchingAffordance = launchingAffordance; + mKeyguardAffordanceHelperCallback.getLeftIcon().setLaunchingAffordance(launchingAffordance); + mKeyguardAffordanceHelperCallback.getRightIcon().setLaunchingAffordance( + launchingAffordance); mKeyguardBypassController.setLaunchingAffordance(launchingAffordance); } @@ -3660,14 +3732,24 @@ public class NotificationPanelViewController extends PanelViewController { * Return true when a bottom affordance is launching an occluded activity with a splash screen. */ public boolean isLaunchingAffordanceWithPreview() { - return mLaunchingAffordance; + return mLaunchingAffordance && mAffordanceHasPreview; } /** * Whether the camera application can be launched for the camera launch gesture. */ public boolean canCameraGestureBeLaunched() { - return false; + if (!mCentralSurfaces.isCameraAllowedByAdmin()) { + return false; + } + + ResolveInfo resolveInfo = mKeyguardBottomArea.resolveCameraIntent(); + String + packageToLaunch = + (resolveInfo == null || resolveInfo.activityInfo == null) ? null + : resolveInfo.activityInfo.packageName; + return packageToLaunch != null && (mBarState != StatusBarState.SHADE || !isForegroundApp( + packageToLaunch)) && !mAffordanceHelper.isSwipingInProgress(); } /** @@ -3756,6 +3838,9 @@ public class NotificationPanelViewController extends PanelViewController { @Override public void setTouchAndAnimationDisabled(boolean disabled) { super.setTouchAndAnimationDisabled(disabled); + if (disabled && mAffordanceHelper.isSwipingInProgress() && !mIsLaunchTransitionRunning) { + mAffordanceHelper.reset(false /* animate */); + } mNotificationStackScrollLayoutController.setAnimationsEnabled(!disabled); } @@ -3838,6 +3923,11 @@ public class NotificationPanelViewController extends PanelViewController { return mKeyguardBottomArea; } + public void setUserSetupComplete(boolean userSetupComplete) { + mUserSetupComplete = userSetupComplete; + mKeyguardBottomArea.setUserSetupComplete(userSetupComplete); + } + public void applyLaunchAnimationProgress(float linearProgress) { boolean hideIcons = LaunchAnimator.getProgress(ActivityLaunchAnimator.TIMINGS, linearProgress, ANIMATION_DELAY_ICON_FADE_IN, 100) == 0.0f; @@ -4191,6 +4281,10 @@ public class NotificationPanelViewController extends PanelViewController { mMetricsLogger.count(COUNTER_PANEL_OPEN_PEEK, 1); } boolean handled = false; + if ((!mIsExpanding || mHintAnimationRunning) && !mQsExpanded + && mBarState != StatusBarState.SHADE && !mDozing) { + handled |= mAffordanceHelper.onTouchEvent(event); + } if (mOnlyAffordanceInThisMotion) { return true; } @@ -4433,6 +4527,139 @@ public class NotificationPanelViewController extends PanelViewController { } } + private class KeyguardAffordanceHelperCallback implements KeyguardAffordanceHelper.Callback { + @Override + public void onAnimationToSideStarted(boolean rightPage, float translation, float vel) { + boolean + start = + mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? rightPage + : !rightPage; + mIsLaunchTransitionRunning = true; + mLaunchAnimationEndRunnable = null; + float displayDensity = mCentralSurfaces.getDisplayDensity(); + int lengthDp = Math.abs((int) (translation / displayDensity)); + int velocityDp = Math.abs((int) (vel / displayDensity)); + if (start) { + mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_DIALER, lengthDp, velocityDp); + mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_DIALER); + mFalsingCollector.onLeftAffordanceOn(); + if (mFalsingCollector.shouldEnforceBouncer()) { + mCentralSurfaces.executeRunnableDismissingKeyguard( + () -> mKeyguardBottomArea.launchLeftAffordance(), null, + true /* dismissShade */, false /* afterKeyguardGone */, + true /* deferred */); + } else { + mKeyguardBottomArea.launchLeftAffordance(); + } + } else { + if (KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE.equals( + mLastCameraLaunchSource)) { + mLockscreenGestureLogger.write( + MetricsEvent.ACTION_LS_CAMERA, lengthDp, velocityDp); + mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_CAMERA); + } + mFalsingCollector.onCameraOn(); + if (mFalsingCollector.shouldEnforceBouncer()) { + mCentralSurfaces.executeRunnableDismissingKeyguard( + () -> mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource), null, + true /* dismissShade */, false /* afterKeyguardGone */, + true /* deferred */); + } else { + mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource); + } + } + mCentralSurfaces.startLaunchTransitionTimeout(); + mBlockTouches = true; + } + + @Override + public void onAnimationToSideEnded() { + mIsLaunchTransitionRunning = false; + mIsLaunchTransitionFinished = true; + if (mLaunchAnimationEndRunnable != null) { + mLaunchAnimationEndRunnable.run(); + mLaunchAnimationEndRunnable = null; + } + mCentralSurfaces.readyForKeyguardDone(); + } + + @Override + public float getMaxTranslationDistance() { + return (float) Math.hypot(mView.getWidth(), getHeight()); + } + + @Override + public void onSwipingStarted(boolean rightIcon) { + mFalsingCollector.onAffordanceSwipingStarted(rightIcon); + mView.requestDisallowInterceptTouchEvent(true); + mOnlyAffordanceInThisMotion = true; + mQsTracking = false; + } + + @Override + public void onSwipingAborted() { + mFalsingCollector.onAffordanceSwipingAborted(); + } + + @Override + public void onIconClicked(boolean rightIcon) { + if (mHintAnimationRunning) { + return; + } + mHintAnimationRunning = true; + mAffordanceHelper.startHintAnimation(rightIcon, () -> { + mHintAnimationRunning = false; + mCentralSurfaces.onHintFinished(); + }); + rightIcon = + mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? !rightIcon + : rightIcon; + if (rightIcon) { + mCentralSurfaces.onCameraHintStarted(); + } else { + if (mKeyguardBottomArea.isLeftVoiceAssist()) { + mCentralSurfaces.onVoiceAssistHintStarted(); + } else { + mCentralSurfaces.onPhoneHintStarted(); + } + } + } + + @Override + public KeyguardAffordanceView getLeftIcon() { + return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getRightView() : mKeyguardBottomArea.getLeftView(); + } + + @Override + public KeyguardAffordanceView getRightIcon() { + return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getLeftView() : mKeyguardBottomArea.getRightView(); + } + + @Override + public View getLeftPreview() { + return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getRightPreview() : mKeyguardBottomArea.getLeftPreview(); + } + + @Override + public View getRightPreview() { + return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getLeftPreview() : mKeyguardBottomArea.getRightPreview(); + } + + @Override + public float getAffordanceFalsingFactor() { + return mCentralSurfaces.isWakeUpComingFromTouch() ? 1.5f : 1.0f; + } + + @Override + public boolean needsAntiFalsing() { + return mBarState == KEYGUARD; + } + } + private class OnEmptySpaceClickListener implements NotificationStackScrollLayout.OnEmptySpaceClickListener { @Override @@ -4891,6 +5118,15 @@ public class NotificationPanelViewController extends PanelViewController { } } + private class OnConfigurationChangedListener extends + PanelViewController.OnConfigurationChangedListener { + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mAffordanceHelper.onConfigurationChanged(); + } + } + private class OnApplyWindowInsetsListener implements View.OnApplyWindowInsetsListener { public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { // the same types of insets that are handled in NotificationShadeWindowView diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index d2fc1af010b93..ed12b00cc6444 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -484,6 +484,8 @@ public abstract class PanelViewController { protected abstract boolean shouldGestureWaitForTouchSlop(); + protected abstract boolean shouldGestureIgnoreXTouchSlop(float x, float y); + protected void onTrackingStopped(boolean expand) { mTracking = false; mCentralSurfaces.onTrackingStopped(expand); @@ -1331,7 +1333,7 @@ public abstract class PanelViewController { if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { mGestureWaitForTouchSlop = shouldGestureWaitForTouchSlop(); - mIgnoreXTouchSlop = true; + mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y); } switch (event.getActionMasked()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java new file mode 100644 index 0000000000000..3d317143eb515 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2014 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.statusbar.policy; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; + +import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.ActivityIntentHelper; +import com.android.systemui.statusbar.phone.KeyguardPreviewContainer; + +import java.util.List; + +/** + * Utility class to inflate previews for phone and camera affordance. + */ +public class PreviewInflater { + + private static final String TAG = "PreviewInflater"; + + private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout"; + private final ActivityIntentHelper mActivityIntentHelper; + + private Context mContext; + private LockPatternUtils mLockPatternUtils; + + public PreviewInflater(Context context, LockPatternUtils lockPatternUtils, + ActivityIntentHelper activityIntentHelper) { + mContext = context; + mLockPatternUtils = lockPatternUtils; + mActivityIntentHelper = activityIntentHelper; + } + + public View inflatePreview(Intent intent) { + WidgetInfo info = getWidgetInfo(intent); + return inflatePreview(info); + } + + public View inflatePreviewFromService(ComponentName componentName) { + WidgetInfo info = getWidgetInfoFromService(componentName); + return inflatePreview(info); + } + + private KeyguardPreviewContainer inflatePreview(WidgetInfo info) { + if (info == null) { + return null; + } + View v = inflateWidgetView(info); + if (v == null) { + return null; + } + KeyguardPreviewContainer container = new KeyguardPreviewContainer(mContext, null); + container.addView(v); + return container; + } + + private View inflateWidgetView(WidgetInfo widgetInfo) { + View widgetView = null; + try { + Context appContext = mContext.createPackageContext( + widgetInfo.contextPackage, Context.CONTEXT_RESTRICTED); + LayoutInflater appInflater = (LayoutInflater) + appContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + appInflater = appInflater.cloneInContext(appContext); + widgetView = appInflater.inflate(widgetInfo.layoutId, null, false); + } catch (PackageManager.NameNotFoundException|RuntimeException e) { + Log.w(TAG, "Error creating widget view", e); + } + return widgetView; + } + + private WidgetInfo getWidgetInfoFromService(ComponentName componentName) { + PackageManager packageManager = mContext.getPackageManager(); + // Look for the preview specified in the service meta-data + try { + Bundle metaData = packageManager.getServiceInfo( + componentName, PackageManager.GET_META_DATA).metaData; + return getWidgetInfoFromMetaData(componentName.getPackageName(), metaData); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "Failed to load preview; " + componentName.flattenToShortString() + + " not found", e); + } + return null; + } + + private WidgetInfo getWidgetInfoFromMetaData(String contextPackage, + Bundle metaData) { + if (metaData == null) { + return null; + } + int layoutId = metaData.getInt(META_DATA_KEYGUARD_LAYOUT); + if (layoutId == 0) { + return null; + } + WidgetInfo info = new WidgetInfo(); + info.contextPackage = contextPackage; + info.layoutId = layoutId; + return info; + } + + private WidgetInfo getWidgetInfo(Intent intent) { + PackageManager packageManager = mContext.getPackageManager(); + int flags = PackageManager.MATCH_DEFAULT_ONLY + | PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; + final List appList = packageManager.queryIntentActivitiesAsUser( + intent, flags, KeyguardUpdateMonitor.getCurrentUser()); + if (appList.size() == 0) { + return null; + } + ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, + flags | PackageManager.GET_META_DATA, + KeyguardUpdateMonitor.getCurrentUser()); + if (mActivityIntentHelper.wouldLaunchResolverActivity(resolved, appList)) { + return null; + } + if (resolved == null || resolved.activityInfo == null) { + return null; + } + return getWidgetInfoFromMetaData(resolved.activityInfo.packageName, + resolved.activityInfo.metaData); + } + + private static class WidgetInfo { + String contextPackage; + int layoutId; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 266f0e95f2ce1..2faff0ced70a6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -848,6 +848,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mCentralSurfaces.showKeyguardImpl(); // Starting a pulse should change the scrim controller to the pulsing state + when(mNotificationPanelViewController.isLaunchTransitionRunning()).thenReturn(true); when(mNotificationPanelViewController.isLaunchingAffordanceWithPreview()).thenReturn(true); mCentralSurfaces.updateScrimController(); verify(mScrimController).transitionTo(eq(ScrimState.UNLOCKED), any()); @@ -884,6 +885,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mCentralSurfaces.showKeyguardImpl(); // Starting a pulse should change the scrim controller to the pulsing state + when(mNotificationPanelViewController.isLaunchTransitionRunning()).thenReturn(true); when(mNotificationPanelViewController.isLaunchingAffordanceWithPreview()).thenReturn(false); mCentralSurfaces.updateScrimController(); verify(mScrimController).transitionTo(eq(ScrimState.KEYGUARD)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt index 4b557dc423fff..31465f45af42e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt @@ -12,12 +12,12 @@ import com.android.systemui.statusbar.policy.AccessibilityController import com.android.systemui.statusbar.policy.FlashlightController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.tuner.TunerService -import java.util.concurrent.Executor import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations +import java.util.concurrent.Executor @SmallTest @RunWith(AndroidTestingRunner::class) @@ -51,5 +51,6 @@ class KeyguardBottomAreaTest : SysuiTestCase() { null, false) as KeyguardBottomAreaView other.initFrom(mKeyguardBottomArea) + other.launchVoiceAssist() } -} +} \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index 046af95c8c1d0..79c7e55d4d096 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -106,6 +106,7 @@ import com.android.systemui.plugins.qs.QS; import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.KeyguardAffordanceView; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -400,6 +401,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mNotificationStackScrollLayoutController.getHeadsUpCallback()) .thenReturn(mHeadsUpCallback); when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea); + when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class)); + when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class)); when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame); when(mView.findViewById(R.id.keyguard_status_view)) From 1524e67dae9d1c1d1bd5d53a0b4088a84bd45f6c Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Tue, 28 Jun 2022 21:16:23 +0000 Subject: [PATCH 05/45] Revert "Removes left/right buttons from bottom area." This reverts commit 0fc5c393afc4133f5b3cc45fbc0e6d20ef6d255f. Reason for revert: Droidfood Blocking bug: 237349230 Change-Id: Ia0fa18ba1a72bc57f45b11f5954b6d8eada076ab (cherry picked from commit 03e0b8e0a7d1fbde2baba05ec8a8c7efaef4c4c9) Merged-In: Ia0fa18ba1a72bc57f45b11f5954b6d8eada076ab --- .../res/layout/keyguard_bottom_area.xml | 20 + packages/SystemUI/res/values/config.xml | 6 + packages/SystemUI/res/values/dimens.xml | 3 + packages/SystemUI/res/values/strings.xml | 7 + .../statusbar/phone/CentralSurfaces.java | 6 + .../CentralSurfacesCommandQueueCallbacks.java | 3 +- .../statusbar/phone/CentralSurfacesImpl.java | 36 +- .../phone/KeyguardAffordanceHelper.java | 587 +++++++++++++++++ .../phone/KeyguardBottomAreaView.java | 610 +++++++++++++++++- .../NotificationPanelViewController.java | 244 ++++++- .../statusbar/phone/PanelViewController.java | 4 +- .../statusbar/policy/PreviewInflater.java | 150 +++++ .../phone/CentralSurfacesImplTest.java | 2 + .../statusbar/phone/KeyguardBottomAreaTest.kt | 5 +- .../NotificationPanelViewControllerTest.java | 3 + 15 files changed, 1648 insertions(+), 38 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index 12dfa1042dd7d..8f8993f3c8d98 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -59,6 +59,26 @@ + + + + 400 + + false + + + false + 333 333 diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 7f7b8716d27c4..4d365412828ed 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -676,6 +676,9 @@ 30dp + + 120dp + 60dp diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index ef672f3a62135..343ec4f67964b 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -313,6 +313,13 @@ Scanning face Send + + + open phone + + open voice assist + + open camera Cancel diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index d25bbbd2a591f..2c22bc68c1981 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -427,6 +427,12 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn void onHintFinished(); + void onCameraHintStarted(); + + void onVoiceAssistHintStarted(); + + void onPhoneHintStarted(); + void onTrackingStopped(boolean expand); // TODO: Figure out way to remove these. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java index 38c37f03f6431..9060d5f67913a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java @@ -388,7 +388,8 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba if (mStatusBarKeyguardViewManager.isBouncerShowing()) { mStatusBarKeyguardViewManager.reset(true /* hide */); } - mNotificationPanelViewController.launchCamera(source); + mNotificationPanelViewController.launchCamera( + mCentralSurfaces.isDeviceInteractive() /* animate */, source); mCentralSurfaces.updateScrimController(); } else { // We need to defer the camera launch until the screen comes on, since otherwise diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 4f99deaaf7995..5181af773d9a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -1285,6 +1285,8 @@ public class CentralSurfacesImpl extends CoreStartable implements backdrop.setScaleY(scale); }); + mNotificationPanelViewController.setUserSetupComplete(mUserSetup); + // Set up the quick settings tile panel final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame); if (container != null) { @@ -3022,7 +3024,8 @@ public class CentralSurfacesImpl extends CoreStartable implements @Override public boolean isInLaunchTransition() { - return mNotificationPanelViewController.isLaunchTransitionFinished(); + return mNotificationPanelViewController.isLaunchTransitionRunning() + || mNotificationPanelViewController.isLaunchTransitionFinished(); } /** @@ -3054,7 +3057,11 @@ public class CentralSurfacesImpl extends CoreStartable implements mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(), LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); }; - hideRunnable.run(); + if (mNotificationPanelViewController.isLaunchTransitionRunning()) { + mNotificationPanelViewController.setLaunchTransitionEndRunnable(hideRunnable); + } else { + hideRunnable.run(); + } } private void cancelAfterLaunchTransitionRunnables() { @@ -3063,6 +3070,7 @@ public class CentralSurfacesImpl extends CoreStartable implements } mLaunchTransitionEndRunnable = null; mLaunchTransitionCancelRunnable = null; + mNotificationPanelViewController.setLaunchTransitionEndRunnable(null); } /** @@ -3490,6 +3498,24 @@ public class CentralSurfacesImpl extends CoreStartable implements mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS); } + @Override + public void onCameraHintStarted() { + mFalsingCollector.onCameraHintStarted(); + mKeyguardIndicationController.showTransientIndication(R.string.camera_hint); + } + + @Override + public void onVoiceAssistHintStarted() { + mFalsingCollector.onLeftAffordanceHintStarted(); + mKeyguardIndicationController.showTransientIndication(R.string.voice_hint); + } + + @Override + public void onPhoneHintStarted() { + mFalsingCollector.onLeftAffordanceHintStarted(); + mKeyguardIndicationController.showTransientIndication(R.string.phone_hint); + } + @Override public void onTrackingStopped(boolean expand) { } @@ -3674,7 +3700,8 @@ public class CentralSurfacesImpl extends CoreStartable implements mWakeUpCoordinator.setFullyAwake(true); mWakeUpCoordinator.setWakingUp(false); if (mLaunchCameraWhenFinishedWaking) { - mNotificationPanelViewController.launchCamera(mLastCameraLaunchSource); + mNotificationPanelViewController.launchCamera( + false /* animate */, mLastCameraLaunchSource); mLaunchCameraWhenFinishedWaking = false; } if (mLaunchEmergencyActionWhenFinishedWaking) { @@ -4316,6 +4343,9 @@ public class CentralSurfacesImpl extends CoreStartable implements if (!mUserSetup) { animateCollapseQuickSettings(); } + if (mNotificationPanelViewController != null) { + mNotificationPanelViewController.setUserSetupComplete(mUserSetup); + } updateQsExpansionEnabled(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java new file mode 100644 index 0000000000000..2922b4c98d347 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java @@ -0,0 +1,587 @@ +/* + * Copyright (C) 2014 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.statusbar.phone; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; + +import com.android.systemui.R; +import com.android.systemui.animation.Interpolators; +import com.android.systemui.classifier.Classifier; +import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.statusbar.KeyguardAffordanceView; +import com.android.wm.shell.animation.FlingAnimationUtils; + +/** + * A touch handler of the keyguard which is responsible for launching phone and camera affordances. + */ +public class KeyguardAffordanceHelper { + + public static final long HINT_PHASE1_DURATION = 200; + private static final long HINT_PHASE2_DURATION = 350; + private static final float BACKGROUND_RADIUS_SCALE_FACTOR = 0.25f; + private static final int HINT_CIRCLE_OPEN_DURATION = 500; + + private final Context mContext; + private final Callback mCallback; + + private FlingAnimationUtils mFlingAnimationUtils; + private VelocityTracker mVelocityTracker; + private boolean mSwipingInProgress; + private float mInitialTouchX; + private float mInitialTouchY; + private float mTranslation; + private float mTranslationOnDown; + private int mTouchSlop; + private int mMinTranslationAmount; + private int mMinFlingVelocity; + private int mHintGrowAmount; + private KeyguardAffordanceView mLeftIcon; + private KeyguardAffordanceView mRightIcon; + private Animator mSwipeAnimator; + private final FalsingManager mFalsingManager; + private int mMinBackgroundRadius; + private boolean mMotionCancelled; + private int mTouchTargetSize; + private View mTargetedView; + private boolean mTouchSlopExeeded; + private AnimatorListenerAdapter mFlingEndListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mSwipeAnimator = null; + mSwipingInProgress = false; + mTargetedView = null; + } + }; + private Runnable mAnimationEndRunnable = new Runnable() { + @Override + public void run() { + mCallback.onAnimationToSideEnded(); + } + }; + + KeyguardAffordanceHelper(Callback callback, Context context, FalsingManager falsingManager) { + mContext = context; + mCallback = callback; + initIcons(); + updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false); + updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false); + mFalsingManager = falsingManager; + initDimens(); + } + + private void initDimens() { + final ViewConfiguration configuration = ViewConfiguration.get(mContext); + mTouchSlop = configuration.getScaledPagingTouchSlop(); + mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity(); + mMinTranslationAmount = mContext.getResources().getDimensionPixelSize( + R.dimen.keyguard_min_swipe_amount); + mMinBackgroundRadius = mContext.getResources().getDimensionPixelSize( + R.dimen.keyguard_affordance_min_background_radius); + mTouchTargetSize = mContext.getResources().getDimensionPixelSize( + R.dimen.keyguard_affordance_touch_target_size); + mHintGrowAmount = + mContext.getResources().getDimensionPixelSize(R.dimen.hint_grow_amount_sideways); + mFlingAnimationUtils = new FlingAnimationUtils(mContext.getResources().getDisplayMetrics(), + 0.4f); + } + + private void initIcons() { + mLeftIcon = mCallback.getLeftIcon(); + mRightIcon = mCallback.getRightIcon(); + updatePreviews(); + } + + public void updatePreviews() { + mLeftIcon.setPreviewView(mCallback.getLeftPreview()); + mRightIcon.setPreviewView(mCallback.getRightPreview()); + } + + public boolean onTouchEvent(MotionEvent event) { + int action = event.getActionMasked(); + if (mMotionCancelled && action != MotionEvent.ACTION_DOWN) { + return false; + } + final float y = event.getY(); + final float x = event.getX(); + + boolean isUp = false; + switch (action) { + case MotionEvent.ACTION_DOWN: + View targetView = getIconAtPosition(x, y); + if (targetView == null || (mTargetedView != null && mTargetedView != targetView)) { + mMotionCancelled = true; + return false; + } + if (mTargetedView != null) { + cancelAnimation(); + } else { + mTouchSlopExeeded = false; + } + startSwiping(targetView); + mInitialTouchX = x; + mInitialTouchY = y; + mTranslationOnDown = mTranslation; + initVelocityTracker(); + trackMovement(event); + mMotionCancelled = false; + break; + case MotionEvent.ACTION_POINTER_DOWN: + mMotionCancelled = true; + endMotion(true /* forceSnapBack */, x, y); + break; + case MotionEvent.ACTION_MOVE: + trackMovement(event); + float xDist = x - mInitialTouchX; + float yDist = y - mInitialTouchY; + float distance = (float) Math.hypot(xDist, yDist); + if (!mTouchSlopExeeded && distance > mTouchSlop) { + mTouchSlopExeeded = true; + } + if (mSwipingInProgress) { + if (mTargetedView == mRightIcon) { + distance = mTranslationOnDown - distance; + distance = Math.min(0, distance); + } else { + distance = mTranslationOnDown + distance; + distance = Math.max(0, distance); + } + setTranslation(distance, false /* isReset */, false /* animateReset */); + } + break; + + case MotionEvent.ACTION_UP: + isUp = true; + case MotionEvent.ACTION_CANCEL: + boolean hintOnTheRight = mTargetedView == mRightIcon; + trackMovement(event); + endMotion(!isUp, x, y); + if (!mTouchSlopExeeded && isUp) { + mCallback.onIconClicked(hintOnTheRight); + } + break; + } + return true; + } + + private void startSwiping(View targetView) { + mCallback.onSwipingStarted(targetView == mRightIcon); + mSwipingInProgress = true; + mTargetedView = targetView; + } + + private View getIconAtPosition(float x, float y) { + if (leftSwipePossible() && isOnIcon(mLeftIcon, x, y)) { + return mLeftIcon; + } + if (rightSwipePossible() && isOnIcon(mRightIcon, x, y)) { + return mRightIcon; + } + return null; + } + + public boolean isOnAffordanceIcon(float x, float y) { + return isOnIcon(mLeftIcon, x, y) || isOnIcon(mRightIcon, x, y); + } + + private boolean isOnIcon(View icon, float x, float y) { + float iconX = icon.getX() + icon.getWidth() / 2.0f; + float iconY = icon.getY() + icon.getHeight() / 2.0f; + double distance = Math.hypot(x - iconX, y - iconY); + return distance <= mTouchTargetSize / 2; + } + + private void endMotion(boolean forceSnapBack, float lastX, float lastY) { + if (mSwipingInProgress) { + flingWithCurrentVelocity(forceSnapBack, lastX, lastY); + } else { + mTargetedView = null; + } + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private boolean rightSwipePossible() { + return mRightIcon.getVisibility() == View.VISIBLE; + } + + private boolean leftSwipePossible() { + return mLeftIcon.getVisibility() == View.VISIBLE; + } + + public boolean onInterceptTouchEvent(MotionEvent ev) { + return false; + } + + public void startHintAnimation(boolean right, + Runnable onFinishedListener) { + cancelAnimation(); + startHintAnimationPhase1(right, onFinishedListener); + } + + private void startHintAnimationPhase1(final boolean right, final Runnable onFinishedListener) { + final KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon; + ValueAnimator animator = getAnimatorToRadius(right, mHintGrowAmount); + animator.addListener(new AnimatorListenerAdapter() { + private boolean mCancelled; + + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mCancelled) { + mSwipeAnimator = null; + mTargetedView = null; + onFinishedListener.run(); + } else { + startUnlockHintAnimationPhase2(right, onFinishedListener); + } + } + }); + animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); + animator.setDuration(HINT_PHASE1_DURATION); + animator.start(); + mSwipeAnimator = animator; + mTargetedView = targetView; + } + + /** + * Phase 2: Move back. + */ + private void startUnlockHintAnimationPhase2(boolean right, final Runnable onFinishedListener) { + ValueAnimator animator = getAnimatorToRadius(right, 0); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mSwipeAnimator = null; + mTargetedView = null; + onFinishedListener.run(); + } + }); + animator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); + animator.setDuration(HINT_PHASE2_DURATION); + animator.setStartDelay(HINT_CIRCLE_OPEN_DURATION); + animator.start(); + mSwipeAnimator = animator; + } + + private ValueAnimator getAnimatorToRadius(final boolean right, int radius) { + final KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon; + ValueAnimator animator = ValueAnimator.ofFloat(targetView.getCircleRadius(), radius); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float newRadius = (float) animation.getAnimatedValue(); + targetView.setCircleRadiusWithoutAnimation(newRadius); + float translation = getTranslationFromRadius(newRadius); + mTranslation = right ? -translation : translation; + updateIconsFromTranslation(targetView); + } + }); + return animator; + } + + private void cancelAnimation() { + if (mSwipeAnimator != null) { + mSwipeAnimator.cancel(); + } + } + + private void flingWithCurrentVelocity(boolean forceSnapBack, float lastX, float lastY) { + float vel = getCurrentVelocity(lastX, lastY); + + // We snap back if the current translation is not far enough + boolean snapBack = false; + if (mCallback.needsAntiFalsing()) { + snapBack = snapBack || mFalsingManager.isFalseTouch( + mTargetedView == mRightIcon + ? Classifier.RIGHT_AFFORDANCE : Classifier.LEFT_AFFORDANCE); + } + snapBack = snapBack || isBelowFalsingThreshold(); + + // or if the velocity is in the opposite direction. + boolean velIsInWrongDirection = vel * mTranslation < 0; + snapBack |= Math.abs(vel) > mMinFlingVelocity && velIsInWrongDirection; + vel = snapBack ^ velIsInWrongDirection ? 0 : vel; + fling(vel, snapBack || forceSnapBack, mTranslation < 0); + } + + private boolean isBelowFalsingThreshold() { + return Math.abs(mTranslation) < Math.abs(mTranslationOnDown) + getMinTranslationAmount(); + } + + private int getMinTranslationAmount() { + float factor = mCallback.getAffordanceFalsingFactor(); + return (int) (mMinTranslationAmount * factor); + } + + private void fling(float vel, final boolean snapBack, boolean right) { + float target = right ? -mCallback.getMaxTranslationDistance() + : mCallback.getMaxTranslationDistance(); + target = snapBack ? 0 : target; + + ValueAnimator animator = ValueAnimator.ofFloat(mTranslation, target); + mFlingAnimationUtils.apply(animator, mTranslation, target, vel); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mTranslation = (float) animation.getAnimatedValue(); + } + }); + animator.addListener(mFlingEndListener); + if (!snapBack) { + startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable, right); + mCallback.onAnimationToSideStarted(right, mTranslation, vel); + } else { + reset(true); + } + animator.start(); + mSwipeAnimator = animator; + if (snapBack) { + mCallback.onSwipingAborted(); + } + } + + private void startFinishingCircleAnimation(float velocity, Runnable animationEndRunnable, + boolean right) { + KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon; + targetView.finishAnimation(velocity, animationEndRunnable); + } + + private void setTranslation(float translation, boolean isReset, boolean animateReset) { + translation = rightSwipePossible() ? translation : Math.max(0, translation); + translation = leftSwipePossible() ? translation : Math.min(0, translation); + float absTranslation = Math.abs(translation); + if (translation != mTranslation || isReset) { + KeyguardAffordanceView targetView = translation > 0 ? mLeftIcon : mRightIcon; + KeyguardAffordanceView otherView = translation > 0 ? mRightIcon : mLeftIcon; + float alpha = absTranslation / getMinTranslationAmount(); + + // We interpolate the alpha of the other icons to 0 + float fadeOutAlpha = 1.0f - alpha; + fadeOutAlpha = Math.max(fadeOutAlpha, 0.0f); + + boolean animateIcons = isReset && animateReset; + boolean forceNoCircleAnimation = isReset && !animateReset; + float radius = getRadiusFromTranslation(absTranslation); + boolean slowAnimation = isReset && isBelowFalsingThreshold(); + if (!isReset) { + updateIcon(targetView, radius, alpha + fadeOutAlpha * targetView.getRestingAlpha(), + false, false, false, false); + } else { + updateIcon(targetView, 0.0f, fadeOutAlpha * targetView.getRestingAlpha(), + animateIcons, slowAnimation, true /* isReset */, forceNoCircleAnimation); + } + updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(), + animateIcons, slowAnimation, isReset, forceNoCircleAnimation); + + mTranslation = translation; + } + } + + private void updateIconsFromTranslation(KeyguardAffordanceView targetView) { + float absTranslation = Math.abs(mTranslation); + float alpha = absTranslation / getMinTranslationAmount(); + + // We interpolate the alpha of the other icons to 0 + float fadeOutAlpha = 1.0f - alpha; + fadeOutAlpha = Math.max(0.0f, fadeOutAlpha); + + // We interpolate the alpha of the targetView to 1 + KeyguardAffordanceView otherView = targetView == mRightIcon ? mLeftIcon : mRightIcon; + updateIconAlpha(targetView, alpha + fadeOutAlpha * targetView.getRestingAlpha(), false); + updateIconAlpha(otherView, fadeOutAlpha * otherView.getRestingAlpha(), false); + } + + private float getTranslationFromRadius(float circleSize) { + float translation = (circleSize - mMinBackgroundRadius) + / BACKGROUND_RADIUS_SCALE_FACTOR; + return translation > 0.0f ? translation + mTouchSlop : 0.0f; + } + + private float getRadiusFromTranslation(float translation) { + if (translation <= mTouchSlop) { + return 0.0f; + } + return (translation - mTouchSlop) * BACKGROUND_RADIUS_SCALE_FACTOR + mMinBackgroundRadius; + } + + public void animateHideLeftRightIcon() { + cancelAnimation(); + updateIcon(mRightIcon, 0f, 0f, true, false, false, false); + updateIcon(mLeftIcon, 0f, 0f, true, false, false, false); + } + + private void updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha, + boolean animate, boolean slowRadiusAnimation, boolean force, + boolean forceNoCircleAnimation) { + if (view.getVisibility() != View.VISIBLE && !force) { + return; + } + if (forceNoCircleAnimation) { + view.setCircleRadiusWithoutAnimation(circleRadius); + } else { + view.setCircleRadius(circleRadius, slowRadiusAnimation); + } + updateIconAlpha(view, alpha, animate); + } + + private void updateIconAlpha(KeyguardAffordanceView view, float alpha, boolean animate) { + float scale = getScale(alpha, view); + alpha = Math.min(1.0f, alpha); + view.setImageAlpha(alpha, animate); + view.setImageScale(scale, animate); + } + + private float getScale(float alpha, KeyguardAffordanceView icon) { + float scale = alpha / icon.getRestingAlpha() * 0.2f + + KeyguardAffordanceView.MIN_ICON_SCALE_AMOUNT; + return Math.min(scale, KeyguardAffordanceView.MAX_ICON_SCALE_AMOUNT); + } + + private void trackMovement(MotionEvent event) { + if (mVelocityTracker != null) { + mVelocityTracker.addMovement(event); + } + } + + private void initVelocityTracker() { + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + } + mVelocityTracker = VelocityTracker.obtain(); + } + + private float getCurrentVelocity(float lastX, float lastY) { + if (mVelocityTracker == null) { + return 0; + } + mVelocityTracker.computeCurrentVelocity(1000); + float aX = mVelocityTracker.getXVelocity(); + float aY = mVelocityTracker.getYVelocity(); + float bX = lastX - mInitialTouchX; + float bY = lastY - mInitialTouchY; + float bLen = (float) Math.hypot(bX, bY); + // Project the velocity onto the distance vector: a * b / |b| + float projectedVelocity = (aX * bX + aY * bY) / bLen; + if (mTargetedView == mRightIcon) { + projectedVelocity = -projectedVelocity; + } + return projectedVelocity; + } + + public void onConfigurationChanged() { + initDimens(); + initIcons(); + } + + public void onRtlPropertiesChanged() { + initIcons(); + } + + public void reset(boolean animate) { + cancelAnimation(); + setTranslation(0.0f, true /* isReset */, animate); + mMotionCancelled = true; + if (mSwipingInProgress) { + mCallback.onSwipingAborted(); + mSwipingInProgress = false; + } + } + + public boolean isSwipingInProgress() { + return mSwipingInProgress; + } + + public void launchAffordance(boolean animate, boolean left) { + if (mSwipingInProgress) { + // We don't want to mess with the state if the user is actually swiping already. + return; + } + KeyguardAffordanceView targetView = left ? mLeftIcon : mRightIcon; + KeyguardAffordanceView otherView = left ? mRightIcon : mLeftIcon; + startSwiping(targetView); + + // Do not animate the circle expanding if the affordance isn't visible, + // otherwise the circle will be meaningless. + if (targetView.getVisibility() != View.VISIBLE) { + animate = false; + } + + if (animate) { + fling(0, false, !left); + updateIcon(otherView, 0.0f, 0, true, false, true, false); + } else { + mCallback.onAnimationToSideStarted(!left, mTranslation, 0); + mTranslation = left ? mCallback.getMaxTranslationDistance() + : mCallback.getMaxTranslationDistance(); + updateIcon(otherView, 0.0f, 0.0f, false, false, true, false); + targetView.instantFinishAnimation(); + mFlingEndListener.onAnimationEnd(null); + mAnimationEndRunnable.run(); + } + } + + public interface Callback { + + /** + * Notifies the callback when an animation to a side page was started. + * + * @param rightPage Is the page animated to the right page? + */ + void onAnimationToSideStarted(boolean rightPage, float translation, float vel); + + /** + * Notifies the callback the animation to a side page has ended. + */ + void onAnimationToSideEnded(); + + float getMaxTranslationDistance(); + + void onSwipingStarted(boolean rightIcon); + + void onSwipingAborted(); + + void onIconClicked(boolean rightIcon); + + KeyguardAffordanceView getLeftIcon(); + + KeyguardAffordanceView getRightIcon(); + + View getLeftPreview(); + + View getRightPreview(); + + /** + * @return The factor the minimum swipe amount should be multiplied with. + */ + float getAffordanceFalsingFactor(); + + boolean needsAntiFalsing(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 61113a05af164..93b2e41e595b6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -16,30 +16,47 @@ package com.android.systemui.statusbar.phone; +import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; +import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; + import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; +import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON; +import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK; +import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON; +import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK; import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE; import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE; +import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; import android.service.quickaccesswallet.GetWalletCardsError; import android.service.quickaccesswallet.GetWalletCardsResponse; import android.service.quickaccesswallet.QuickAccessWalletClient; +import android.telecom.TelecomManager; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -47,35 +64,81 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.Utils; +import com.android.systemui.ActivityIntentHelper; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.Interpolators; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.camera.CameraIntents; +import com.android.systemui.controls.ControlsServiceInfo; import com.android.systemui.controls.dagger.ControlsComponent; import com.android.systemui.controls.management.ControlsListingController; import com.android.systemui.controls.ui.ControlsActivity; import com.android.systemui.controls.ui.ControlsUiController; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.plugins.IntentButtonProvider; +import com.android.systemui.plugins.IntentButtonProvider.IntentButton; +import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState; import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; +import com.android.systemui.statusbar.KeyguardAffordanceView; +import com.android.systemui.statusbar.policy.AccessibilityController; +import com.android.systemui.statusbar.policy.ExtensionController; +import com.android.systemui.statusbar.policy.ExtensionController.Extension; +import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.statusbar.policy.PreviewInflater; +import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory; +import com.android.systemui.tuner.TunerService; import com.android.systemui.wallet.controller.QuickAccessWalletController; +import java.util.List; + /** * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status * text. */ -public class KeyguardBottomAreaView extends FrameLayout { +public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener, + KeyguardStateController.Callback, + AccessibilityController.AccessibilityStateChangedCallback { - private static final String TAG = "CentralSurfaces/KeyguardBottomAreaView"; + final static String TAG = "CentralSurfaces/KeyguardBottomAreaView"; + + public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance"; + public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture"; + public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap"; + public static final String CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = "lift_to_launch_ml"; + + public static final String EXTRA_CAMERA_LAUNCH_SOURCE + = "com.android.systemui.camera_launch_source"; + + private static final String LEFT_BUTTON_PLUGIN + = "com.android.systemui.action.PLUGIN_LOCKSCREEN_LEFT_BUTTON"; + private static final String RIGHT_BUTTON_PLUGIN + = "com.android.systemui.action.PLUGIN_LOCKSCREEN_RIGHT_BUTTON"; + + private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL); + private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; + // TODO(b/179494051): May no longer be needed + private final boolean mShowLeftAffordance; + private final boolean mShowCameraAffordance; + + private KeyguardAffordanceView mRightAffordanceView; + private KeyguardAffordanceView mLeftAffordanceView; + private ImageView mWalletButton; private ImageView mQRCodeScannerButton; private ImageView mControlsButton; private boolean mHasCard = false; - private final WalletCardRetriever mCardRetriever = new WalletCardRetriever(); + private WalletCardRetriever mCardRetriever = new WalletCardRetriever(); private QuickAccessWalletController mQuickAccessWalletController; private QRCodeScannerController mQRCodeScannerController; private ControlsComponent mControlsComponent; @@ -85,42 +148,54 @@ public class KeyguardBottomAreaView extends FrameLayout { private ViewGroup mIndicationArea; private TextView mIndicationText; private TextView mIndicationTextBottom; + private ViewGroup mPreviewContainer; private ViewGroup mOverlayContainer; + private View mLeftPreview; + private View mCameraPreview; + private ActivityStarter mActivityStarter; private KeyguardStateController mKeyguardStateController; + private FlashlightController mFlashlightController; + private PreviewInflater mPreviewInflater; + private AccessibilityController mAccessibilityController; private CentralSurfaces mCentralSurfaces; + private KeyguardAffordanceHelper mAffordanceHelper; private FalsingManager mFalsingManager; + private boolean mUserSetupComplete; + private boolean mLeftIsVoiceAssist; + private Drawable mLeftAssistIcon; + + private IntentButton mRightButton = new DefaultRightButton(); + private Extension mRightExtension; + private String mRightButtonStr; + private IntentButton mLeftButton = new DefaultLeftButton(); + private Extension mLeftExtension; + private String mLeftButtonStr; private boolean mDozing; private int mIndicationBottomMargin; private int mIndicationPadding; private float mDarkAmount; private int mBurnInXOffset; private int mBurnInYOffset; + private ActivityIntentHelper mActivityIntentHelper; + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private final ControlsListingController.ControlsListingCallback mListingCallback = - serviceInfos -> post(() -> { - boolean available = !serviceInfos.isEmpty(); + private ControlsListingController.ControlsListingCallback mListingCallback = + new ControlsListingController.ControlsListingCallback() { + public void onServicesUpdated(List serviceInfos) { + post(() -> { + boolean available = !serviceInfos.isEmpty(); - if (available != mControlServicesAvailable) { - mControlServicesAvailable = available; - updateControlsVisibility(); - updateAffordanceColors(); + if (available != mControlServicesAvailable) { + mControlServicesAvailable = available; + updateControlsVisibility(); + updateAffordanceColors(); + } + }); } - }); - - private final KeyguardStateController.Callback mKeyguardStateCallback = - new KeyguardStateController.Callback() { - @Override - public void onKeyguardShowingChanged() { - if (mKeyguardStateController.isShowing()) { - if (mQuickAccessWalletController != null) { - mQuickAccessWalletController.queryWalletCards(mCardRetriever); - } - } - } - }; + }; public KeyguardBottomAreaView(Context context) { this(context, null); @@ -137,8 +212,43 @@ public class KeyguardBottomAreaView extends FrameLayout { public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + mShowLeftAffordance = getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance); + mShowCameraAffordance = getResources() + .getBoolean(R.bool.config_keyguardShowCameraAffordance); } + private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() { + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + String label = null; + if (host == mRightAffordanceView) { + label = getResources().getString(R.string.camera_label); + } else if (host == mLeftAffordanceView) { + if (mLeftIsVoiceAssist) { + label = getResources().getString(R.string.voice_assist_label); + } else { + label = getResources().getString(R.string.phone_label); + } + } + info.addAction(new AccessibilityAction(ACTION_CLICK, label)); + } + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (action == ACTION_CLICK) { + if (host == mRightAffordanceView) { + launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE); + return true; + } else if (host == mLeftAffordanceView) { + launchLeftAffordance(); + return true; + } + } + return super.performAccessibilityAction(host, action, args); + } + }; + public void initFrom(KeyguardBottomAreaView oldBottomArea) { setCentralSurfaces(oldBottomArea.mCentralSurfaces); @@ -169,7 +279,11 @@ public class KeyguardBottomAreaView extends FrameLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); + mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext), + new ActivityIntentHelper(mContext)); mOverlayContainer = findViewById(R.id.overlay_container); + mRightAffordanceView = findViewById(R.id.camera_button); + mLeftAffordanceView = findViewById(R.id.left_button); mWalletButton = findViewById(R.id.wallet_button); mQRCodeScannerButton = findViewById(R.id.qr_code_scanner_button); mControlsButton = findViewById(R.id.controls_button); @@ -181,11 +295,18 @@ public class KeyguardBottomAreaView extends FrameLayout { R.dimen.keyguard_indication_margin_bottom); mBurnInYOffset = getResources().getDimensionPixelSize( R.dimen.default_burn_in_prevention_offset); + updateCameraVisibility(); mKeyguardStateController = Dependency.get(KeyguardStateController.class); - mKeyguardStateController.addCallback(mKeyguardStateCallback); + mKeyguardStateController.addCallback(this); setClipChildren(false); setClipToPadding(false); + mRightAffordanceView.setOnClickListener(this); + mLeftAffordanceView.setOnClickListener(this); + initAccessibility(); mActivityStarter = Dependency.get(ActivityStarter.class); + mFlashlightController = Dependency.get(FlashlightController.class); + mAccessibilityController = Dependency.get(AccessibilityController.class); + mActivityIntentHelper = new ActivityIntentHelper(getContext()); mIndicationPadding = getResources().getDimensionPixelSize( R.dimen.keyguard_indication_area_padding); @@ -194,18 +315,51 @@ public class KeyguardBottomAreaView extends FrameLayout { updateControlsVisibility(); } + /** + * Set the container where the previews are rendered. + */ + public void setPreviewContainer(ViewGroup previewContainer) { + mPreviewContainer = previewContainer; + inflateCameraPreview(); + updateLeftAffordance(); + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + mAccessibilityController.addStateChangedCallback(this); + mRightExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class) + .withPlugin(IntentButtonProvider.class, RIGHT_BUTTON_PLUGIN, + p -> p.getIntentButton()) + .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_RIGHT_BUTTON)) + .withDefault(() -> new DefaultRightButton()) + .withCallback(button -> setRightButton(button)) + .build(); + mLeftExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class) + .withPlugin(IntentButtonProvider.class, LEFT_BUTTON_PLUGIN, + p -> p.getIntentButton()) + .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_LEFT_BUTTON)) + .withDefault(() -> new DefaultLeftButton()) + .withCallback(button -> setLeftButton(button)) + .build(); final IntentFilter filter = new IntentFilter(); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); - mKeyguardStateController.addCallback(mKeyguardStateCallback); + getContext().registerReceiverAsUser(mDevicePolicyReceiver, + UserHandle.ALL, filter, null, null); + mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class); + mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback); + mKeyguardStateController.addCallback(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - mKeyguardStateController.removeCallback(mKeyguardStateCallback); + mKeyguardStateController.removeCallback(this); + mAccessibilityController.removeStateChangedCallback(this); + mRightExtension.destroy(); + mLeftExtension.destroy(); + getContext().unregisterReceiver(mDevicePolicyReceiver); + mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback); if (mQuickAccessWalletController != null) { mQuickAccessWalletController.unregisterWalletChangeObservers( @@ -224,6 +378,11 @@ public class KeyguardBottomAreaView extends FrameLayout { } } + private void initAccessibility() { + mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate); + mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate); + } + @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -245,7 +404,19 @@ public class KeyguardBottomAreaView extends FrameLayout { getResources().getDimensionPixelSize( com.android.internal.R.dimen.text_size_small_material)); - ViewGroup.LayoutParams lp = mWalletButton.getLayoutParams(); + ViewGroup.LayoutParams lp = mRightAffordanceView.getLayoutParams(); + lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width); + lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height); + mRightAffordanceView.setLayoutParams(lp); + updateRightAffordanceIcon(); + + lp = mLeftAffordanceView.getLayoutParams(); + lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width); + lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height); + mLeftAffordanceView.setLayoutParams(lp); + updateLeftAffordanceIcon(); + + lp = mWalletButton.getLayoutParams(); lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width); lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height); mWalletButton.setLayoutParams(lp); @@ -268,8 +439,74 @@ public class KeyguardBottomAreaView extends FrameLayout { updateAffordanceColors(); } + private void updateRightAffordanceIcon() { + IconState state = mRightButton.getIcon(); + mRightAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE); + if (state.drawable != mRightAffordanceView.getDrawable() + || state.tint != mRightAffordanceView.shouldTint()) { + mRightAffordanceView.setImageDrawable(state.drawable, state.tint); + } + mRightAffordanceView.setContentDescription(state.contentDescription); + } + public void setCentralSurfaces(CentralSurfaces centralSurfaces) { mCentralSurfaces = centralSurfaces; + updateCameraVisibility(); // in case onFinishInflate() was called too early + } + + public void setAffordanceHelper(KeyguardAffordanceHelper affordanceHelper) { + mAffordanceHelper = affordanceHelper; + } + + public void setUserSetupComplete(boolean userSetupComplete) { + mUserSetupComplete = userSetupComplete; + updateCameraVisibility(); + updateLeftAffordanceIcon(); + } + + private Intent getCameraIntent() { + return mRightButton.getIntent(); + } + + /** + * Resolves the intent to launch the camera application. + */ + public ResolveInfo resolveCameraIntent() { + return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(), + PackageManager.MATCH_DEFAULT_ONLY, + KeyguardUpdateMonitor.getCurrentUser()); + } + + private void updateCameraVisibility() { + if (mRightAffordanceView == null) { + // Things are not set up yet; reply hazy, ask again later + return; + } + mRightAffordanceView.setVisibility(!mDozing && mShowCameraAffordance + && mRightButton.getIcon().isVisible ? View.VISIBLE : View.GONE); + } + + /** + * Set an alternate icon for the left assist affordance (replace the mic icon) + */ + public void setLeftAssistIcon(Drawable drawable) { + mLeftAssistIcon = drawable; + updateLeftAffordanceIcon(); + } + + private void updateLeftAffordanceIcon() { + if (!mShowLeftAffordance || mDozing) { + mLeftAffordanceView.setVisibility(GONE); + return; + } + + IconState state = mLeftButton.getIcon(); + mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE); + if (state.drawable != mLeftAffordanceView.getDrawable() + || state.tint != mLeftAffordanceView.shouldTint()) { + mLeftAffordanceView.setImageDrawable(state.drawable, state.tint); + } + mLeftAffordanceView.setContentDescription(state.contentDescription); } private void updateWalletVisibility() { @@ -315,6 +552,73 @@ public class KeyguardBottomAreaView extends FrameLayout { } } + public boolean isLeftVoiceAssist() { + return mLeftIsVoiceAssist; + } + + private boolean isPhoneVisible() { + PackageManager pm = mContext.getPackageManager(); + return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) + && pm.resolveActivity(PHONE_INTENT, 0) != null; + } + + @Override + public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) { + mRightAffordanceView.setClickable(touchExplorationEnabled); + mLeftAffordanceView.setClickable(touchExplorationEnabled); + mRightAffordanceView.setFocusable(accessibilityEnabled); + mLeftAffordanceView.setFocusable(accessibilityEnabled); + } + + @Override + public void onClick(View v) { + if (v == mRightAffordanceView) { + launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE); + } else if (v == mLeftAffordanceView) { + launchLeftAffordance(); + } + } + + public void launchCamera(String source) { + final Intent intent = getCameraIntent(); + intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source); + boolean wouldLaunchResolverActivity = mActivityIntentHelper.wouldLaunchResolverActivity( + intent, KeyguardUpdateMonitor.getCurrentUser()); + if (CameraIntents.isSecureCameraIntent(intent) && !wouldLaunchResolverActivity) { + AsyncTask.execute(new Runnable() { + @Override + public void run() { + // Normally an activity will set it's requested rotation + // animation on its window. However when launching an activity + // causes the orientation to change this is too late. In these cases + // the default animation is used. This doesn't look good for + // the camera (as it rotates the camera contents out of sync + // with physical reality). So, we ask the WindowManager to + // force the crossfade animation if an orientation change + // happens to occur during the launch. + ActivityOptions o = ActivityOptions.makeBasic(); + o.setDisallowEnterPictureInPictureWhileLaunching(true); + o.setRotationAnimationHint( + WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); + try { + ActivityTaskManager.getService().startActivityAsUser( + null, getContext().getBasePackageName(), + getContext().getAttributionTag(), intent, + intent.resolveTypeIfNeeded(getContext().getContentResolver()), + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, o.toBundle(), + UserHandle.CURRENT.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, "Unable to start camera activity", e); + } + } + }); + } else { + // We need to delay starting the activity because ResolverActivity finishes itself if + // launched behind lockscreen. + mActivityStarter.startActivity(intent, false /* dismissShade */); + } + } + public void setDarkAmount(float darkAmount) { if (darkAmount == mDarkAmount) { return; @@ -323,6 +627,77 @@ public class KeyguardBottomAreaView extends FrameLayout { dozeTimeTick(); } + public void launchLeftAffordance() { + if (mLeftIsVoiceAssist) { + launchVoiceAssist(); + } else { + launchPhone(); + } + } + + @VisibleForTesting + void launchVoiceAssist() { + Runnable runnable = new Runnable() { + @Override + public void run() { + Dependency.get(AssistManager.class).launchVoiceAssistFromKeyguard(); + } + }; + if (!mKeyguardStateController.canDismissLockScreen()) { + Dependency.get(Dependency.BACKGROUND_EXECUTOR).execute(runnable); + } else { + boolean dismissShade = !TextUtils.isEmpty(mRightButtonStr) + && Dependency.get(TunerService.class).getValue(LOCKSCREEN_RIGHT_UNLOCK, 1) != 0; + mCentralSurfaces.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */, + dismissShade, false /* afterKeyguardGone */, true /* deferred */); + } + } + + private boolean canLaunchVoiceAssist() { + return Dependency.get(AssistManager.class).canVoiceAssistBeLaunchedFromKeyguard(); + } + + private void launchPhone() { + final TelecomManager tm = TelecomManager.from(mContext); + if (tm.isInCall()) { + AsyncTask.execute(new Runnable() { + @Override + public void run() { + tm.showInCallScreen(false /* showDialpad */); + } + }); + } else { + boolean dismissShade = !TextUtils.isEmpty(mLeftButtonStr) + && Dependency.get(TunerService.class).getValue(LOCKSCREEN_LEFT_UNLOCK, 1) != 0; + mActivityStarter.startActivity(mLeftButton.getIntent(), dismissShade); + } + } + + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + if (changedView == this && visibility == VISIBLE) { + updateCameraVisibility(); + } + } + + public KeyguardAffordanceView getLeftView() { + return mLeftAffordanceView; + } + + public KeyguardAffordanceView getRightView() { + return mRightAffordanceView; + } + + public View getLeftPreview() { + return mLeftPreview; + } + + public View getRightPreview() { + return mCameraPreview; + } + public View getIndicationArea() { return mIndicationArea; } @@ -332,6 +707,66 @@ public class KeyguardBottomAreaView extends FrameLayout { return false; } + @Override + public void onUnlockedChanged() { + updateCameraVisibility(); + } + + @Override + public void onKeyguardShowingChanged() { + if (mKeyguardStateController.isShowing()) { + if (mQuickAccessWalletController != null) { + mQuickAccessWalletController.queryWalletCards(mCardRetriever); + } + } + } + + private void inflateCameraPreview() { + if (mPreviewContainer == null) { + return; + } + View previewBefore = mCameraPreview; + boolean visibleBefore = false; + if (previewBefore != null) { + mPreviewContainer.removeView(previewBefore); + visibleBefore = previewBefore.getVisibility() == View.VISIBLE; + } + mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent()); + if (mCameraPreview != null) { + mPreviewContainer.addView(mCameraPreview); + mCameraPreview.setVisibility(visibleBefore ? View.VISIBLE : View.INVISIBLE); + } + if (mAffordanceHelper != null) { + mAffordanceHelper.updatePreviews(); + } + } + + private void updateLeftPreview() { + if (mPreviewContainer == null) { + return; + } + View previewBefore = mLeftPreview; + if (previewBefore != null) { + mPreviewContainer.removeView(previewBefore); + } + + if (mLeftIsVoiceAssist) { + if (Dependency.get(AssistManager.class).getVoiceInteractorComponentName() != null) { + mLeftPreview = mPreviewInflater.inflatePreviewFromService( + Dependency.get(AssistManager.class).getVoiceInteractorComponentName()); + } + } else { + mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent()); + } + if (mLeftPreview != null) { + mPreviewContainer.addView(mLeftPreview); + mLeftPreview.setVisibility(View.INVISIBLE); + } + if (mAffordanceHelper != null) { + mAffordanceHelper.updatePreviews(); + } + } + public void startFinishDozeAnimation() { long delay = 0; if (mWalletButton.getVisibility() == View.VISIBLE) { @@ -343,6 +778,13 @@ public class KeyguardBottomAreaView extends FrameLayout { if (mControlsButton.getVisibility() == View.VISIBLE) { startFinishDozeAnimationElement(mControlsButton, delay); } + if (mLeftAffordanceView.getVisibility() == View.VISIBLE) { + startFinishDozeAnimationElement(mLeftAffordanceView, delay); + delay += DOZE_ANIMATION_STAGGER_DELAY; + } + if (mRightAffordanceView.getVisibility() == View.VISIBLE) { + startFinishDozeAnimationElement(mRightAffordanceView, delay); + } } private void startFinishDozeAnimationElement(View element, long delay) { @@ -356,9 +798,58 @@ public class KeyguardBottomAreaView extends FrameLayout { .setDuration(DOZE_ANIMATION_ELEMENT_DURATION); } + private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + post(new Runnable() { + @Override + public void run() { + updateCameraVisibility(); + } + }); + } + }; + + private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = + new KeyguardUpdateMonitorCallback() { + @Override + public void onUserSwitchComplete(int userId) { + updateCameraVisibility(); + } + + @Override + public void onUserUnlocked() { + inflateCameraPreview(); + updateCameraVisibility(); + updateLeftAffordance(); + } + }; + + public void updateLeftAffordance() { + updateLeftAffordanceIcon(); + updateLeftPreview(); + } + + private void setRightButton(IntentButton button) { + mRightButton = button; + updateRightAffordanceIcon(); + updateCameraVisibility(); + inflateCameraPreview(); + } + + private void setLeftButton(IntentButton button) { + mLeftButton = button; + if (!(mLeftButton instanceof DefaultLeftButton)) { + mLeftIsVoiceAssist = false; + } + updateLeftAffordance(); + } + public void setDozing(boolean dozing, boolean animate) { mDozing = dozing; + updateCameraVisibility(); + updateLeftAffordanceIcon(); updateWalletVisibility(); updateControlsVisibility(); updateQRCodeButtonVisibility(); @@ -397,12 +888,77 @@ public class KeyguardBottomAreaView extends FrameLayout { * Sets the alpha of the indication areas and affordances, excluding the lock icon. */ public void setAffordanceAlpha(float alpha) { + mLeftAffordanceView.setAlpha(alpha); + mRightAffordanceView.setAlpha(alpha); mIndicationArea.setAlpha(alpha); mWalletButton.setAlpha(alpha); mQRCodeScannerButton.setAlpha(alpha); mControlsButton.setAlpha(alpha); } + private class DefaultLeftButton implements IntentButton { + + private IconState mIconState = new IconState(); + + @Override + public IconState getIcon() { + mLeftIsVoiceAssist = canLaunchVoiceAssist(); + if (mLeftIsVoiceAssist) { + mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance; + if (mLeftAssistIcon == null) { + mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp); + } else { + mIconState.drawable = mLeftAssistIcon; + } + mIconState.contentDescription = mContext.getString( + R.string.accessibility_voice_assist_button); + } else { + mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance + && isPhoneVisible(); + mIconState.drawable = mContext.getDrawable( + com.android.internal.R.drawable.ic_phone); + mIconState.contentDescription = mContext.getString( + R.string.accessibility_phone_button); + } + return mIconState; + } + + @Override + public Intent getIntent() { + return PHONE_INTENT; + } + } + + private class DefaultRightButton implements IntentButton { + + private IconState mIconState = new IconState(); + + @Override + public IconState getIcon() { + boolean isCameraDisabled = (mCentralSurfaces != null) + && !mCentralSurfaces.isCameraAllowedByAdmin(); + mIconState.isVisible = !isCameraDisabled + && mShowCameraAffordance + && mUserSetupComplete + && resolveCameraIntent() != null; + mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp); + mIconState.contentDescription = + mContext.getString(R.string.accessibility_camera_button); + return mIconState; + } + + @Override + public Intent getIntent() { + boolean canDismissLs = mKeyguardStateController.canDismissLockScreen(); + boolean secure = mKeyguardStateController.isMethodSecure(); + if (secure && !canDismissLs) { + return CameraIntents.getSecureCameraIntent(getContext()); + } else { + return CameraIntents.getInsecureCameraIntent(getContext()); + } + } + } + @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { int bottom = insets.getDisplayCutout() != null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index c757cba319672..fbbb587872b45 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -50,6 +50,8 @@ import android.app.ActivityManager; import android.app.Fragment; import android.app.StatusBarManager; import android.content.ContentResolver; +import android.content.pm.ResolveInfo; +import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Canvas; @@ -143,6 +145,7 @@ import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.GestureRecorder; +import com.android.systemui.statusbar.KeyguardAffordanceView; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -249,6 +252,9 @@ public class NotificationPanelViewController extends PanelViewController { private final OnOverscrollTopChangedListener mOnOverscrollTopChangedListener = new OnOverscrollTopChangedListener(); + private final KeyguardAffordanceHelperCallback + mKeyguardAffordanceHelperCallback = + new KeyguardAffordanceHelperCallback(); private final OnEmptySpaceClickListener mOnEmptySpaceClickListener = new OnEmptySpaceClickListener(); @@ -332,6 +338,8 @@ public class NotificationPanelViewController extends PanelViewController { // Current max allowed keyguard notifications determined by measuring the panel private int mMaxAllowedKeyguardNotifications; + private ViewGroup mPreviewContainer; + private KeyguardAffordanceHelper mAffordanceHelper; private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController; private KeyguardUserSwitcherController mKeyguardUserSwitcherController; private KeyguardStatusBarView mKeyguardStatusBar; @@ -429,6 +437,8 @@ public class NotificationPanelViewController extends PanelViewController { */ private boolean mQsAnimatorExpand; private boolean mIsLaunchTransitionFinished; + private boolean mIsLaunchTransitionRunning; + private Runnable mLaunchAnimationEndRunnable; private boolean mOnlyAffordanceInThisMotion; private ValueAnimator mQsSizeChangeAnimator; @@ -445,8 +455,10 @@ public class NotificationPanelViewController extends PanelViewController { private boolean mClosingWithAlphaFadeOut; private boolean mHeadsUpAnimatingAway; private boolean mLaunchingAffordance; + private boolean mAffordanceHasPreview; private final FalsingManager mFalsingManager; private final FalsingCollector mFalsingCollector; + private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE; private Runnable mHeadsUpExistenceChangedRunnable = () -> { setHeadsUpAnimatingAway(false); @@ -479,6 +491,7 @@ public class NotificationPanelViewController extends PanelViewController { private float mLinearDarkAmount; private boolean mPulsing; + private boolean mUserSetupComplete; private boolean mHideIconsDuringLaunchAnimation = true; private int mStackScrollerMeasuringPass; /** @@ -995,6 +1008,8 @@ public class NotificationPanelViewController extends PanelViewController { mOnEmptySpaceClickListener); addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp); mKeyguardBottomArea = mView.findViewById(R.id.keyguard_bottom_area); + mPreviewContainer = mView.findViewById(R.id.preview_container); + mKeyguardBottomArea.setPreviewContainer(mPreviewContainer); initBottomArea(); @@ -1018,6 +1033,7 @@ public class NotificationPanelViewController extends PanelViewController { mView.setRtlChangeListener(layoutDirection -> { if (layoutDirection != mOldLayoutDirection) { + mAffordanceHelper.onRtlPropertiesChanged(); mOldLayoutDirection = layoutDirection; } }); @@ -1251,6 +1267,7 @@ public class NotificationPanelViewController extends PanelViewController { mKeyguardBottomArea = (KeyguardBottomAreaView) mLayoutInflater.inflate( R.layout.keyguard_bottom_area, mView, false); mKeyguardBottomArea.initFrom(oldBottomArea); + mKeyguardBottomArea.setPreviewContainer(mPreviewContainer); mView.addView(mKeyguardBottomArea, index); initBottomArea(); mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea); @@ -1287,7 +1304,11 @@ public class NotificationPanelViewController extends PanelViewController { } private void initBottomArea() { + mAffordanceHelper = new KeyguardAffordanceHelper( + mKeyguardAffordanceHelperCallback, mView.getContext(), mFalsingManager); + mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper); mKeyguardBottomArea.setCentralSurfaces(mCentralSurfaces); + mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete); mKeyguardBottomArea.setFalsingManager(mFalsingManager); mKeyguardBottomArea.initWallet(mQuickAccessWalletController); mKeyguardBottomArea.initControls(mControlsComponent); @@ -1652,6 +1673,10 @@ public class NotificationPanelViewController extends PanelViewController { public void resetViews(boolean animate) { mIsLaunchTransitionFinished = false; mBlockTouches = false; + if (!mLaunchingAffordance) { + mAffordanceHelper.reset(false); + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE; + } mCentralSurfaces.getGutsManager().closeAndSaveGuts(true /* leavebehind */, true /* force */, true /* controls */, -1 /* x */, -1 /* y */, true /* resetMenu */); if (animate && !isFullyCollapsed()) { @@ -2194,6 +2219,11 @@ public class NotificationPanelViewController extends PanelViewController { return isFullyCollapsed() || mBarState != StatusBarState.SHADE; } + @Override + protected boolean shouldGestureIgnoreXTouchSlop(float x, float y) { + return !mAffordanceHelper.isOnAffordanceIcon(x, y); + } + private void onQsTouch(MotionEvent event) { int pointerIndex = event.findPointerIndex(mTrackingPointer); if (pointerIndex < 0) { @@ -3358,6 +3388,9 @@ public class NotificationPanelViewController extends PanelViewController { mQsExpandImmediate = true; setShowShelfOnly(true); } + if (mBarState == KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) { + mAffordanceHelper.animateHideLeftRightIcon(); + } mNotificationStackScrollLayoutController.onPanelTrackingStarted(); cancelPendingPanelCollapse(); } @@ -3371,6 +3404,12 @@ public class NotificationPanelViewController extends PanelViewController { true /* animate */); } mNotificationStackScrollLayoutController.onPanelTrackingStopped(); + if (expand && (mBarState == KEYGUARD + || mBarState == StatusBarState.SHADE_LOCKED)) { + if (!mHintAnimationRunning) { + mAffordanceHelper.reset(true); + } + } // If we unlocked from a swipe, the user's finger might still be down after the // unlock animation ends. We need to wait until ACTION_UP to enable blurs again. @@ -3443,6 +3482,10 @@ public class NotificationPanelViewController extends PanelViewController { return mIsLaunchTransitionFinished; } + public boolean isLaunchTransitionRunning() { + return mIsLaunchTransitionRunning; + } + @Override public void setIsLaunchAnimationRunning(boolean running) { boolean wasRunning = mIsLaunchAnimationRunning; @@ -3461,6 +3504,10 @@ public class NotificationPanelViewController extends PanelViewController { } } + public void setLaunchTransitionEndRunnable(Runnable r) { + mLaunchAnimationEndRunnable = r; + } + private void updateDozingVisibilities(boolean animate) { mKeyguardBottomArea.setDozing(mDozing, animate); if (!mDozing && animate) { @@ -3639,8 +3686,30 @@ public class NotificationPanelViewController extends PanelViewController { && mBarState == StatusBarState.SHADE; } - /** Launches the camera. */ - public void launchCamera(int source) { + public void launchCamera(boolean animate, int source) { + if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) { + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP; + } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) { + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE; + } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER) { + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER; + } else { + + // Default. + mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE; + } + + // If we are launching it when we are occluded already we don't want it to animate, + // nor setting these flags, since the occluded state doesn't change anymore, hence it's + // never reset. + if (!isFullyCollapsed()) { + setLaunchingAffordance(true); + } else { + animate = false; + } + mAffordanceHasPreview = mKeyguardBottomArea.getRightPreview() != null; + mAffordanceHelper.launchAffordance( + animate, mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); } public void onAffordanceLaunchEnded() { @@ -3653,6 +3722,9 @@ public class NotificationPanelViewController extends PanelViewController { */ private void setLaunchingAffordance(boolean launchingAffordance) { mLaunchingAffordance = launchingAffordance; + mKeyguardAffordanceHelperCallback.getLeftIcon().setLaunchingAffordance(launchingAffordance); + mKeyguardAffordanceHelperCallback.getRightIcon().setLaunchingAffordance( + launchingAffordance); mKeyguardBypassController.setLaunchingAffordance(launchingAffordance); } @@ -3660,14 +3732,24 @@ public class NotificationPanelViewController extends PanelViewController { * Return true when a bottom affordance is launching an occluded activity with a splash screen. */ public boolean isLaunchingAffordanceWithPreview() { - return mLaunchingAffordance; + return mLaunchingAffordance && mAffordanceHasPreview; } /** * Whether the camera application can be launched for the camera launch gesture. */ public boolean canCameraGestureBeLaunched() { - return false; + if (!mCentralSurfaces.isCameraAllowedByAdmin()) { + return false; + } + + ResolveInfo resolveInfo = mKeyguardBottomArea.resolveCameraIntent(); + String + packageToLaunch = + (resolveInfo == null || resolveInfo.activityInfo == null) ? null + : resolveInfo.activityInfo.packageName; + return packageToLaunch != null && (mBarState != StatusBarState.SHADE || !isForegroundApp( + packageToLaunch)) && !mAffordanceHelper.isSwipingInProgress(); } /** @@ -3756,6 +3838,9 @@ public class NotificationPanelViewController extends PanelViewController { @Override public void setTouchAndAnimationDisabled(boolean disabled) { super.setTouchAndAnimationDisabled(disabled); + if (disabled && mAffordanceHelper.isSwipingInProgress() && !mIsLaunchTransitionRunning) { + mAffordanceHelper.reset(false /* animate */); + } mNotificationStackScrollLayoutController.setAnimationsEnabled(!disabled); } @@ -3838,6 +3923,11 @@ public class NotificationPanelViewController extends PanelViewController { return mKeyguardBottomArea; } + public void setUserSetupComplete(boolean userSetupComplete) { + mUserSetupComplete = userSetupComplete; + mKeyguardBottomArea.setUserSetupComplete(userSetupComplete); + } + public void applyLaunchAnimationProgress(float linearProgress) { boolean hideIcons = LaunchAnimator.getProgress(ActivityLaunchAnimator.TIMINGS, linearProgress, ANIMATION_DELAY_ICON_FADE_IN, 100) == 0.0f; @@ -4191,6 +4281,10 @@ public class NotificationPanelViewController extends PanelViewController { mMetricsLogger.count(COUNTER_PANEL_OPEN_PEEK, 1); } boolean handled = false; + if ((!mIsExpanding || mHintAnimationRunning) && !mQsExpanded + && mBarState != StatusBarState.SHADE && !mDozing) { + handled |= mAffordanceHelper.onTouchEvent(event); + } if (mOnlyAffordanceInThisMotion) { return true; } @@ -4433,6 +4527,139 @@ public class NotificationPanelViewController extends PanelViewController { } } + private class KeyguardAffordanceHelperCallback implements KeyguardAffordanceHelper.Callback { + @Override + public void onAnimationToSideStarted(boolean rightPage, float translation, float vel) { + boolean + start = + mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? rightPage + : !rightPage; + mIsLaunchTransitionRunning = true; + mLaunchAnimationEndRunnable = null; + float displayDensity = mCentralSurfaces.getDisplayDensity(); + int lengthDp = Math.abs((int) (translation / displayDensity)); + int velocityDp = Math.abs((int) (vel / displayDensity)); + if (start) { + mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_DIALER, lengthDp, velocityDp); + mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_DIALER); + mFalsingCollector.onLeftAffordanceOn(); + if (mFalsingCollector.shouldEnforceBouncer()) { + mCentralSurfaces.executeRunnableDismissingKeyguard( + () -> mKeyguardBottomArea.launchLeftAffordance(), null, + true /* dismissShade */, false /* afterKeyguardGone */, + true /* deferred */); + } else { + mKeyguardBottomArea.launchLeftAffordance(); + } + } else { + if (KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE.equals( + mLastCameraLaunchSource)) { + mLockscreenGestureLogger.write( + MetricsEvent.ACTION_LS_CAMERA, lengthDp, velocityDp); + mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_CAMERA); + } + mFalsingCollector.onCameraOn(); + if (mFalsingCollector.shouldEnforceBouncer()) { + mCentralSurfaces.executeRunnableDismissingKeyguard( + () -> mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource), null, + true /* dismissShade */, false /* afterKeyguardGone */, + true /* deferred */); + } else { + mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource); + } + } + mCentralSurfaces.startLaunchTransitionTimeout(); + mBlockTouches = true; + } + + @Override + public void onAnimationToSideEnded() { + mIsLaunchTransitionRunning = false; + mIsLaunchTransitionFinished = true; + if (mLaunchAnimationEndRunnable != null) { + mLaunchAnimationEndRunnable.run(); + mLaunchAnimationEndRunnable = null; + } + mCentralSurfaces.readyForKeyguardDone(); + } + + @Override + public float getMaxTranslationDistance() { + return (float) Math.hypot(mView.getWidth(), getHeight()); + } + + @Override + public void onSwipingStarted(boolean rightIcon) { + mFalsingCollector.onAffordanceSwipingStarted(rightIcon); + mView.requestDisallowInterceptTouchEvent(true); + mOnlyAffordanceInThisMotion = true; + mQsTracking = false; + } + + @Override + public void onSwipingAborted() { + mFalsingCollector.onAffordanceSwipingAborted(); + } + + @Override + public void onIconClicked(boolean rightIcon) { + if (mHintAnimationRunning) { + return; + } + mHintAnimationRunning = true; + mAffordanceHelper.startHintAnimation(rightIcon, () -> { + mHintAnimationRunning = false; + mCentralSurfaces.onHintFinished(); + }); + rightIcon = + mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? !rightIcon + : rightIcon; + if (rightIcon) { + mCentralSurfaces.onCameraHintStarted(); + } else { + if (mKeyguardBottomArea.isLeftVoiceAssist()) { + mCentralSurfaces.onVoiceAssistHintStarted(); + } else { + mCentralSurfaces.onPhoneHintStarted(); + } + } + } + + @Override + public KeyguardAffordanceView getLeftIcon() { + return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getRightView() : mKeyguardBottomArea.getLeftView(); + } + + @Override + public KeyguardAffordanceView getRightIcon() { + return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getLeftView() : mKeyguardBottomArea.getRightView(); + } + + @Override + public View getLeftPreview() { + return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getRightPreview() : mKeyguardBottomArea.getLeftPreview(); + } + + @Override + public View getRightPreview() { + return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL + ? mKeyguardBottomArea.getLeftPreview() : mKeyguardBottomArea.getRightPreview(); + } + + @Override + public float getAffordanceFalsingFactor() { + return mCentralSurfaces.isWakeUpComingFromTouch() ? 1.5f : 1.0f; + } + + @Override + public boolean needsAntiFalsing() { + return mBarState == KEYGUARD; + } + } + private class OnEmptySpaceClickListener implements NotificationStackScrollLayout.OnEmptySpaceClickListener { @Override @@ -4891,6 +5118,15 @@ public class NotificationPanelViewController extends PanelViewController { } } + private class OnConfigurationChangedListener extends + PanelViewController.OnConfigurationChangedListener { + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mAffordanceHelper.onConfigurationChanged(); + } + } + private class OnApplyWindowInsetsListener implements View.OnApplyWindowInsetsListener { public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { // the same types of insets that are handled in NotificationShadeWindowView diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index d2fc1af010b93..ed12b00cc6444 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -484,6 +484,8 @@ public abstract class PanelViewController { protected abstract boolean shouldGestureWaitForTouchSlop(); + protected abstract boolean shouldGestureIgnoreXTouchSlop(float x, float y); + protected void onTrackingStopped(boolean expand) { mTracking = false; mCentralSurfaces.onTrackingStopped(expand); @@ -1331,7 +1333,7 @@ public abstract class PanelViewController { if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { mGestureWaitForTouchSlop = shouldGestureWaitForTouchSlop(); - mIgnoreXTouchSlop = true; + mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y); } switch (event.getActionMasked()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java new file mode 100644 index 0000000000000..3d317143eb515 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2014 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.statusbar.policy; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; + +import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.ActivityIntentHelper; +import com.android.systemui.statusbar.phone.KeyguardPreviewContainer; + +import java.util.List; + +/** + * Utility class to inflate previews for phone and camera affordance. + */ +public class PreviewInflater { + + private static final String TAG = "PreviewInflater"; + + private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout"; + private final ActivityIntentHelper mActivityIntentHelper; + + private Context mContext; + private LockPatternUtils mLockPatternUtils; + + public PreviewInflater(Context context, LockPatternUtils lockPatternUtils, + ActivityIntentHelper activityIntentHelper) { + mContext = context; + mLockPatternUtils = lockPatternUtils; + mActivityIntentHelper = activityIntentHelper; + } + + public View inflatePreview(Intent intent) { + WidgetInfo info = getWidgetInfo(intent); + return inflatePreview(info); + } + + public View inflatePreviewFromService(ComponentName componentName) { + WidgetInfo info = getWidgetInfoFromService(componentName); + return inflatePreview(info); + } + + private KeyguardPreviewContainer inflatePreview(WidgetInfo info) { + if (info == null) { + return null; + } + View v = inflateWidgetView(info); + if (v == null) { + return null; + } + KeyguardPreviewContainer container = new KeyguardPreviewContainer(mContext, null); + container.addView(v); + return container; + } + + private View inflateWidgetView(WidgetInfo widgetInfo) { + View widgetView = null; + try { + Context appContext = mContext.createPackageContext( + widgetInfo.contextPackage, Context.CONTEXT_RESTRICTED); + LayoutInflater appInflater = (LayoutInflater) + appContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + appInflater = appInflater.cloneInContext(appContext); + widgetView = appInflater.inflate(widgetInfo.layoutId, null, false); + } catch (PackageManager.NameNotFoundException|RuntimeException e) { + Log.w(TAG, "Error creating widget view", e); + } + return widgetView; + } + + private WidgetInfo getWidgetInfoFromService(ComponentName componentName) { + PackageManager packageManager = mContext.getPackageManager(); + // Look for the preview specified in the service meta-data + try { + Bundle metaData = packageManager.getServiceInfo( + componentName, PackageManager.GET_META_DATA).metaData; + return getWidgetInfoFromMetaData(componentName.getPackageName(), metaData); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "Failed to load preview; " + componentName.flattenToShortString() + + " not found", e); + } + return null; + } + + private WidgetInfo getWidgetInfoFromMetaData(String contextPackage, + Bundle metaData) { + if (metaData == null) { + return null; + } + int layoutId = metaData.getInt(META_DATA_KEYGUARD_LAYOUT); + if (layoutId == 0) { + return null; + } + WidgetInfo info = new WidgetInfo(); + info.contextPackage = contextPackage; + info.layoutId = layoutId; + return info; + } + + private WidgetInfo getWidgetInfo(Intent intent) { + PackageManager packageManager = mContext.getPackageManager(); + int flags = PackageManager.MATCH_DEFAULT_ONLY + | PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; + final List appList = packageManager.queryIntentActivitiesAsUser( + intent, flags, KeyguardUpdateMonitor.getCurrentUser()); + if (appList.size() == 0) { + return null; + } + ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, + flags | PackageManager.GET_META_DATA, + KeyguardUpdateMonitor.getCurrentUser()); + if (mActivityIntentHelper.wouldLaunchResolverActivity(resolved, appList)) { + return null; + } + if (resolved == null || resolved.activityInfo == null) { + return null; + } + return getWidgetInfoFromMetaData(resolved.activityInfo.packageName, + resolved.activityInfo.metaData); + } + + private static class WidgetInfo { + String contextPackage; + int layoutId; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 266f0e95f2ce1..2faff0ced70a6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -848,6 +848,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mCentralSurfaces.showKeyguardImpl(); // Starting a pulse should change the scrim controller to the pulsing state + when(mNotificationPanelViewController.isLaunchTransitionRunning()).thenReturn(true); when(mNotificationPanelViewController.isLaunchingAffordanceWithPreview()).thenReturn(true); mCentralSurfaces.updateScrimController(); verify(mScrimController).transitionTo(eq(ScrimState.UNLOCKED), any()); @@ -884,6 +885,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mCentralSurfaces.showKeyguardImpl(); // Starting a pulse should change the scrim controller to the pulsing state + when(mNotificationPanelViewController.isLaunchTransitionRunning()).thenReturn(true); when(mNotificationPanelViewController.isLaunchingAffordanceWithPreview()).thenReturn(false); mCentralSurfaces.updateScrimController(); verify(mScrimController).transitionTo(eq(ScrimState.KEYGUARD)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt index 4b557dc423fff..31465f45af42e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt @@ -12,12 +12,12 @@ import com.android.systemui.statusbar.policy.AccessibilityController import com.android.systemui.statusbar.policy.FlashlightController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.tuner.TunerService -import java.util.concurrent.Executor import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations +import java.util.concurrent.Executor @SmallTest @RunWith(AndroidTestingRunner::class) @@ -51,5 +51,6 @@ class KeyguardBottomAreaTest : SysuiTestCase() { null, false) as KeyguardBottomAreaView other.initFrom(mKeyguardBottomArea) + other.launchVoiceAssist() } -} +} \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index 046af95c8c1d0..79c7e55d4d096 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -106,6 +106,7 @@ import com.android.systemui.plugins.qs.QS; import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.KeyguardAffordanceView; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -400,6 +401,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mNotificationStackScrollLayoutController.getHeadsUpCallback()) .thenReturn(mHeadsUpCallback); when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea); + when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class)); + when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class)); when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame); when(mView.findViewById(R.id.keyguard_status_view)) From 2889b5cc38ccfa6e2dbb85b855ee68cc433214ad Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Mon, 25 Jul 2022 22:16:16 +0000 Subject: [PATCH 06/45] Revert "Fix binder error when an app has many channels" Revert submission 19290255-jr-bind-flicker Reason for revert: b/240100577 Reverted Changes: I9a1c96f75:Improve App notification loading I391ce0b10:Fix binder error when an app has many channels Change-Id: I43777d003de5742056f600980ab52d58dbdb3ad8 (cherry picked from commit 34b3e4b51c6565cf84084c7533e1d9308fd39b10) Merged-In: I43777d003de5742056f600980ab52d58dbdb3ad8 --- .../android/app/NotificationChannelGroup.java | 21 +++++--- .../row/ChannelEditorDialogControllerTest.kt | 2 +- .../notification/PreferencesHelper.java | 50 ++++++++----------- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 1769993e0e075..f97415ca20c8a 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -20,7 +20,6 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Intent; -import android.content.pm.ParceledListSlice; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -67,7 +66,7 @@ public final class NotificationChannelGroup implements Parcelable { private CharSequence mName; private String mDescription; private boolean mBlocked; - private ParceledListSlice mChannels; + private List mChannels = new ArrayList<>(); // Bitwise representation of fields that have been changed by the user private int mUserLockedFields; @@ -101,8 +100,7 @@ public final class NotificationChannelGroup implements Parcelable { } else { mDescription = null; } - mChannels = in.readParcelable( - NotificationChannelGroup.class.getClassLoader(), ParceledListSlice.class); + in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader(), android.app.NotificationChannel.class); mBlocked = in.readBoolean(); mUserLockedFields = in.readInt(); } @@ -129,7 +127,7 @@ public final class NotificationChannelGroup implements Parcelable { } else { dest.writeByte((byte) 0); } - dest.writeParcelable(mChannels, flags); + dest.writeParcelableList(mChannels, flags); dest.writeBoolean(mBlocked); dest.writeInt(mUserLockedFields); } @@ -159,7 +157,7 @@ public final class NotificationChannelGroup implements Parcelable { * Returns the list of channels that belong to this group */ public List getChannels() { - return mChannels == null ? new ArrayList<>() : mChannels.getList(); + return mChannels; } /** @@ -190,11 +188,18 @@ public final class NotificationChannelGroup implements Parcelable { mBlocked = blocked; } + /** + * @hide + */ + public void addChannel(NotificationChannel channel) { + mChannels.add(channel); + } + /** * @hide */ public void setChannels(List channels) { - mChannels = new ParceledListSlice<>(channels); + mChannels = channels; } /** @@ -329,7 +334,7 @@ public final class NotificationChannelGroup implements Parcelable { proto.write(NotificationChannelGroupProto.NAME, mName.toString()); proto.write(NotificationChannelGroupProto.DESCRIPTION, mDescription); proto.write(NotificationChannelGroupProto.IS_BLOCKED, mBlocked); - for (NotificationChannel channel : mChannels.getList()) { + for (NotificationChannel channel : mChannels) { channel.dumpDebug(proto, NotificationChannelGroupProto.CHANNELS); } proto.end(token); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt index 214ba16dfc44b..64d0256287541 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt @@ -98,7 +98,7 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() { @Test fun testPrepareDialogForApp_onlyDefaultChannel() { - group.channels = listOf(channelDefault) + group.addChannel(channelDefault) controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID, setOf(channelDefault), appIcon, clickListener) diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 066692d374d0f..477b8da61e0f5 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -86,7 +86,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -1328,17 +1327,16 @@ public class PreferencesHelper implements RankingConfig { return null; } NotificationChannelGroup group = r.groups.get(groupId).clone(); - ArrayList channels = new ArrayList(); + group.setChannels(new ArrayList<>()); int N = r.channels.size(); for (int i = 0; i < N; i++) { final NotificationChannel nc = r.channels.valueAt(i); if (includeDeleted || !nc.isDeleted()) { if (groupId.equals(nc.getGroup())) { - channels.add(nc); + group.addChannel(nc); } } } - group.setChannels(channels); return group; } } @@ -1359,48 +1357,44 @@ public class PreferencesHelper implements RankingConfig { public ParceledListSlice getNotificationChannelGroups(String pkg, int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) { Objects.requireNonNull(pkg); - List groups = new ArrayList<>(); + Map groups = new ArrayMap<>(); synchronized (mPackagePreferences) { PackagePreferences r = getPackagePreferencesLocked(pkg, uid); if (r == null) { return ParceledListSlice.emptyList(); } - Map> groupedChannels = new HashMap(); + NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null); int N = r.channels.size(); for (int i = 0; i < N; i++) { final NotificationChannel nc = r.channels.valueAt(i); if (includeDeleted || !nc.isDeleted()) { if (nc.getGroup() != null) { if (r.groups.get(nc.getGroup()) != null) { - ArrayList channels = groupedChannels.getOrDefault( - nc.getGroup(), new ArrayList<>()); - channels.add(nc); - groupedChannels.put(nc.getGroup(), channels); + NotificationChannelGroup ncg = groups.get(nc.getGroup()); + if (ncg == null) { + ncg = r.groups.get(nc.getGroup()).clone(); + ncg.setChannels(new ArrayList<>()); + groups.put(nc.getGroup(), ncg); + + } + ncg.addChannel(nc); } } else { - ArrayList channels = groupedChannels.getOrDefault( - null, new ArrayList<>()); - channels.add(nc); - groupedChannels.put(null, channels); + nonGrouped.addChannel(nc); } } } - for (NotificationChannelGroup group : r.groups.values()) { - ArrayList channels = - groupedChannels.getOrDefault(group.getId(), new ArrayList<>()); - if (includeEmpty || !channels.isEmpty()) { - NotificationChannelGroup clone = group.clone(); - clone.setChannels(channels); - groups.add(clone); + if (includeNonGrouped && nonGrouped.getChannels().size() > 0) { + groups.put(null, nonGrouped); + } + if (includeEmpty) { + for (NotificationChannelGroup group : r.groups.values()) { + if (!groups.containsKey(group.getId())) { + groups.put(group.getId(), group); + } } } - - if (includeNonGrouped && groupedChannels.containsKey(null)) { - NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null); - nonGrouped.setChannels(groupedChannels.get(null)); - groups.add(nonGrouped); - } - return new ParceledListSlice<>(groups); + return new ParceledListSlice<>(new ArrayList<>(groups.values())); } } From ccebab96bcf805343e084326ce5de9a5a1dae576 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Mon, 25 Jul 2022 22:16:16 +0000 Subject: [PATCH 07/45] Revert "Fix binder error when an app has many channels" Revert submission 19290255-jr-bind-flicker Reason for revert: b/240100577 Reverted Changes: I9a1c96f75:Improve App notification loading I391ce0b10:Fix binder error when an app has many channels Change-Id: I43777d003de5742056f600980ab52d58dbdb3ad8 (cherry picked from commit 34b3e4b51c6565cf84084c7533e1d9308fd39b10) Merged-In: I43777d003de5742056f600980ab52d58dbdb3ad8 --- .../android/app/NotificationChannelGroup.java | 21 +++++--- .../row/ChannelEditorDialogControllerTest.kt | 2 +- .../notification/PreferencesHelper.java | 50 ++++++++----------- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 1769993e0e075..f97415ca20c8a 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -20,7 +20,6 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Intent; -import android.content.pm.ParceledListSlice; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -67,7 +66,7 @@ public final class NotificationChannelGroup implements Parcelable { private CharSequence mName; private String mDescription; private boolean mBlocked; - private ParceledListSlice mChannels; + private List mChannels = new ArrayList<>(); // Bitwise representation of fields that have been changed by the user private int mUserLockedFields; @@ -101,8 +100,7 @@ public final class NotificationChannelGroup implements Parcelable { } else { mDescription = null; } - mChannels = in.readParcelable( - NotificationChannelGroup.class.getClassLoader(), ParceledListSlice.class); + in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader(), android.app.NotificationChannel.class); mBlocked = in.readBoolean(); mUserLockedFields = in.readInt(); } @@ -129,7 +127,7 @@ public final class NotificationChannelGroup implements Parcelable { } else { dest.writeByte((byte) 0); } - dest.writeParcelable(mChannels, flags); + dest.writeParcelableList(mChannels, flags); dest.writeBoolean(mBlocked); dest.writeInt(mUserLockedFields); } @@ -159,7 +157,7 @@ public final class NotificationChannelGroup implements Parcelable { * Returns the list of channels that belong to this group */ public List getChannels() { - return mChannels == null ? new ArrayList<>() : mChannels.getList(); + return mChannels; } /** @@ -190,11 +188,18 @@ public final class NotificationChannelGroup implements Parcelable { mBlocked = blocked; } + /** + * @hide + */ + public void addChannel(NotificationChannel channel) { + mChannels.add(channel); + } + /** * @hide */ public void setChannels(List channels) { - mChannels = new ParceledListSlice<>(channels); + mChannels = channels; } /** @@ -329,7 +334,7 @@ public final class NotificationChannelGroup implements Parcelable { proto.write(NotificationChannelGroupProto.NAME, mName.toString()); proto.write(NotificationChannelGroupProto.DESCRIPTION, mDescription); proto.write(NotificationChannelGroupProto.IS_BLOCKED, mBlocked); - for (NotificationChannel channel : mChannels.getList()) { + for (NotificationChannel channel : mChannels) { channel.dumpDebug(proto, NotificationChannelGroupProto.CHANNELS); } proto.end(token); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt index 214ba16dfc44b..64d0256287541 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt @@ -98,7 +98,7 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() { @Test fun testPrepareDialogForApp_onlyDefaultChannel() { - group.channels = listOf(channelDefault) + group.addChannel(channelDefault) controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID, setOf(channelDefault), appIcon, clickListener) diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 066692d374d0f..477b8da61e0f5 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -86,7 +86,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -1328,17 +1327,16 @@ public class PreferencesHelper implements RankingConfig { return null; } NotificationChannelGroup group = r.groups.get(groupId).clone(); - ArrayList channels = new ArrayList(); + group.setChannels(new ArrayList<>()); int N = r.channels.size(); for (int i = 0; i < N; i++) { final NotificationChannel nc = r.channels.valueAt(i); if (includeDeleted || !nc.isDeleted()) { if (groupId.equals(nc.getGroup())) { - channels.add(nc); + group.addChannel(nc); } } } - group.setChannels(channels); return group; } } @@ -1359,48 +1357,44 @@ public class PreferencesHelper implements RankingConfig { public ParceledListSlice getNotificationChannelGroups(String pkg, int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) { Objects.requireNonNull(pkg); - List groups = new ArrayList<>(); + Map groups = new ArrayMap<>(); synchronized (mPackagePreferences) { PackagePreferences r = getPackagePreferencesLocked(pkg, uid); if (r == null) { return ParceledListSlice.emptyList(); } - Map> groupedChannels = new HashMap(); + NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null); int N = r.channels.size(); for (int i = 0; i < N; i++) { final NotificationChannel nc = r.channels.valueAt(i); if (includeDeleted || !nc.isDeleted()) { if (nc.getGroup() != null) { if (r.groups.get(nc.getGroup()) != null) { - ArrayList channels = groupedChannels.getOrDefault( - nc.getGroup(), new ArrayList<>()); - channels.add(nc); - groupedChannels.put(nc.getGroup(), channels); + NotificationChannelGroup ncg = groups.get(nc.getGroup()); + if (ncg == null) { + ncg = r.groups.get(nc.getGroup()).clone(); + ncg.setChannels(new ArrayList<>()); + groups.put(nc.getGroup(), ncg); + + } + ncg.addChannel(nc); } } else { - ArrayList channels = groupedChannels.getOrDefault( - null, new ArrayList<>()); - channels.add(nc); - groupedChannels.put(null, channels); + nonGrouped.addChannel(nc); } } } - for (NotificationChannelGroup group : r.groups.values()) { - ArrayList channels = - groupedChannels.getOrDefault(group.getId(), new ArrayList<>()); - if (includeEmpty || !channels.isEmpty()) { - NotificationChannelGroup clone = group.clone(); - clone.setChannels(channels); - groups.add(clone); + if (includeNonGrouped && nonGrouped.getChannels().size() > 0) { + groups.put(null, nonGrouped); + } + if (includeEmpty) { + for (NotificationChannelGroup group : r.groups.values()) { + if (!groups.containsKey(group.getId())) { + groups.put(group.getId(), group); + } } } - - if (includeNonGrouped && groupedChannels.containsKey(null)) { - NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null); - nonGrouped.setChannels(groupedChannels.get(null)); - groups.add(nonGrouped); - } - return new ParceledListSlice<>(groups); + return new ParceledListSlice<>(new ArrayList<>(groups.values())); } } From 799dfe794049df06070e328776242f4df5dfebd0 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 08/45] Revert "Remove support for COMBINED_SIGNAL_ICONS" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: I101f16263fff7f5ac2076fffab41824be8200953 (cherry picked from commit 6a9d2b06aadc7858fff5d775425b8da28ec44fcc) Merged-In: I101f16263fff7f5ac2076fffab41824be8200953 --- .../mobile/MobileStatusTracker.java | 7 - .../qs/QuickStatusBarHeaderController.java | 15 +- .../systemui/qs/carrier/CellSignalState.kt | 3 +- .../systemui/qs/carrier/QSCarrier.java | 48 +-- .../qs/carrier/QSCarrierGroupController.java | 109 ++++++- .../connectivity/MobileSignalController.java | 290 ++++++++++++++++-- .../MobileSignalControllerFactory.kt | 7 +- .../connectivity/NetworkControllerImpl.java | 52 +++- .../connectivity/WifiSignalController.java | 5 + .../phone/StatusBarSignalPolicy.java | 41 ++- .../qs/QuickStatusBarHeaderControllerTest.kt | 18 +- .../carrier/QSCarrierGroupControllerTest.java | 4 +- .../systemui/qs/carrier/QSCarrierTest.java | 16 +- .../NetworkControllerBaseTest.java | 14 +- .../NetworkControllerDataTest.java | 1 + .../NetworkControllerSignalTest.java | 5 + .../NetworkControllerWifiTest.java | 39 +++ 17 files changed, 598 insertions(+), 76 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java index b416738ade4aa..1a08366734bcd 100644 --- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java @@ -44,8 +44,6 @@ public class MobileStatusTracker { private final Handler mReceiverHandler; private final MobileTelephonyCallback mTelephonyCallback; - private boolean mListening = false; - /** * MobileStatusTracker constructors * @@ -78,7 +76,6 @@ public class MobileStatusTracker { * Config the MobileStatusTracker to start or stop monitoring platform signals. */ public void setListening(boolean listening) { - mListening = listening; if (listening) { mPhone.registerTelephonyCallback(mReceiverHandler::post, mTelephonyCallback); } else { @@ -86,10 +83,6 @@ public class MobileStatusTracker { } } - public boolean isListening() { - return mListening; - } - private void updateDataSim() { int activeDataSubId = mDefaults.getActiveDataSubId(); if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java index eeb1010693fca..ec0d0811ee760 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java @@ -134,9 +134,18 @@ class QuickStatusBarHeaderController extends ViewController rssiIgnoredSlots = List.of( - getResources().getString(com.android.internal.R.string.status_bar_mobile) - ); + List rssiIgnoredSlots; + + if (mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) { + rssiIgnoredSlots = List.of( + getResources().getString(com.android.internal.R.string.status_bar_no_calling), + getResources().getString(com.android.internal.R.string.status_bar_call_strength) + ); + } else { + rssiIgnoredSlots = List.of( + getResources().getString(com.android.internal.R.string.status_bar_mobile) + ); + } mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots, mInsetsProvider, mFeatureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)); diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt b/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt index e925b5472c27b..2dac639055240 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt @@ -27,6 +27,7 @@ data class CellSignalState( @JvmField val contentDescription: String? = null, @JvmField val typeContentDescription: String? = null, @JvmField val roaming: Boolean = false, + @JvmField val providerModelBehavior: Boolean = false ) { /** * Changes the visibility of this state by returning a copy with the visibility changed. @@ -40,4 +41,4 @@ data class CellSignalState( if (this.visible == visible) return this else return copy(visible = visible) } -} +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java index 703b95a082dc8..592da6554b906 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java @@ -45,7 +45,7 @@ public class QSCarrier extends LinearLayout { private View mSpacer; @Nullable private CellSignalState mLastSignalState; - private boolean mMobileSignalInitialized = false; + private boolean mProviderModelInitialized = false; private boolean mIsSingleCarrier; public QSCarrier(Context context) { @@ -96,25 +96,35 @@ public class QSCarrier extends LinearLayout { mMobileRoaming.setImageTintList(colorStateList); mMobileSignal.setImageTintList(colorStateList); - if (!mMobileSignalInitialized) { - mMobileSignalInitialized = true; - mMobileSignal.setImageDrawable(new SignalDrawable(mContext)); + if (state.providerModelBehavior) { + if (!mProviderModelInitialized) { + mProviderModelInitialized = true; + mMobileSignal.setImageDrawable( + mContext.getDrawable(R.drawable.ic_qs_no_calling_sms)); + } + mMobileSignal.setImageDrawable(mContext.getDrawable(state.mobileSignalIconId)); + mMobileSignal.setContentDescription(state.contentDescription); + } else { + if (!mProviderModelInitialized) { + mProviderModelInitialized = true; + mMobileSignal.setImageDrawable(new SignalDrawable(mContext)); + } + mMobileSignal.setImageLevel(state.mobileSignalIconId); + StringBuilder contentDescription = new StringBuilder(); + if (state.contentDescription != null) { + contentDescription.append(state.contentDescription).append(", "); + } + if (state.roaming) { + contentDescription + .append(mContext.getString(R.string.data_connection_roaming)) + .append(", "); + } + // TODO: show mobile data off/no internet text for 5 seconds before carrier text + if (hasValidTypeContentDescription(state.typeContentDescription)) { + contentDescription.append(state.typeContentDescription); + } + mMobileSignal.setContentDescription(contentDescription); } - mMobileSignal.setImageLevel(state.mobileSignalIconId); - StringBuilder contentDescription = new StringBuilder(); - if (state.contentDescription != null) { - contentDescription.append(state.contentDescription).append(", "); - } - if (state.roaming) { - contentDescription - .append(mContext.getString(R.string.data_connection_roaming)) - .append(", "); - } - // TODO: show mobile data off/no internet text for 5 seconds before carrier text - if (hasValidTypeContentDescription(state.typeContentDescription)) { - contentDescription.append(state.typeContentDescription); - } - mMobileSignal.setContentDescription(contentDescription); } return true; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java index cb76ee2bb6a1c..6908e5ab49e6a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java @@ -42,7 +42,10 @@ import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.statusbar.connectivity.IconState; import com.android.systemui.statusbar.connectivity.MobileDataIndicators; import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.connectivity.SignalCallback; @@ -75,6 +78,7 @@ public class QSCarrierGroupController { private QSCarrier[] mCarrierGroups = new QSCarrier[SIM_SLOTS]; private int[] mLastSignalLevel = new int[SIM_SLOTS]; private String[] mLastSignalLevelDescription = new String[SIM_SLOTS]; + private final boolean mProviderModel; private final CarrierConfigTracker mCarrierConfigTracker; private boolean mIsSingleCarrier; @@ -86,6 +90,9 @@ public class QSCarrierGroupController { private final SignalCallback mSignalCallback = new SignalCallback() { @Override public void setMobileDataIndicators(@NonNull MobileDataIndicators indicators) { + if (mProviderModel) { + return; + } int slotIndex = getSlotIndex(indicators.subId); if (slotIndex >= SIM_SLOTS) { Log.w(TAG, "setMobileDataIndicators - slot: " + slotIndex); @@ -100,11 +107,90 @@ public class QSCarrierGroupController { indicators.statusIcon.icon, indicators.statusIcon.contentDescription, indicators.typeContentDescription.toString(), - indicators.roaming + indicators.roaming, + mProviderModel ); mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget(); } + @Override + public void setCallIndicator(@NonNull IconState statusIcon, int subId) { + if (!mProviderModel) { + return; + } + int slotIndex = getSlotIndex(subId); + if (slotIndex >= SIM_SLOTS) { + Log.w(TAG, "setMobileDataIndicators - slot: " + slotIndex); + return; + } + if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { + Log.e(TAG, "Invalid SIM slot index for subscription: " + subId); + return; + } + + boolean displayCallStrengthIcon = + mCarrierConfigTracker.getCallStrengthConfig(subId); + + if (statusIcon.icon == R.drawable.ic_qs_no_calling_sms) { + if (statusIcon.visible) { + mInfos[slotIndex] = new CellSignalState( + true, + statusIcon.icon, + statusIcon.contentDescription, + "", + false, + mProviderModel); + } else { + // Whenever the no Calling & SMS state is cleared, switched to the last + // known call strength icon. + if (displayCallStrengthIcon) { + mInfos[slotIndex] = new CellSignalState( + true, + mLastSignalLevel[slotIndex], + mLastSignalLevelDescription[slotIndex], + "", + false, + mProviderModel); + } else { + mInfos[slotIndex] = new CellSignalState( + true, + R.drawable.ic_qs_sim_card, + "", + "", + false, + mProviderModel); + } + } + mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget(); + } else { + mLastSignalLevel[slotIndex] = statusIcon.icon; + mLastSignalLevelDescription[slotIndex] = statusIcon.contentDescription; + // Only Shows the call strength icon when the no Calling & SMS icon is not + // shown. + if (mInfos[slotIndex].mobileSignalIconId + != R.drawable.ic_qs_no_calling_sms) { + if (displayCallStrengthIcon) { + mInfos[slotIndex] = new CellSignalState( + true, + statusIcon.icon, + statusIcon.contentDescription, + "", + false, + mProviderModel); + } else { + mInfos[slotIndex] = new CellSignalState( + true, + R.drawable.ic_qs_sim_card, + "", + "", + false, + mProviderModel); + } + mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget(); + } + } + } + @Override public void setNoSims(boolean hasNoSims, boolean simDetected) { if (hasNoSims) { @@ -133,8 +219,14 @@ public class QSCarrierGroupController { @Background Handler bgHandler, @Main Looper mainLooper, NetworkController networkController, CarrierTextManager.Builder carrierTextManagerBuilder, Context context, - CarrierConfigTracker carrierConfigTracker, SlotIndexResolver slotIndexResolver) { + CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags, + SlotIndexResolver slotIndexResolver) { + if (featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) { + mProviderModel = true; + } else { + mProviderModel = false; + } mActivityStarter = activityStarter; mBgHandler = bgHandler; mNetworkController = networkController; @@ -170,7 +262,8 @@ public class QSCarrierGroupController { R.drawable.ic_qs_no_calling_sms, context.getText(AccessibilityContentDescriptions.NO_CALLING).toString(), "", - false); + false, + mProviderModel); mLastSignalLevel[i] = TelephonyIcons.MOBILE_CALL_STRENGTH_ICONS[0]; mLastSignalLevelDescription[i] = context.getText(AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]) @@ -258,7 +351,8 @@ public class QSCarrierGroupController { for (int i = 0; i < SIM_SLOTS; i++) { if (mInfos[i].visible && mInfos[i].mobileSignalIconId == R.drawable.ic_qs_sim_card) { - mInfos[i] = new CellSignalState(true, R.drawable.ic_blank, "", "", false); + mInfos[i] = new CellSignalState(true, R.drawable.ic_blank, "", "", false, + mProviderModel); } } } @@ -376,13 +470,15 @@ public class QSCarrierGroupController { private final CarrierTextManager.Builder mCarrierTextControllerBuilder; private final Context mContext; private final CarrierConfigTracker mCarrierConfigTracker; + private final FeatureFlags mFeatureFlags; private final SlotIndexResolver mSlotIndexResolver; @Inject public Builder(ActivityStarter activityStarter, @Background Handler handler, @Main Looper looper, NetworkController networkController, CarrierTextManager.Builder carrierTextControllerBuilder, Context context, - CarrierConfigTracker carrierConfigTracker, SlotIndexResolver slotIndexResolver) { + CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags, + SlotIndexResolver slotIndexResolver) { mActivityStarter = activityStarter; mHandler = handler; mLooper = looper; @@ -390,6 +486,7 @@ public class QSCarrierGroupController { mCarrierTextControllerBuilder = carrierTextControllerBuilder; mContext = context; mCarrierConfigTracker = carrierConfigTracker; + mFeatureFlags = featureFlags; mSlotIndexResolver = slotIndexResolver; } @@ -401,7 +498,7 @@ public class QSCarrierGroupController { public QSCarrierGroupController build() { return new QSCarrierGroupController(mView, mActivityStarter, mHandler, mLooper, mNetworkController, mCarrierTextControllerBuilder, mContext, - mCarrierConfigTracker, mSlotIndexResolver); + mCarrierConfigTracker, mFeatureFlags, mSlotIndexResolver); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java index 5cf1abc18274e..f3dedc4e0d6ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java @@ -26,17 +26,25 @@ import android.net.NetworkCapabilities; import android.os.Handler; import android.os.Looper; import android.provider.Settings.Global; +import android.telephony.AccessNetworkConstants; import android.telephony.CellSignalStrength; import android.telephony.CellSignalStrengthCdma; +import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.telephony.ims.ImsException; +import android.telephony.ims.ImsMmTelManager; +import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.ImsRegistrationAttributes; +import android.telephony.ims.RegistrationManager.RegistrationCallback; import android.text.Html; import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.AccessibilityContentDescriptions; import com.android.settingslib.SignalIcon.MobileIconGroup; import com.android.settingslib.graph.SignalDrawable; import com.android.settingslib.mobile.MobileMappings.Config; @@ -46,6 +54,8 @@ import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.R; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.util.CarrierConfigTracker; import java.io.PrintWriter; @@ -60,20 +70,31 @@ import java.util.Map; public class MobileSignalController extends SignalController { private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); private static final int STATUS_HISTORY_SIZE = 64; + private static final int IMS_TYPE_WWAN = 1; + private static final int IMS_TYPE_WLAN = 2; + private static final int IMS_TYPE_WLAN_CROSS_SIM = 3; private final TelephonyManager mPhone; private final CarrierConfigTracker mCarrierConfigTracker; + private final ImsMmTelManager mImsMmTelManager; private final SubscriptionDefaults mDefaults; private final String mNetworkNameDefault; private final String mNetworkNameSeparator; private final ContentObserver mObserver; + private final boolean mProviderModelBehavior; + private final Handler mReceiverHandler; + private int mImsType = IMS_TYPE_WWAN; // Save entire info for logging, we only use the id. final SubscriptionInfo mSubscriptionInfo; private Map mNetworkToIconLookup; + private int mLastLevel; private MobileIconGroup mDefaultIcons; private Config mConfig; @VisibleForTesting boolean mInflateSignalStrengths = false; + private int mLastWwanLevel; + private int mLastWlanLevel; + private int mLastWlanCrossSimLevel; @VisibleForTesting final MobileStatusTracker mMobileStatusTracker; @@ -112,6 +133,52 @@ public class MobileSignalController extends SignalController mCurrentState.connected = mWifiTracker.connected; mCurrentState.ssid = mWifiTracker.ssid; mCurrentState.rssi = mWifiTracker.rssi; + boolean levelChanged = mCurrentState.level != mWifiTracker.level; mCurrentState.level = mWifiTracker.level; mCurrentState.statusLabel = mWifiTracker.statusLabel; mCurrentState.isCarrierMerged = mWifiTracker.isCarrierMerged; @@ -229,6 +230,10 @@ public class WifiSignalController extends SignalController mCurrentState.iconGroup = mCurrentState.isCarrierMerged ? mCarrierMergedWifiIconGroup : mUnmergedWifiIconGroup; + + if (levelChanged) { + mNetworkController.notifyWifiLevelChange(mCurrentState.level); + } } boolean isCarrierMergedWifi(int subId) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java index 492734e93dcac..ee242a4b1b751 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java @@ -26,6 +26,8 @@ import android.util.Log; import com.android.settingslib.mobile.TelephonyIcons; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.statusbar.connectivity.IconState; import com.android.systemui.statusbar.connectivity.MobileDataIndicators; import com.android.systemui.statusbar.connectivity.NetworkController; @@ -64,6 +66,7 @@ public class StatusBarSignalPolicy implements SignalCallback, private final Handler mHandler = Handler.getMain(); private final CarrierConfigTracker mCarrierConfigTracker; private final TunerService mTunerService; + private final FeatureFlags mFeatureFlags; private boolean mHideAirplane; private boolean mHideMobile; @@ -87,7 +90,8 @@ public class StatusBarSignalPolicy implements SignalCallback, CarrierConfigTracker carrierConfigTracker, NetworkController networkController, SecurityController securityController, - TunerService tunerService + TunerService tunerService, + FeatureFlags featureFlags ) { mContext = context; @@ -96,6 +100,7 @@ public class StatusBarSignalPolicy implements SignalCallback, mNetworkController = networkController; mSecurityController = securityController; mTunerService = tunerService; + mFeatureFlags = featureFlags; mSlotAirplane = mContext.getString(com.android.internal.R.string.status_bar_airplane); mSlotMobile = mContext.getString(com.android.internal.R.string.status_bar_mobile); @@ -372,6 +377,40 @@ public class StatusBarSignalPolicy implements SignalCallback, // Noop yay! } + @Override + public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork, + boolean noNetworksAvailable) { + if (!mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) { + return; + } + if (DEBUG) { + Log.d(TAG, "setConnectivityStatus: " + + "noDefaultNetwork = " + noDefaultNetwork + "," + + "noValidatedNetwork = " + noValidatedNetwork + "," + + "noNetworksAvailable = " + noNetworksAvailable); + } + WifiIconState newState = mWifiIconState.copy(); + newState.noDefaultNetwork = noDefaultNetwork; + newState.noValidatedNetwork = noValidatedNetwork; + newState.noNetworksAvailable = noNetworksAvailable; + newState.slot = mSlotWifi; + newState.airplaneSpacerVisible = mIsAirplaneMode; + if (noDefaultNetwork && noNetworksAvailable && !mIsAirplaneMode) { + newState.visible = true; + newState.resId = R.drawable.ic_qs_no_internet_unavailable; + } else if (noDefaultNetwork && !noNetworksAvailable + && (!mIsAirplaneMode || (mIsAirplaneMode && mIsWifiEnabled))) { + newState.visible = true; + newState.resId = R.drawable.ic_qs_no_internet_available; + } else { + newState.visible = false; + newState.resId = 0; + } + updateWifiIconWithState(newState); + mWifiIconState = newState; + } + + @Override public void setEthernetIndicators(IconState state) { boolean visible = state.visible && !mHideEthernet; diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt index be14cc51ef969..07c8af953d1e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt @@ -26,6 +26,7 @@ import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.colorextraction.SysuiColorExtractor import com.android.systemui.demomode.DemoModeController import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.qs.carrier.QSCarrierGroup import com.android.systemui.qs.carrier.QSCarrierGroupController import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider @@ -45,10 +46,10 @@ import org.junit.runner.RunWith import org.mockito.Answers import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock +import org.mockito.Mockito.`when` import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.reset import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @@ -161,6 +162,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { @Test fun testRSSISlot_notCombined() { + `when`(featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)).thenReturn(false) controller.init() val captor = argumentCaptor>() @@ -171,6 +173,20 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { ) } + @Test + fun testRSSISlot_combined() { + `when`(featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)).thenReturn(true) + controller.init() + + val captor = argumentCaptor>() + verify(view).onAttach(any(), any(), capture(captor), any(), anyBoolean()) + + assertThat(captor.value).containsExactly( + mContext.getString(com.android.internal.R.string.status_bar_no_calling), + mContext.getString(com.android.internal.R.string.status_bar_call_strength) + ) + } + @Test fun testSingleCarrierCallback() { controller.init() diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java index 1963e30e741e1..bd794d6813ec2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java @@ -37,6 +37,7 @@ import android.widget.TextView; import androidx.test.filters.SmallTest; import com.android.keyguard.CarrierTextManager; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.connectivity.IconState; import com.android.systemui.statusbar.connectivity.MobileDataIndicators; @@ -79,6 +80,7 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest { @Mock private QSCarrier mQSCarrier3; private TestableLooper mTestableLooper; + @Mock private FeatureFlags mFeatureFlags; @Mock private QSCarrierGroupController.OnSingleCarrierChangedListener mOnSingleCarrierChangedListener; @@ -118,7 +120,7 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest { mQSCarrierGroupController = new QSCarrierGroupController.Builder( mActivityStarter, handler, TestableLooper.get(this).getLooper(), mNetworkController, mCarrierTextControllerBuilder, mContext, mCarrierConfigTracker, - mSlotIndexResolver) + mFeatureFlags, mSlotIndexResolver) .setQSCarrierGroup(mQSCarrierGroup) .build(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java index 99a17a613041e..5212255078fc8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java @@ -22,11 +22,13 @@ import static org.junit.Assert.assertTrue; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.util.FeatureFlagUtils; import android.view.LayoutInflater; import android.view.View; import androidx.test.filters.SmallTest; +import com.android.settingslib.graph.SignalDrawable; import com.android.settingslib.mobile.TelephonyIcons; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -57,14 +59,14 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_first() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); assertTrue(mQSCarrier.updateState(c, false)); } @Test public void testUpdateState_same() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); assertTrue(mQSCarrier.updateState(c, false)); assertFalse(mQSCarrier.updateState(c, false)); @@ -72,7 +74,7 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_changed() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); assertTrue(mQSCarrier.updateState(c, false)); @@ -83,14 +85,14 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_singleCarrier_first() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); assertTrue(mQSCarrier.updateState(c, true)); } @Test public void testUpdateState_singleCarrier_noShowIcon() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); mQSCarrier.updateState(c, true); @@ -99,7 +101,7 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_multiCarrier_showIcon() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); mQSCarrier.updateState(c, false); @@ -108,7 +110,7 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_changeSingleMultiSingle() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); mQSCarrier.updateState(c, true); assertEquals(View.GONE, mQSCarrier.getRSSIView().getVisibility()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java index f8a0d2fc415c0..8808502ba0df3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java @@ -70,6 +70,8 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.log.LogBuffer; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; @@ -125,6 +127,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected CarrierConfigTracker mCarrierConfigTracker; protected FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); protected Handler mMainHandler; + protected FeatureFlags mFeatureFlags; protected WifiStatusTrackerFactory mWifiStatusTrackerFactory; protected MobileSignalControllerFactory mMobileFactory; @@ -156,6 +159,9 @@ public class NetworkControllerBaseTest extends SysuiTestCase { @Before public void setUp() throws Exception { + mFeatureFlags = mock(FeatureFlags.class); + when(mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)).thenReturn(false); + mInstrumentation = InstrumentationRegistry.getInstrumentation(); Settings.Global.putInt(mContext.getContentResolver(), Global.AIRPLANE_MODE_ON, 0); TestableResources res = mContext.getOrCreateTestableResources(); @@ -222,7 +228,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mMobileFactory = new MobileSignalControllerFactory( mContext, mCallbackHandler, - mCarrierConfigTracker + mCarrierConfigTracker, + mFeatureFlags ); mNetworkController = new NetworkControllerImpl(mContext, @@ -245,6 +252,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class) ); @@ -438,6 +446,10 @@ public class NetworkControllerBaseTest extends SysuiTestCase { updateSignalStrength(); } + public void setImsType(int imsType) { + mMobileSignalController.setImsType(imsType); + } + public void setIsGsm(boolean gsm) { when(mSignalStrength.isGsm()).thenReturn(gsm); updateSignalStrength(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java index ed8a3e16cdd14..f3edef434ed4c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java @@ -147,6 +147,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, new Handler(TestableLooper.get(this).getLooper()), + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); setupNetworkController(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java index a76676e01c150..f60b6d1997be0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java @@ -87,6 +87,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class) ); @@ -123,6 +124,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); TestableLooper.get(this).processAllMessages(); @@ -157,6 +159,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); setupNetworkController(); @@ -194,6 +197,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); mNetworkController.registerListeners(); @@ -279,6 +283,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); setupNetworkController(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java index 68170ea4b518e..3f71491592477 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java @@ -30,6 +30,7 @@ import android.net.NetworkInfo; import android.net.vcn.VcnTransportInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.telephony.CellSignalStrength; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; @@ -284,6 +285,44 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { verifyLastMobileDataIndicatorsForVcn(false, 1, 0, false); } + @Test + public void testCallStrengh() { + if (true) return; + String testSsid = "Test SSID"; + setWifiEnabled(true); + setWifiState(true, testSsid); + // Set the ImsType to be IMS_TYPE_WLAN + setImsType(2); + setWifiLevel(1); + for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) { + setWifiLevel(testLevel); + verifyLastCallStrength(TelephonyIcons.WIFI_CALL_STRENGTH_ICONS[testLevel]); + } + // Set the ImsType to be IMS_TYPE_WWAN + setImsType(1); + setupDefaultSignal(); + for (int testStrength = 0; + testStrength < CellSignalStrength.getNumSignalStrengthLevels(); testStrength++) { + setLevel(testStrength); + verifyLastCallStrength(TelephonyIcons.MOBILE_CALL_STRENGTH_ICONS[testStrength]); + } + } + + @Test + public void testNonPrimaryWiFi() { + if (true) return; + String testSsid = "Test SSID"; + setWifiEnabled(true); + setWifiState(true, testSsid); + // Set the ImsType to be IMS_TYPE_WLAN + setImsType(2); + setWifiLevel(1); + verifyLastCallStrength(TelephonyIcons.WIFI_CALL_STRENGTH_ICONS[1]); + when(mWifiInfo.isPrimary()).thenReturn(false); + setWifiLevel(3); + verifyLastCallStrength(TelephonyIcons.WIFI_CALL_STRENGTH_ICONS[1]); + } + protected void setWifiActivity(int activity) { // TODO: Not this, because this variable probably isn't sticking around. mNetworkController.mWifiSignalController.setActivity(activity); From 2f61c45d1b5ef4b5aa95aa70973ff112f02535f8 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 09/45] Revert "Create a MobileStatusTrackerFactory" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: Iccec69e2697f6638a6ef07e86bb9303641ef7167 (cherry picked from commit d611126474130e657ab8f70e91c861a40b80f86c) Merged-In: Iccec69e2697f6638a6ef07e86bb9303641ef7167 --- .../connectivity/MobileSignalController.java | 6 +-- .../MobileSignalControllerFactory.kt | 7 ---- .../MobileStatusTrackerFactory.kt | 42 ------------------- 3 files changed, 3 insertions(+), 52 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileStatusTrackerFactory.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java index f3dedc4e0d6ee..9d8667a3ccb08 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java @@ -96,7 +96,7 @@ public class MobileSignalController extends SignalController Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 10/45] Revert "Change from deprecated telephony api" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: I6b1a152d01eeb938b2e1a286e69e2994775ceb43 (cherry picked from commit 9d7f532671abb5f3290828e0da4e948a8ac092ca) Merged-In: I6b1a152d01eeb938b2e1a286e69e2994775ceb43 --- .../systemui/qs/tiles/dialog/InternetDialogController.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index 3c8775d01e2d6..f1fdae7db4825 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -778,8 +778,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi return; } - mTelephonyManager.setDataEnabledForReason( - TelephonyManager.DATA_ENABLED_REASON_USER, enabled); + mTelephonyManager.setDataEnabled(enabled); if (disableOtherSubscriptions) { final List subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); From 74adc48f27cb7edd0866f94b152c0e4c4ff696c9 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 11/45] Revert "[Cleanup] Order NetworkController's intent filters" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: Id6b03a4423b6b34f469cc6d749b0433e35e8b281 (cherry picked from commit 40f9d90bc607194ab0bd05b2442deb30b7b36fb8) Merged-In: Id6b03a4423b6b34f469cc6d749b0433e35e8b281 --- .../connectivity/NetworkControllerImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java index 6be347b55bc51..8a84ba12fa1cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java @@ -503,16 +503,16 @@ public class NetworkControllerImpl extends BroadcastReceiver // broadcasts IntentFilter filter = new IntentFilter(); - filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); - filter.addAction(Intent.ACTION_SERVICE_STATE); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(Intent.ACTION_SIM_STATE_CHANGED); - filter.addAction(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); + filter.addAction(Intent.ACTION_SERVICE_STATE); filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED); - filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); + filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); + filter.addAction(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler); mListening = true; From 778fb59e7e270318a75e470d369b2cae957d8ec9 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 12/45] Revert "Add an @Inject-able MobileSignalControllerFactory" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: Ic004e4164580d19914912e6fb8d8951cd075f9e9 (cherry picked from commit b1971c7747b58a049761137898e424c925347c9c) Merged-In: Ic004e4164580d19914912e6fb8d8951cd075f9e9 --- .../MobileSignalControllerFactory.kt | 60 ------------------- .../connectivity/NetworkControllerImpl.java | 41 ++++--------- .../NetworkControllerBaseTest.java | 9 +-- .../NetworkControllerDataTest.java | 1 - .../NetworkControllerSignalTest.java | 5 -- 5 files changed, 14 insertions(+), 102 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt deleted file mode 100644 index fa1333073f37f..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.systemui.statusbar.connectivity - -import android.content.Context -import android.os.Looper -import android.telephony.SubscriptionInfo -import android.telephony.TelephonyManager -import com.android.settingslib.mobile.MobileMappings -import com.android.settingslib.mobile.MobileStatusTracker -import com.android.systemui.flags.FeatureFlags -import com.android.systemui.util.CarrierConfigTracker -import javax.inject.Inject - -/** - * Factory to make MobileSignalController injectable - */ -internal class MobileSignalControllerFactory @Inject constructor( - val context: Context, - val callbackHandler: CallbackHandler, - val carrierConfigTracker: CarrierConfigTracker, - val featureFlags: FeatureFlags, -) { - fun createMobileSignalController( - config: MobileMappings.Config, - hasMobileData: Boolean, - phone: TelephonyManager, - networkController: NetworkControllerImpl, // TODO: no! - subscriptionInfo: SubscriptionInfo, - subscriptionDefaults: MobileStatusTracker.SubscriptionDefaults, - receiverLooper: Looper // TODO: no! - ): MobileSignalController { - return MobileSignalController( - context, - config, - hasMobileData, - phone, - callbackHandler, - networkController, - subscriptionInfo, - subscriptionDefaults, - receiverLooper, - carrierConfigTracker, - featureFlags, - ) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java index 8a84ba12fa1cc..a1dc7b41d42bf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java @@ -140,7 +140,6 @@ public class NetworkControllerImpl extends BroadcastReceiver private final FeatureFlags mFeatureFlags; private final DumpManager mDumpManager; private final LogBuffer mLogBuffer; - private final MobileSignalControllerFactory mMobileFactory; private TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener; private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -236,7 +235,6 @@ public class NetworkControllerImpl extends BroadcastReceiver DemoModeController demoModeController, CarrierConfigTracker carrierConfigTracker, WifiStatusTrackerFactory trackerFactory, - MobileSignalControllerFactory mobileFactory, @Main Handler handler, InternetDialogFactory internetDialogFactory, FeatureFlags featureFlags, @@ -259,7 +257,6 @@ public class NetworkControllerImpl extends BroadcastReceiver demoModeController, carrierConfigTracker, trackerFactory, - mobileFactory, handler, featureFlags, dumpManager, @@ -286,7 +283,6 @@ public class NetworkControllerImpl extends BroadcastReceiver DemoModeController demoModeController, CarrierConfigTracker carrierConfigTracker, WifiStatusTrackerFactory trackerFactory, - MobileSignalControllerFactory mobileFactory, @Main Handler handler, FeatureFlags featureFlags, DumpManager dumpManager, @@ -302,7 +298,6 @@ public class NetworkControllerImpl extends BroadcastReceiver mCallbackHandler = callbackHandler; mDataSaverController = new DataSaverControllerImpl(context); mBroadcastDispatcher = broadcastDispatcher; - mMobileFactory = mobileFactory; mSubscriptionManager = subManager; mSubDefaults = defaultsHandler; @@ -987,15 +982,11 @@ public class NetworkControllerImpl extends BroadcastReceiver mMobileSignalControllers.put(subId, cachedControllers.get(subId)); cachedControllers.remove(subId); } else { - MobileSignalController controller = mMobileFactory.createMobileSignalController( - mConfig, - mHasMobileDataFeature, - mPhone.createForSubscriptionId(subId), - this, - subscriptions.get(i), - mSubDefaults, - mReceiverHandler.getLooper() - ); + MobileSignalController controller = new MobileSignalController(mContext, mConfig, + mHasMobileDataFeature, mPhone.createForSubscriptionId(subId), + mCallbackHandler, this, subscriptions.get(i), + mSubDefaults, mReceiverHandler.getLooper(), mCarrierConfigTracker, + mFeatureFlags); controller.setUserSetupComplete(mUserSetup); mMobileSignalControllers.put(subId, controller); if (subscriptions.get(i).getSimSlotIndex() == 0) { @@ -1356,7 +1347,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mMobileSignalControllers.clear(); int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); for (int i = start /* get out of normal index range */; i < start + num; i++) { - subs.add(addDemoModeSignalController(i, i)); + subs.add(addSignalController(i, i)); } mCallbackHandler.setSubs(subs); for (int i = 0; i < mMobileSignalControllers.size(); i++) { @@ -1382,7 +1373,7 @@ public class NetworkControllerImpl extends BroadcastReceiver List subs = new ArrayList<>(); while (mMobileSignalControllers.size() <= slot) { int nextSlot = mMobileSignalControllers.size(); - subs.add(addDemoModeSignalController(nextSlot, nextSlot)); + subs.add(addSignalController(nextSlot, nextSlot)); } if (!subs.isEmpty()) { mCallbackHandler.setSubs(subs); @@ -1472,20 +1463,14 @@ public class NetworkControllerImpl extends BroadcastReceiver mHistoryIndex = (mHistoryIndex + 1) % HISTORY_SIZE; } - private SubscriptionInfo addDemoModeSignalController(int id, int simSlotIndex) { + private SubscriptionInfo addSignalController(int id, int simSlotIndex) { SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0, null, null, null, "", false, null, null); - - MobileSignalController controller = mMobileFactory.createMobileSignalController( - mConfig, - mHasMobileDataFeature, - mPhone.createForSubscriptionId(info.getSubscriptionId()), - this, - info, - mSubDefaults, - mReceiverHandler.getLooper() - ); - + MobileSignalController controller = new MobileSignalController(mContext, + mConfig, mHasMobileDataFeature, + mPhone.createForSubscriptionId(info.getSubscriptionId()), mCallbackHandler, this, + info, mSubDefaults, mReceiverHandler.getLooper(), mCarrierConfigTracker, + mFeatureFlags); mMobileSignalControllers.put(id, controller); controller.getState().userSetup = true; return info; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java index 8808502ba0df3..0d1879cb25939 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java @@ -129,7 +129,6 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected Handler mMainHandler; protected FeatureFlags mFeatureFlags; protected WifiStatusTrackerFactory mWifiStatusTrackerFactory; - protected MobileSignalControllerFactory mMobileFactory; protected int mSubId; @@ -225,12 +224,6 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mWifiStatusTrackerFactory = new WifiStatusTrackerFactory( mContext, mMockWm, mMockNsm, mMockCm, mMainHandler); - mMobileFactory = new MobileSignalControllerFactory( - mContext, - mCallbackHandler, - mCarrierConfigTracker, - mFeatureFlags - ); mNetworkController = new NetworkControllerImpl(mContext, mMockCm, @@ -250,7 +243,6 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mDemoModeController, mCarrierConfigTracker, mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -645,4 +637,5 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected void assertDataNetworkNameEquals(String expected) { assertEquals("Data network name", expected, mNetworkController.getMobileDataNetworkName()); } + } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java index f3edef434ed4c..e3dd6f4e6e406 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java @@ -145,7 +145,6 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mDemoModeController, mock(CarrierConfigTracker.class), mWifiStatusTrackerFactory, - mMobileFactory, new Handler(TestableLooper.get(this).getLooper()), mFeatureFlags, mock(DumpManager.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java index f60b6d1997be0..698899a8fc36f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java @@ -85,7 +85,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mCarrierConfigTracker, mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -122,7 +121,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mCarrierConfigTracker, mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -157,7 +155,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mock(CarrierConfigTracker.class), mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -195,7 +192,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mock(CarrierConfigTracker.class), mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -281,7 +277,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mock(CarrierConfigTracker.class), mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), From ad7bef8a3acf8b712caffea7371bdf1f09b19886 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 13/45] Revert "Remove support for COMBINED_SIGNAL_ICONS" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: I101f16263fff7f5ac2076fffab41824be8200953 (cherry picked from commit 6a9d2b06aadc7858fff5d775425b8da28ec44fcc) Merged-In: I101f16263fff7f5ac2076fffab41824be8200953 --- .../mobile/MobileStatusTracker.java | 7 - .../qs/QuickStatusBarHeaderController.java | 15 +- .../systemui/qs/carrier/CellSignalState.kt | 3 +- .../systemui/qs/carrier/QSCarrier.java | 48 +-- .../qs/carrier/QSCarrierGroupController.java | 109 ++++++- .../connectivity/MobileSignalController.java | 290 ++++++++++++++++-- .../MobileSignalControllerFactory.kt | 7 +- .../connectivity/NetworkControllerImpl.java | 52 +++- .../connectivity/WifiSignalController.java | 5 + .../phone/StatusBarSignalPolicy.java | 41 ++- .../qs/QuickStatusBarHeaderControllerTest.kt | 18 +- .../carrier/QSCarrierGroupControllerTest.java | 4 +- .../systemui/qs/carrier/QSCarrierTest.java | 16 +- .../NetworkControllerBaseTest.java | 14 +- .../NetworkControllerDataTest.java | 1 + .../NetworkControllerSignalTest.java | 5 + .../NetworkControllerWifiTest.java | 39 +++ 17 files changed, 598 insertions(+), 76 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java index b416738ade4aa..1a08366734bcd 100644 --- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java @@ -44,8 +44,6 @@ public class MobileStatusTracker { private final Handler mReceiverHandler; private final MobileTelephonyCallback mTelephonyCallback; - private boolean mListening = false; - /** * MobileStatusTracker constructors * @@ -78,7 +76,6 @@ public class MobileStatusTracker { * Config the MobileStatusTracker to start or stop monitoring platform signals. */ public void setListening(boolean listening) { - mListening = listening; if (listening) { mPhone.registerTelephonyCallback(mReceiverHandler::post, mTelephonyCallback); } else { @@ -86,10 +83,6 @@ public class MobileStatusTracker { } } - public boolean isListening() { - return mListening; - } - private void updateDataSim() { int activeDataSubId = mDefaults.getActiveDataSubId(); if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java index eeb1010693fca..ec0d0811ee760 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java @@ -134,9 +134,18 @@ class QuickStatusBarHeaderController extends ViewController rssiIgnoredSlots = List.of( - getResources().getString(com.android.internal.R.string.status_bar_mobile) - ); + List rssiIgnoredSlots; + + if (mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) { + rssiIgnoredSlots = List.of( + getResources().getString(com.android.internal.R.string.status_bar_no_calling), + getResources().getString(com.android.internal.R.string.status_bar_call_strength) + ); + } else { + rssiIgnoredSlots = List.of( + getResources().getString(com.android.internal.R.string.status_bar_mobile) + ); + } mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots, mInsetsProvider, mFeatureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)); diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt b/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt index e925b5472c27b..2dac639055240 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt @@ -27,6 +27,7 @@ data class CellSignalState( @JvmField val contentDescription: String? = null, @JvmField val typeContentDescription: String? = null, @JvmField val roaming: Boolean = false, + @JvmField val providerModelBehavior: Boolean = false ) { /** * Changes the visibility of this state by returning a copy with the visibility changed. @@ -40,4 +41,4 @@ data class CellSignalState( if (this.visible == visible) return this else return copy(visible = visible) } -} +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java index 703b95a082dc8..592da6554b906 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java @@ -45,7 +45,7 @@ public class QSCarrier extends LinearLayout { private View mSpacer; @Nullable private CellSignalState mLastSignalState; - private boolean mMobileSignalInitialized = false; + private boolean mProviderModelInitialized = false; private boolean mIsSingleCarrier; public QSCarrier(Context context) { @@ -96,25 +96,35 @@ public class QSCarrier extends LinearLayout { mMobileRoaming.setImageTintList(colorStateList); mMobileSignal.setImageTintList(colorStateList); - if (!mMobileSignalInitialized) { - mMobileSignalInitialized = true; - mMobileSignal.setImageDrawable(new SignalDrawable(mContext)); + if (state.providerModelBehavior) { + if (!mProviderModelInitialized) { + mProviderModelInitialized = true; + mMobileSignal.setImageDrawable( + mContext.getDrawable(R.drawable.ic_qs_no_calling_sms)); + } + mMobileSignal.setImageDrawable(mContext.getDrawable(state.mobileSignalIconId)); + mMobileSignal.setContentDescription(state.contentDescription); + } else { + if (!mProviderModelInitialized) { + mProviderModelInitialized = true; + mMobileSignal.setImageDrawable(new SignalDrawable(mContext)); + } + mMobileSignal.setImageLevel(state.mobileSignalIconId); + StringBuilder contentDescription = new StringBuilder(); + if (state.contentDescription != null) { + contentDescription.append(state.contentDescription).append(", "); + } + if (state.roaming) { + contentDescription + .append(mContext.getString(R.string.data_connection_roaming)) + .append(", "); + } + // TODO: show mobile data off/no internet text for 5 seconds before carrier text + if (hasValidTypeContentDescription(state.typeContentDescription)) { + contentDescription.append(state.typeContentDescription); + } + mMobileSignal.setContentDescription(contentDescription); } - mMobileSignal.setImageLevel(state.mobileSignalIconId); - StringBuilder contentDescription = new StringBuilder(); - if (state.contentDescription != null) { - contentDescription.append(state.contentDescription).append(", "); - } - if (state.roaming) { - contentDescription - .append(mContext.getString(R.string.data_connection_roaming)) - .append(", "); - } - // TODO: show mobile data off/no internet text for 5 seconds before carrier text - if (hasValidTypeContentDescription(state.typeContentDescription)) { - contentDescription.append(state.typeContentDescription); - } - mMobileSignal.setContentDescription(contentDescription); } return true; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java index cb76ee2bb6a1c..6908e5ab49e6a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java @@ -42,7 +42,10 @@ import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.statusbar.connectivity.IconState; import com.android.systemui.statusbar.connectivity.MobileDataIndicators; import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.connectivity.SignalCallback; @@ -75,6 +78,7 @@ public class QSCarrierGroupController { private QSCarrier[] mCarrierGroups = new QSCarrier[SIM_SLOTS]; private int[] mLastSignalLevel = new int[SIM_SLOTS]; private String[] mLastSignalLevelDescription = new String[SIM_SLOTS]; + private final boolean mProviderModel; private final CarrierConfigTracker mCarrierConfigTracker; private boolean mIsSingleCarrier; @@ -86,6 +90,9 @@ public class QSCarrierGroupController { private final SignalCallback mSignalCallback = new SignalCallback() { @Override public void setMobileDataIndicators(@NonNull MobileDataIndicators indicators) { + if (mProviderModel) { + return; + } int slotIndex = getSlotIndex(indicators.subId); if (slotIndex >= SIM_SLOTS) { Log.w(TAG, "setMobileDataIndicators - slot: " + slotIndex); @@ -100,11 +107,90 @@ public class QSCarrierGroupController { indicators.statusIcon.icon, indicators.statusIcon.contentDescription, indicators.typeContentDescription.toString(), - indicators.roaming + indicators.roaming, + mProviderModel ); mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget(); } + @Override + public void setCallIndicator(@NonNull IconState statusIcon, int subId) { + if (!mProviderModel) { + return; + } + int slotIndex = getSlotIndex(subId); + if (slotIndex >= SIM_SLOTS) { + Log.w(TAG, "setMobileDataIndicators - slot: " + slotIndex); + return; + } + if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { + Log.e(TAG, "Invalid SIM slot index for subscription: " + subId); + return; + } + + boolean displayCallStrengthIcon = + mCarrierConfigTracker.getCallStrengthConfig(subId); + + if (statusIcon.icon == R.drawable.ic_qs_no_calling_sms) { + if (statusIcon.visible) { + mInfos[slotIndex] = new CellSignalState( + true, + statusIcon.icon, + statusIcon.contentDescription, + "", + false, + mProviderModel); + } else { + // Whenever the no Calling & SMS state is cleared, switched to the last + // known call strength icon. + if (displayCallStrengthIcon) { + mInfos[slotIndex] = new CellSignalState( + true, + mLastSignalLevel[slotIndex], + mLastSignalLevelDescription[slotIndex], + "", + false, + mProviderModel); + } else { + mInfos[slotIndex] = new CellSignalState( + true, + R.drawable.ic_qs_sim_card, + "", + "", + false, + mProviderModel); + } + } + mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget(); + } else { + mLastSignalLevel[slotIndex] = statusIcon.icon; + mLastSignalLevelDescription[slotIndex] = statusIcon.contentDescription; + // Only Shows the call strength icon when the no Calling & SMS icon is not + // shown. + if (mInfos[slotIndex].mobileSignalIconId + != R.drawable.ic_qs_no_calling_sms) { + if (displayCallStrengthIcon) { + mInfos[slotIndex] = new CellSignalState( + true, + statusIcon.icon, + statusIcon.contentDescription, + "", + false, + mProviderModel); + } else { + mInfos[slotIndex] = new CellSignalState( + true, + R.drawable.ic_qs_sim_card, + "", + "", + false, + mProviderModel); + } + mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget(); + } + } + } + @Override public void setNoSims(boolean hasNoSims, boolean simDetected) { if (hasNoSims) { @@ -133,8 +219,14 @@ public class QSCarrierGroupController { @Background Handler bgHandler, @Main Looper mainLooper, NetworkController networkController, CarrierTextManager.Builder carrierTextManagerBuilder, Context context, - CarrierConfigTracker carrierConfigTracker, SlotIndexResolver slotIndexResolver) { + CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags, + SlotIndexResolver slotIndexResolver) { + if (featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) { + mProviderModel = true; + } else { + mProviderModel = false; + } mActivityStarter = activityStarter; mBgHandler = bgHandler; mNetworkController = networkController; @@ -170,7 +262,8 @@ public class QSCarrierGroupController { R.drawable.ic_qs_no_calling_sms, context.getText(AccessibilityContentDescriptions.NO_CALLING).toString(), "", - false); + false, + mProviderModel); mLastSignalLevel[i] = TelephonyIcons.MOBILE_CALL_STRENGTH_ICONS[0]; mLastSignalLevelDescription[i] = context.getText(AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]) @@ -258,7 +351,8 @@ public class QSCarrierGroupController { for (int i = 0; i < SIM_SLOTS; i++) { if (mInfos[i].visible && mInfos[i].mobileSignalIconId == R.drawable.ic_qs_sim_card) { - mInfos[i] = new CellSignalState(true, R.drawable.ic_blank, "", "", false); + mInfos[i] = new CellSignalState(true, R.drawable.ic_blank, "", "", false, + mProviderModel); } } } @@ -376,13 +470,15 @@ public class QSCarrierGroupController { private final CarrierTextManager.Builder mCarrierTextControllerBuilder; private final Context mContext; private final CarrierConfigTracker mCarrierConfigTracker; + private final FeatureFlags mFeatureFlags; private final SlotIndexResolver mSlotIndexResolver; @Inject public Builder(ActivityStarter activityStarter, @Background Handler handler, @Main Looper looper, NetworkController networkController, CarrierTextManager.Builder carrierTextControllerBuilder, Context context, - CarrierConfigTracker carrierConfigTracker, SlotIndexResolver slotIndexResolver) { + CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags, + SlotIndexResolver slotIndexResolver) { mActivityStarter = activityStarter; mHandler = handler; mLooper = looper; @@ -390,6 +486,7 @@ public class QSCarrierGroupController { mCarrierTextControllerBuilder = carrierTextControllerBuilder; mContext = context; mCarrierConfigTracker = carrierConfigTracker; + mFeatureFlags = featureFlags; mSlotIndexResolver = slotIndexResolver; } @@ -401,7 +498,7 @@ public class QSCarrierGroupController { public QSCarrierGroupController build() { return new QSCarrierGroupController(mView, mActivityStarter, mHandler, mLooper, mNetworkController, mCarrierTextControllerBuilder, mContext, - mCarrierConfigTracker, mSlotIndexResolver); + mCarrierConfigTracker, mFeatureFlags, mSlotIndexResolver); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java index 5cf1abc18274e..f3dedc4e0d6ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java @@ -26,17 +26,25 @@ import android.net.NetworkCapabilities; import android.os.Handler; import android.os.Looper; import android.provider.Settings.Global; +import android.telephony.AccessNetworkConstants; import android.telephony.CellSignalStrength; import android.telephony.CellSignalStrengthCdma; +import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.telephony.ims.ImsException; +import android.telephony.ims.ImsMmTelManager; +import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.ImsRegistrationAttributes; +import android.telephony.ims.RegistrationManager.RegistrationCallback; import android.text.Html; import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.AccessibilityContentDescriptions; import com.android.settingslib.SignalIcon.MobileIconGroup; import com.android.settingslib.graph.SignalDrawable; import com.android.settingslib.mobile.MobileMappings.Config; @@ -46,6 +54,8 @@ import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.R; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.util.CarrierConfigTracker; import java.io.PrintWriter; @@ -60,20 +70,31 @@ import java.util.Map; public class MobileSignalController extends SignalController { private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); private static final int STATUS_HISTORY_SIZE = 64; + private static final int IMS_TYPE_WWAN = 1; + private static final int IMS_TYPE_WLAN = 2; + private static final int IMS_TYPE_WLAN_CROSS_SIM = 3; private final TelephonyManager mPhone; private final CarrierConfigTracker mCarrierConfigTracker; + private final ImsMmTelManager mImsMmTelManager; private final SubscriptionDefaults mDefaults; private final String mNetworkNameDefault; private final String mNetworkNameSeparator; private final ContentObserver mObserver; + private final boolean mProviderModelBehavior; + private final Handler mReceiverHandler; + private int mImsType = IMS_TYPE_WWAN; // Save entire info for logging, we only use the id. final SubscriptionInfo mSubscriptionInfo; private Map mNetworkToIconLookup; + private int mLastLevel; private MobileIconGroup mDefaultIcons; private Config mConfig; @VisibleForTesting boolean mInflateSignalStrengths = false; + private int mLastWwanLevel; + private int mLastWlanLevel; + private int mLastWlanCrossSimLevel; @VisibleForTesting final MobileStatusTracker mMobileStatusTracker; @@ -112,6 +133,52 @@ public class MobileSignalController extends SignalController mCurrentState.connected = mWifiTracker.connected; mCurrentState.ssid = mWifiTracker.ssid; mCurrentState.rssi = mWifiTracker.rssi; + boolean levelChanged = mCurrentState.level != mWifiTracker.level; mCurrentState.level = mWifiTracker.level; mCurrentState.statusLabel = mWifiTracker.statusLabel; mCurrentState.isCarrierMerged = mWifiTracker.isCarrierMerged; @@ -229,6 +230,10 @@ public class WifiSignalController extends SignalController mCurrentState.iconGroup = mCurrentState.isCarrierMerged ? mCarrierMergedWifiIconGroup : mUnmergedWifiIconGroup; + + if (levelChanged) { + mNetworkController.notifyWifiLevelChange(mCurrentState.level); + } } boolean isCarrierMergedWifi(int subId) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java index 492734e93dcac..ee242a4b1b751 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java @@ -26,6 +26,8 @@ import android.util.Log; import com.android.settingslib.mobile.TelephonyIcons; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.statusbar.connectivity.IconState; import com.android.systemui.statusbar.connectivity.MobileDataIndicators; import com.android.systemui.statusbar.connectivity.NetworkController; @@ -64,6 +66,7 @@ public class StatusBarSignalPolicy implements SignalCallback, private final Handler mHandler = Handler.getMain(); private final CarrierConfigTracker mCarrierConfigTracker; private final TunerService mTunerService; + private final FeatureFlags mFeatureFlags; private boolean mHideAirplane; private boolean mHideMobile; @@ -87,7 +90,8 @@ public class StatusBarSignalPolicy implements SignalCallback, CarrierConfigTracker carrierConfigTracker, NetworkController networkController, SecurityController securityController, - TunerService tunerService + TunerService tunerService, + FeatureFlags featureFlags ) { mContext = context; @@ -96,6 +100,7 @@ public class StatusBarSignalPolicy implements SignalCallback, mNetworkController = networkController; mSecurityController = securityController; mTunerService = tunerService; + mFeatureFlags = featureFlags; mSlotAirplane = mContext.getString(com.android.internal.R.string.status_bar_airplane); mSlotMobile = mContext.getString(com.android.internal.R.string.status_bar_mobile); @@ -372,6 +377,40 @@ public class StatusBarSignalPolicy implements SignalCallback, // Noop yay! } + @Override + public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork, + boolean noNetworksAvailable) { + if (!mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) { + return; + } + if (DEBUG) { + Log.d(TAG, "setConnectivityStatus: " + + "noDefaultNetwork = " + noDefaultNetwork + "," + + "noValidatedNetwork = " + noValidatedNetwork + "," + + "noNetworksAvailable = " + noNetworksAvailable); + } + WifiIconState newState = mWifiIconState.copy(); + newState.noDefaultNetwork = noDefaultNetwork; + newState.noValidatedNetwork = noValidatedNetwork; + newState.noNetworksAvailable = noNetworksAvailable; + newState.slot = mSlotWifi; + newState.airplaneSpacerVisible = mIsAirplaneMode; + if (noDefaultNetwork && noNetworksAvailable && !mIsAirplaneMode) { + newState.visible = true; + newState.resId = R.drawable.ic_qs_no_internet_unavailable; + } else if (noDefaultNetwork && !noNetworksAvailable + && (!mIsAirplaneMode || (mIsAirplaneMode && mIsWifiEnabled))) { + newState.visible = true; + newState.resId = R.drawable.ic_qs_no_internet_available; + } else { + newState.visible = false; + newState.resId = 0; + } + updateWifiIconWithState(newState); + mWifiIconState = newState; + } + + @Override public void setEthernetIndicators(IconState state) { boolean visible = state.visible && !mHideEthernet; diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt index be14cc51ef969..07c8af953d1e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt @@ -26,6 +26,7 @@ import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.colorextraction.SysuiColorExtractor import com.android.systemui.demomode.DemoModeController import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.qs.carrier.QSCarrierGroup import com.android.systemui.qs.carrier.QSCarrierGroupController import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider @@ -45,10 +46,10 @@ import org.junit.runner.RunWith import org.mockito.Answers import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock +import org.mockito.Mockito.`when` import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.reset import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @@ -161,6 +162,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { @Test fun testRSSISlot_notCombined() { + `when`(featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)).thenReturn(false) controller.init() val captor = argumentCaptor>() @@ -171,6 +173,20 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { ) } + @Test + fun testRSSISlot_combined() { + `when`(featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)).thenReturn(true) + controller.init() + + val captor = argumentCaptor>() + verify(view).onAttach(any(), any(), capture(captor), any(), anyBoolean()) + + assertThat(captor.value).containsExactly( + mContext.getString(com.android.internal.R.string.status_bar_no_calling), + mContext.getString(com.android.internal.R.string.status_bar_call_strength) + ) + } + @Test fun testSingleCarrierCallback() { controller.init() diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java index 1963e30e741e1..bd794d6813ec2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java @@ -37,6 +37,7 @@ import android.widget.TextView; import androidx.test.filters.SmallTest; import com.android.keyguard.CarrierTextManager; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.connectivity.IconState; import com.android.systemui.statusbar.connectivity.MobileDataIndicators; @@ -79,6 +80,7 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest { @Mock private QSCarrier mQSCarrier3; private TestableLooper mTestableLooper; + @Mock private FeatureFlags mFeatureFlags; @Mock private QSCarrierGroupController.OnSingleCarrierChangedListener mOnSingleCarrierChangedListener; @@ -118,7 +120,7 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest { mQSCarrierGroupController = new QSCarrierGroupController.Builder( mActivityStarter, handler, TestableLooper.get(this).getLooper(), mNetworkController, mCarrierTextControllerBuilder, mContext, mCarrierConfigTracker, - mSlotIndexResolver) + mFeatureFlags, mSlotIndexResolver) .setQSCarrierGroup(mQSCarrierGroup) .build(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java index 99a17a613041e..5212255078fc8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java @@ -22,11 +22,13 @@ import static org.junit.Assert.assertTrue; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.util.FeatureFlagUtils; import android.view.LayoutInflater; import android.view.View; import androidx.test.filters.SmallTest; +import com.android.settingslib.graph.SignalDrawable; import com.android.settingslib.mobile.TelephonyIcons; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; @@ -57,14 +59,14 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_first() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); assertTrue(mQSCarrier.updateState(c, false)); } @Test public void testUpdateState_same() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); assertTrue(mQSCarrier.updateState(c, false)); assertFalse(mQSCarrier.updateState(c, false)); @@ -72,7 +74,7 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_changed() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); assertTrue(mQSCarrier.updateState(c, false)); @@ -83,14 +85,14 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_singleCarrier_first() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); assertTrue(mQSCarrier.updateState(c, true)); } @Test public void testUpdateState_singleCarrier_noShowIcon() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); mQSCarrier.updateState(c, true); @@ -99,7 +101,7 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_multiCarrier_showIcon() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); mQSCarrier.updateState(c, false); @@ -108,7 +110,7 @@ public class QSCarrierTest extends SysuiTestCase { @Test public void testUpdateState_changeSingleMultiSingle() { - CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false); + CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false); mQSCarrier.updateState(c, true); assertEquals(View.GONE, mQSCarrier.getRSSIView().getVisibility()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java index f8a0d2fc415c0..8808502ba0df3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java @@ -70,6 +70,8 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.log.LogBuffer; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; @@ -125,6 +127,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected CarrierConfigTracker mCarrierConfigTracker; protected FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); protected Handler mMainHandler; + protected FeatureFlags mFeatureFlags; protected WifiStatusTrackerFactory mWifiStatusTrackerFactory; protected MobileSignalControllerFactory mMobileFactory; @@ -156,6 +159,9 @@ public class NetworkControllerBaseTest extends SysuiTestCase { @Before public void setUp() throws Exception { + mFeatureFlags = mock(FeatureFlags.class); + when(mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)).thenReturn(false); + mInstrumentation = InstrumentationRegistry.getInstrumentation(); Settings.Global.putInt(mContext.getContentResolver(), Global.AIRPLANE_MODE_ON, 0); TestableResources res = mContext.getOrCreateTestableResources(); @@ -222,7 +228,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mMobileFactory = new MobileSignalControllerFactory( mContext, mCallbackHandler, - mCarrierConfigTracker + mCarrierConfigTracker, + mFeatureFlags ); mNetworkController = new NetworkControllerImpl(mContext, @@ -245,6 +252,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class) ); @@ -438,6 +446,10 @@ public class NetworkControllerBaseTest extends SysuiTestCase { updateSignalStrength(); } + public void setImsType(int imsType) { + mMobileSignalController.setImsType(imsType); + } + public void setIsGsm(boolean gsm) { when(mSignalStrength.isGsm()).thenReturn(gsm); updateSignalStrength(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java index ed8a3e16cdd14..f3edef434ed4c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java @@ -147,6 +147,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, new Handler(TestableLooper.get(this).getLooper()), + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); setupNetworkController(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java index a76676e01c150..f60b6d1997be0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java @@ -87,6 +87,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class) ); @@ -123,6 +124,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); TestableLooper.get(this).processAllMessages(); @@ -157,6 +159,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); setupNetworkController(); @@ -194,6 +197,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); mNetworkController.registerListeners(); @@ -279,6 +283,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mWifiStatusTrackerFactory, mMobileFactory, mMainHandler, + mFeatureFlags, mock(DumpManager.class), mock(LogBuffer.class)); setupNetworkController(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java index 68170ea4b518e..3f71491592477 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java @@ -30,6 +30,7 @@ import android.net.NetworkInfo; import android.net.vcn.VcnTransportInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.telephony.CellSignalStrength; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; @@ -284,6 +285,44 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { verifyLastMobileDataIndicatorsForVcn(false, 1, 0, false); } + @Test + public void testCallStrengh() { + if (true) return; + String testSsid = "Test SSID"; + setWifiEnabled(true); + setWifiState(true, testSsid); + // Set the ImsType to be IMS_TYPE_WLAN + setImsType(2); + setWifiLevel(1); + for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) { + setWifiLevel(testLevel); + verifyLastCallStrength(TelephonyIcons.WIFI_CALL_STRENGTH_ICONS[testLevel]); + } + // Set the ImsType to be IMS_TYPE_WWAN + setImsType(1); + setupDefaultSignal(); + for (int testStrength = 0; + testStrength < CellSignalStrength.getNumSignalStrengthLevels(); testStrength++) { + setLevel(testStrength); + verifyLastCallStrength(TelephonyIcons.MOBILE_CALL_STRENGTH_ICONS[testStrength]); + } + } + + @Test + public void testNonPrimaryWiFi() { + if (true) return; + String testSsid = "Test SSID"; + setWifiEnabled(true); + setWifiState(true, testSsid); + // Set the ImsType to be IMS_TYPE_WLAN + setImsType(2); + setWifiLevel(1); + verifyLastCallStrength(TelephonyIcons.WIFI_CALL_STRENGTH_ICONS[1]); + when(mWifiInfo.isPrimary()).thenReturn(false); + setWifiLevel(3); + verifyLastCallStrength(TelephonyIcons.WIFI_CALL_STRENGTH_ICONS[1]); + } + protected void setWifiActivity(int activity) { // TODO: Not this, because this variable probably isn't sticking around. mNetworkController.mWifiSignalController.setActivity(activity); From 4bcc776f46282127d26f8a9552a455d846766115 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 14/45] Revert "Create a MobileStatusTrackerFactory" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: Iccec69e2697f6638a6ef07e86bb9303641ef7167 (cherry picked from commit d611126474130e657ab8f70e91c861a40b80f86c) Merged-In: Iccec69e2697f6638a6ef07e86bb9303641ef7167 --- .../connectivity/MobileSignalController.java | 6 +-- .../MobileSignalControllerFactory.kt | 7 ---- .../MobileStatusTrackerFactory.kt | 42 ------------------- 3 files changed, 3 insertions(+), 52 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileStatusTrackerFactory.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java index f3dedc4e0d6ee..9d8667a3ccb08 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java @@ -96,7 +96,7 @@ public class MobileSignalController extends SignalController Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 15/45] Revert "Change from deprecated telephony api" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: I6b1a152d01eeb938b2e1a286e69e2994775ceb43 (cherry picked from commit 9d7f532671abb5f3290828e0da4e948a8ac092ca) Merged-In: I6b1a152d01eeb938b2e1a286e69e2994775ceb43 --- .../systemui/qs/tiles/dialog/InternetDialogController.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index 3c8775d01e2d6..f1fdae7db4825 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -778,8 +778,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi return; } - mTelephonyManager.setDataEnabledForReason( - TelephonyManager.DATA_ENABLED_REASON_USER, enabled); + mTelephonyManager.setDataEnabled(enabled); if (disableOtherSubscriptions) { final List subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); From 1800e48f6e29d5001952d1f10c80a558f0d8a275 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 16/45] Revert "[Cleanup] Order NetworkController's intent filters" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: Id6b03a4423b6b34f469cc6d749b0433e35e8b281 (cherry picked from commit 40f9d90bc607194ab0bd05b2442deb30b7b36fb8) Merged-In: Id6b03a4423b6b34f469cc6d749b0433e35e8b281 --- .../connectivity/NetworkControllerImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java index 6be347b55bc51..8a84ba12fa1cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java @@ -503,16 +503,16 @@ public class NetworkControllerImpl extends BroadcastReceiver // broadcasts IntentFilter filter = new IntentFilter(); - filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); - filter.addAction(Intent.ACTION_SERVICE_STATE); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(Intent.ACTION_SIM_STATE_CHANGED); - filter.addAction(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); + filter.addAction(Intent.ACTION_SERVICE_STATE); filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED); - filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); + filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); + filter.addAction(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler); mListening = true; From 7077e6b6fc1a5b3fe6358df568dfb5e786870cb1 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Tue, 26 Jul 2022 21:10:38 +0000 Subject: [PATCH 17/45] Revert "Add an @Inject-able MobileSignalControllerFactory" Revert submission 19279477 Reason for revert: b/240223150 Reverted Changes: I1bef3f309:Remove support for COMBINED_SIGNAL_ICONS I38f76a746:Create a MobileStatusTrackerFactory I0b1dd8e71:Change from deprecated telephony api Id1a02134f:[Cleanup] Order NetworkController's intent filters... I405ad3858:Add an @Inject-able MobileSignalControllerFactory Change-Id: Ic004e4164580d19914912e6fb8d8951cd075f9e9 (cherry picked from commit b1971c7747b58a049761137898e424c925347c9c) Merged-In: Ic004e4164580d19914912e6fb8d8951cd075f9e9 --- .../MobileSignalControllerFactory.kt | 60 ------------------- .../connectivity/NetworkControllerImpl.java | 41 ++++--------- .../NetworkControllerBaseTest.java | 9 +-- .../NetworkControllerDataTest.java | 1 - .../NetworkControllerSignalTest.java | 5 -- 5 files changed, 14 insertions(+), 102 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt deleted file mode 100644 index fa1333073f37f..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.systemui.statusbar.connectivity - -import android.content.Context -import android.os.Looper -import android.telephony.SubscriptionInfo -import android.telephony.TelephonyManager -import com.android.settingslib.mobile.MobileMappings -import com.android.settingslib.mobile.MobileStatusTracker -import com.android.systemui.flags.FeatureFlags -import com.android.systemui.util.CarrierConfigTracker -import javax.inject.Inject - -/** - * Factory to make MobileSignalController injectable - */ -internal class MobileSignalControllerFactory @Inject constructor( - val context: Context, - val callbackHandler: CallbackHandler, - val carrierConfigTracker: CarrierConfigTracker, - val featureFlags: FeatureFlags, -) { - fun createMobileSignalController( - config: MobileMappings.Config, - hasMobileData: Boolean, - phone: TelephonyManager, - networkController: NetworkControllerImpl, // TODO: no! - subscriptionInfo: SubscriptionInfo, - subscriptionDefaults: MobileStatusTracker.SubscriptionDefaults, - receiverLooper: Looper // TODO: no! - ): MobileSignalController { - return MobileSignalController( - context, - config, - hasMobileData, - phone, - callbackHandler, - networkController, - subscriptionInfo, - subscriptionDefaults, - receiverLooper, - carrierConfigTracker, - featureFlags, - ) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java index 8a84ba12fa1cc..a1dc7b41d42bf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java @@ -140,7 +140,6 @@ public class NetworkControllerImpl extends BroadcastReceiver private final FeatureFlags mFeatureFlags; private final DumpManager mDumpManager; private final LogBuffer mLogBuffer; - private final MobileSignalControllerFactory mMobileFactory; private TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener; private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -236,7 +235,6 @@ public class NetworkControllerImpl extends BroadcastReceiver DemoModeController demoModeController, CarrierConfigTracker carrierConfigTracker, WifiStatusTrackerFactory trackerFactory, - MobileSignalControllerFactory mobileFactory, @Main Handler handler, InternetDialogFactory internetDialogFactory, FeatureFlags featureFlags, @@ -259,7 +257,6 @@ public class NetworkControllerImpl extends BroadcastReceiver demoModeController, carrierConfigTracker, trackerFactory, - mobileFactory, handler, featureFlags, dumpManager, @@ -286,7 +283,6 @@ public class NetworkControllerImpl extends BroadcastReceiver DemoModeController demoModeController, CarrierConfigTracker carrierConfigTracker, WifiStatusTrackerFactory trackerFactory, - MobileSignalControllerFactory mobileFactory, @Main Handler handler, FeatureFlags featureFlags, DumpManager dumpManager, @@ -302,7 +298,6 @@ public class NetworkControllerImpl extends BroadcastReceiver mCallbackHandler = callbackHandler; mDataSaverController = new DataSaverControllerImpl(context); mBroadcastDispatcher = broadcastDispatcher; - mMobileFactory = mobileFactory; mSubscriptionManager = subManager; mSubDefaults = defaultsHandler; @@ -987,15 +982,11 @@ public class NetworkControllerImpl extends BroadcastReceiver mMobileSignalControllers.put(subId, cachedControllers.get(subId)); cachedControllers.remove(subId); } else { - MobileSignalController controller = mMobileFactory.createMobileSignalController( - mConfig, - mHasMobileDataFeature, - mPhone.createForSubscriptionId(subId), - this, - subscriptions.get(i), - mSubDefaults, - mReceiverHandler.getLooper() - ); + MobileSignalController controller = new MobileSignalController(mContext, mConfig, + mHasMobileDataFeature, mPhone.createForSubscriptionId(subId), + mCallbackHandler, this, subscriptions.get(i), + mSubDefaults, mReceiverHandler.getLooper(), mCarrierConfigTracker, + mFeatureFlags); controller.setUserSetupComplete(mUserSetup); mMobileSignalControllers.put(subId, controller); if (subscriptions.get(i).getSimSlotIndex() == 0) { @@ -1356,7 +1347,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mMobileSignalControllers.clear(); int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); for (int i = start /* get out of normal index range */; i < start + num; i++) { - subs.add(addDemoModeSignalController(i, i)); + subs.add(addSignalController(i, i)); } mCallbackHandler.setSubs(subs); for (int i = 0; i < mMobileSignalControllers.size(); i++) { @@ -1382,7 +1373,7 @@ public class NetworkControllerImpl extends BroadcastReceiver List subs = new ArrayList<>(); while (mMobileSignalControllers.size() <= slot) { int nextSlot = mMobileSignalControllers.size(); - subs.add(addDemoModeSignalController(nextSlot, nextSlot)); + subs.add(addSignalController(nextSlot, nextSlot)); } if (!subs.isEmpty()) { mCallbackHandler.setSubs(subs); @@ -1472,20 +1463,14 @@ public class NetworkControllerImpl extends BroadcastReceiver mHistoryIndex = (mHistoryIndex + 1) % HISTORY_SIZE; } - private SubscriptionInfo addDemoModeSignalController(int id, int simSlotIndex) { + private SubscriptionInfo addSignalController(int id, int simSlotIndex) { SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0, null, null, null, "", false, null, null); - - MobileSignalController controller = mMobileFactory.createMobileSignalController( - mConfig, - mHasMobileDataFeature, - mPhone.createForSubscriptionId(info.getSubscriptionId()), - this, - info, - mSubDefaults, - mReceiverHandler.getLooper() - ); - + MobileSignalController controller = new MobileSignalController(mContext, + mConfig, mHasMobileDataFeature, + mPhone.createForSubscriptionId(info.getSubscriptionId()), mCallbackHandler, this, + info, mSubDefaults, mReceiverHandler.getLooper(), mCarrierConfigTracker, + mFeatureFlags); mMobileSignalControllers.put(id, controller); controller.getState().userSetup = true; return info; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java index 8808502ba0df3..0d1879cb25939 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java @@ -129,7 +129,6 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected Handler mMainHandler; protected FeatureFlags mFeatureFlags; protected WifiStatusTrackerFactory mWifiStatusTrackerFactory; - protected MobileSignalControllerFactory mMobileFactory; protected int mSubId; @@ -225,12 +224,6 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mWifiStatusTrackerFactory = new WifiStatusTrackerFactory( mContext, mMockWm, mMockNsm, mMockCm, mMainHandler); - mMobileFactory = new MobileSignalControllerFactory( - mContext, - mCallbackHandler, - mCarrierConfigTracker, - mFeatureFlags - ); mNetworkController = new NetworkControllerImpl(mContext, mMockCm, @@ -250,7 +243,6 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mDemoModeController, mCarrierConfigTracker, mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -645,4 +637,5 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected void assertDataNetworkNameEquals(String expected) { assertEquals("Data network name", expected, mNetworkController.getMobileDataNetworkName()); } + } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java index f3edef434ed4c..e3dd6f4e6e406 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java @@ -145,7 +145,6 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mDemoModeController, mock(CarrierConfigTracker.class), mWifiStatusTrackerFactory, - mMobileFactory, new Handler(TestableLooper.get(this).getLooper()), mFeatureFlags, mock(DumpManager.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java index f60b6d1997be0..698899a8fc36f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java @@ -85,7 +85,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mCarrierConfigTracker, mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -122,7 +121,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mCarrierConfigTracker, mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -157,7 +155,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mock(CarrierConfigTracker.class), mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -195,7 +192,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mock(CarrierConfigTracker.class), mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), @@ -281,7 +277,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mDemoModeController, mock(CarrierConfigTracker.class), mWifiStatusTrackerFactory, - mMobileFactory, mMainHandler, mFeatureFlags, mock(DumpManager.class), From a038fb0766d00b282806e7dc04cfc87388136328 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 24 Aug 2022 12:22:12 +0000 Subject: [PATCH 18/45] Revert^3 "Fix binder error when an app has many channels" f6d322577af7231c28d398096b3ca9b88260fa49 Change-Id: Ib42bf11c154e287119a5af0a4f92510cfb3a6cc7 (cherry picked from commit 6e662a45b543873892af32b9e7b5bcf736374df9) Merged-In: Ib42bf11c154e287119a5af0a4f92510cfb3a6cc7 --- .../android/app/NotificationChannelGroup.java | 21 ++++--- .../row/ChannelEditorDialogControllerTest.kt | 2 +- .../notification/PreferencesHelper.java | 55 ++++++++----------- .../notification/PreferencesHelperTest.java | 30 ---------- 4 files changed, 37 insertions(+), 71 deletions(-) diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 807bd5764cba5..2b245aae915f1 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -20,7 +20,6 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Intent; -import android.content.pm.ParceledListSlice; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -68,7 +67,7 @@ public final class NotificationChannelGroup implements Parcelable { private CharSequence mName; private String mDescription; private boolean mBlocked; - private ParceledListSlice mChannels; + private List mChannels = new ArrayList<>(); // Bitwise representation of fields that have been changed by the user private int mUserLockedFields; @@ -103,8 +102,7 @@ public final class NotificationChannelGroup implements Parcelable { } else { mDescription = null; } - mChannels = in.readParcelable( - NotificationChannelGroup.class.getClassLoader(), ParceledListSlice.class); + in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader(), android.app.NotificationChannel.class); mBlocked = in.readBoolean(); mUserLockedFields = in.readInt(); } @@ -131,7 +129,7 @@ public final class NotificationChannelGroup implements Parcelable { } else { dest.writeByte((byte) 0); } - dest.writeParcelable(mChannels, flags); + dest.writeParcelableList(mChannels, flags); dest.writeBoolean(mBlocked); dest.writeInt(mUserLockedFields); } @@ -161,7 +159,7 @@ public final class NotificationChannelGroup implements Parcelable { * Returns the list of channels that belong to this group */ public List getChannels() { - return mChannels == null ? new ArrayList<>() : mChannels.getList(); + return mChannels; } /** @@ -192,11 +190,18 @@ public final class NotificationChannelGroup implements Parcelable { mBlocked = blocked; } + /** + * @hide + */ + public void addChannel(NotificationChannel channel) { + mChannels.add(channel); + } + /** * @hide */ public void setChannels(List channels) { - mChannels = new ParceledListSlice<>(channels); + mChannels = channels; } /** @@ -331,7 +336,7 @@ public final class NotificationChannelGroup implements Parcelable { proto.write(NotificationChannelGroupProto.NAME, mName.toString()); proto.write(NotificationChannelGroupProto.DESCRIPTION, mDescription); proto.write(NotificationChannelGroupProto.IS_BLOCKED, mBlocked); - for (NotificationChannel channel : mChannels.getList()) { + for (NotificationChannel channel : mChannels) { channel.dumpDebug(proto, NotificationChannelGroupProto.CHANNELS); } proto.end(token); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt index 214ba16dfc44b..64d0256287541 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt @@ -98,7 +98,7 @@ class ChannelEditorDialogControllerTest : SysuiTestCase() { @Test fun testPrepareDialogForApp_onlyDefaultChannel() { - group.channels = listOf(channelDefault) + group.addChannel(channelDefault) controller.prepareDialogForApp(TEST_APP_NAME, TEST_PACKAGE_NAME, TEST_UID, setOf(channelDefault), appIcon, clickListener) diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 729c521a4ce07..477b8da61e0f5 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -86,7 +86,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -1328,17 +1327,16 @@ public class PreferencesHelper implements RankingConfig { return null; } NotificationChannelGroup group = r.groups.get(groupId).clone(); - ArrayList channels = new ArrayList(); + group.setChannels(new ArrayList<>()); int N = r.channels.size(); for (int i = 0; i < N; i++) { final NotificationChannel nc = r.channels.valueAt(i); if (includeDeleted || !nc.isDeleted()) { if (groupId.equals(nc.getGroup())) { - channels.add(nc); + group.addChannel(nc); } } } - group.setChannels(channels); return group; } } @@ -1351,10 +1349,7 @@ public class PreferencesHelper implements RankingConfig { if (r == null) { return null; } - if (r.groups.get(groupId) != null) { - return r.groups.get(groupId).clone(); - } - return null; + return r.groups.get(groupId); } } @@ -1362,48 +1357,44 @@ public class PreferencesHelper implements RankingConfig { public ParceledListSlice getNotificationChannelGroups(String pkg, int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) { Objects.requireNonNull(pkg); - List groups = new ArrayList<>(); + Map groups = new ArrayMap<>(); synchronized (mPackagePreferences) { PackagePreferences r = getPackagePreferencesLocked(pkg, uid); if (r == null) { return ParceledListSlice.emptyList(); } - Map> groupedChannels = new HashMap(); + NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null); int N = r.channels.size(); for (int i = 0; i < N; i++) { final NotificationChannel nc = r.channels.valueAt(i); if (includeDeleted || !nc.isDeleted()) { if (nc.getGroup() != null) { if (r.groups.get(nc.getGroup()) != null) { - ArrayList channels = groupedChannels.getOrDefault( - nc.getGroup(), new ArrayList<>()); - channels.add(nc); - groupedChannels.put(nc.getGroup(), channels); + NotificationChannelGroup ncg = groups.get(nc.getGroup()); + if (ncg == null) { + ncg = r.groups.get(nc.getGroup()).clone(); + ncg.setChannels(new ArrayList<>()); + groups.put(nc.getGroup(), ncg); + + } + ncg.addChannel(nc); } } else { - ArrayList channels = groupedChannels.getOrDefault( - null, new ArrayList<>()); - channels.add(nc); - groupedChannels.put(null, channels); + nonGrouped.addChannel(nc); } } } - for (NotificationChannelGroup group : r.groups.values()) { - ArrayList channels = - groupedChannels.getOrDefault(group.getId(), new ArrayList<>()); - if (includeEmpty || !channels.isEmpty()) { - NotificationChannelGroup clone = group.clone(); - clone.setChannels(channels); - groups.add(clone); + if (includeNonGrouped && nonGrouped.getChannels().size() > 0) { + groups.put(null, nonGrouped); + } + if (includeEmpty) { + for (NotificationChannelGroup group : r.groups.values()) { + if (!groups.containsKey(group.getId())) { + groups.put(group.getId(), group); + } } } - - if (includeNonGrouped && groupedChannels.containsKey(null)) { - NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null); - nonGrouped.setChannels(groupedChannels.get(null)); - groups.add(nonGrouped); - } - return new ParceledListSlice<>(groups); + return new ParceledListSlice<>(new ArrayList<>(groups.values())); } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index d62ac99e530bf..598a22bbde393 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -93,7 +93,6 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; -import android.os.Parcel; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; @@ -2447,35 +2446,6 @@ public class PreferencesHelperTest extends UiServiceTestCase { mLogger.get(6).event); // Final log is the deletion of the channel. } - @Test - public void testGetNotificationChannelGroup() throws Exception { - NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted"); - NotificationChannel base = - new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT); - base.setGroup("not"); - NotificationChannel convo = - new NotificationChannel("convo", "belongs to notDeleted", IMPORTANCE_DEFAULT); - convo.setGroup("not"); - convo.setConversationId("not deleted", "banana"); - - mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, notDeleted, true); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, base, true, false); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, convo, true, false); - mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, notDeleted, true); - - NotificationChannelGroup g - = mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG_N_MR1, UID_N_MR1); - Parcel parcel = Parcel.obtain(); - g.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - - NotificationChannelGroup g2 - = mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG_N_MR1, UID_N_MR1); - Parcel parcel2 = Parcel.obtain(); - g2.writeToParcel(parcel2, 0); - parcel2.setDataPosition(0); - } - @Test public void testOnUserRemoved() throws Exception { int[] user0Uids = {98, 235, 16, 3782}; From c1cad4f689c524905c544c48538479ac504e544c Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Wed, 24 Aug 2022 21:02:37 +0000 Subject: [PATCH 19/45] Revert "Remove BatteryStats user activity types and use PowerManager ones instead." This reverts commit 79e517c3d45ce704ff43f068fbb63d24ab4693c6. Reason for revert: b/243434675 Change-Id: Ie2476f23715ed933064470ee2f50d550e92d46b8 (cherry picked from commit c969b1a51b23597add887c337aefac7ea4ebe537) Merged-In: Ie2476f23715ed933064470ee2f50d550e92d46b8 --- core/java/android/os/BatteryStats.java | 13 +++++- core/java/android/os/PowerManager.java | 38 ---------------- .../android/internal/os/BatteryStatsImpl.java | 11 +++-- .../com/android/server/power/Notifier.java | 3 +- .../com/android/server/power/PowerGroup.java | 27 +++--------- .../server/power/PowerManagerService.java | 44 +++++++------------ 6 files changed, 41 insertions(+), 95 deletions(-) diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 801d34d9d8848..06c35b5bec5d9 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -956,7 +956,16 @@ public abstract class BatteryStats implements Parcelable { public static final int NUM_WIFI_BATCHED_SCAN_BINS = 5; - public static final int NUM_USER_ACTIVITY_TYPES = PowerManager.USER_ACTIVITY_EVENT_MAX + 1; + /** + * Note that these must match the constants in android.os.PowerManager. + * Also, if the user activity types change, the BatteryStatsImpl.VERSION must + * also be bumped. + */ + static final String[] USER_ACTIVITY_TYPES = { + "other", "button", "touch", "accessibility", "attention" + }; + + public static final int NUM_USER_ACTIVITY_TYPES = USER_ACTIVITY_TYPES.length; public abstract void noteUserActivityLocked(int type); public abstract boolean hasUserActivity(); @@ -6168,7 +6177,7 @@ public abstract class BatteryStats implements Parcelable { } sb.append(val); sb.append(" "); - sb.append(PowerManager.userActivityEventToString(i)); + sb.append(Uid.USER_ACTIVITY_TYPES[i]); } } if (hasData) { diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 8a203e07ae6dd..13ca2c34b27ec 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -344,44 +344,6 @@ public final class PowerManager { */ public static final int USER_ACTIVITY_EVENT_DEVICE_STATE = 6; - /** - * @hide - */ - public static final int USER_ACTIVITY_EVENT_MAX = USER_ACTIVITY_EVENT_DEVICE_STATE; - - /** - * @hide - */ - @IntDef(prefix = { "USER_ACTIVITY_EVENT_" }, value = { - USER_ACTIVITY_EVENT_OTHER, - USER_ACTIVITY_EVENT_BUTTON, - USER_ACTIVITY_EVENT_TOUCH, - USER_ACTIVITY_EVENT_ACCESSIBILITY, - USER_ACTIVITY_EVENT_ATTENTION, - USER_ACTIVITY_EVENT_FACE_DOWN, - USER_ACTIVITY_EVENT_DEVICE_STATE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface UserActivityEvent{} - - /** - * - * Convert the user activity event to a string for debugging purposes. - * @hide - */ - public static String userActivityEventToString(@UserActivityEvent int userActivityEvent) { - switch (userActivityEvent) { - case USER_ACTIVITY_EVENT_OTHER: return "other"; - case USER_ACTIVITY_EVENT_BUTTON: return "button"; - case USER_ACTIVITY_EVENT_TOUCH: return "touch"; - case USER_ACTIVITY_EVENT_ACCESSIBILITY: return "accessibility"; - case USER_ACTIVITY_EVENT_ATTENTION: return "attention"; - case USER_ACTIVITY_EVENT_FACE_DOWN: return "faceDown"; - case USER_ACTIVITY_EVENT_DEVICE_STATE: return "deviceState"; - default: return Integer.toString(userActivityEvent); - } - } - /** * User activity flag: If already dimmed, extend the dim timeout * but do not brighten. This flag is useful for keeping the screen on diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 06473b5ee8dee..98d4c5976adc8 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -6144,8 +6144,7 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("this") - public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event, - long elapsedRealtimeMs, long uptimeMs) { + public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) { if (mOnBatteryInternal) { uid = mapUid(uid); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event); @@ -9957,14 +9956,14 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) { + public void noteUserActivityLocked(int type) { if (mUserActivityCounters == null) { initUserActivityLocked(); } - if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) { - mUserActivityCounters[event].stepAtomic(); + if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) { + mUserActivityCounters[type].stepAtomic(); } else { - Slog.w(TAG, "Unknown user activity event " + event + " was specified.", + Slog.w(TAG, "Unknown user activity type " + type + " was specified.", new Throwable()); } } diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index dad9584c67225..5a2fb18673ac1 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -571,8 +571,7 @@ public class Notifier { /** * Called when there has been user activity. */ - public void onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event, - int uid) { + public void onUserActivity(int displayGroupId, int event, int uid) { if (DEBUG) { Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid); } diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java index 9fe53fbfaf255..fec61ac8f2cf0 100644 --- a/services/core/java/com/android/server/power/PowerGroup.java +++ b/services/core/java/com/android/server/power/PowerGroup.java @@ -74,8 +74,6 @@ public class PowerGroup { private long mLastPowerOnTime; private long mLastUserActivityTime; private long mLastUserActivityTimeNoChangeLights; - @PowerManager.UserActivityEvent - private int mLastUserActivityEvent; /** Timestamp (milliseconds since boot) of the last time the power group was awoken.*/ private long mLastWakeTime; /** Timestamp (milliseconds since boot) of the last time the power group was put to sleep. */ @@ -246,7 +244,7 @@ public class PowerGroup { return true; } - boolean dozeLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) { + boolean dozeLocked(long eventTime, int uid, int reason) { if (eventTime < getLastWakeTimeLocked() || !isInteractive(mWakefulness)) { return false; } @@ -255,14 +253,9 @@ public class PowerGroup { try { reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX, Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN)); - long millisSinceLastUserActivity = eventTime - Math.max( - mLastUserActivityTimeNoChangeLights, mLastUserActivityTime); Slog.i(TAG, "Powering off display group due to " - + PowerManager.sleepReasonToString(reason) - + " (groupId= " + getGroupId() + ", uid= " + uid - + ", millisSinceLastUserActivity=" + millisSinceLastUserActivity - + ", lastUserActivityEvent=" + PowerManager.userActivityEventToString( - mLastUserActivityEvent) + ")..."); + + PowerManager.sleepReasonToString(reason) + " (groupId= " + getGroupId() + + ", uid= " + uid + ")..."); setSandmanSummonedLocked(/* isSandmanSummoned= */ true); setWakefulnessLocked(WAKEFULNESS_DOZING, eventTime, uid, reason, /* opUid= */ 0, @@ -273,16 +266,14 @@ public class PowerGroup { return true; } - boolean sleepLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) { + boolean sleepLocked(long eventTime, int uid, int reason) { if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) { return false; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "sleepPowerGroup"); try { - Slog.i(TAG, - "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ", reason=" - + PowerManager.sleepReasonToString(reason) + ")..."); + Slog.i(TAG, "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ")..."); setSandmanSummonedLocked(/* isSandmanSummoned= */ true); setWakefulnessLocked(WAKEFULNESS_ASLEEP, eventTime, uid, reason, /* opUid= */0, /* opPackageName= */ null, /* details= */ null); @@ -296,20 +287,16 @@ public class PowerGroup { return mLastUserActivityTime; } - void setLastUserActivityTimeLocked(long lastUserActivityTime, - @PowerManager.UserActivityEvent int event) { + void setLastUserActivityTimeLocked(long lastUserActivityTime) { mLastUserActivityTime = lastUserActivityTime; - mLastUserActivityEvent = event; } public long getLastUserActivityTimeNoChangeLightsLocked() { return mLastUserActivityTimeNoChangeLights; } - public void setLastUserActivityTimeNoChangeLightsLocked(long time, - @PowerManager.UserActivityEvent int event) { + public void setLastUserActivityTimeNoChangeLightsLocked(long time) { mLastUserActivityTimeNoChangeLights = time; - mLastUserActivityEvent = event; } public int getUserActivitySummaryLocked() { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index bc93cb30e449c..dbf05f1cd7c7f 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -1169,7 +1169,6 @@ public final class PowerManagerService extends SystemService return; } - Slog.i(TAG, "onFlip(): Face " + (isFaceDown ? "down." : "up.")); mIsFaceDown = isFaceDown; if (isFaceDown) { final long currentTime = mClock.uptimeMillis(); @@ -1889,13 +1888,12 @@ public final class PowerManagerService extends SystemService // Called from native code. @SuppressWarnings("unused") - private void userActivityFromNative(long eventTime, @PowerManager.UserActivityEvent int event, - int displayId, int flags) { + private void userActivityFromNative(long eventTime, int event, int displayId, int flags) { userActivityInternal(displayId, eventTime, event, flags, Process.SYSTEM_UID); } - private void userActivityInternal(int displayId, long eventTime, - @PowerManager.UserActivityEvent int event, int flags, int uid) { + private void userActivityInternal(int displayId, long eventTime, int event, int flags, + int uid) { synchronized (mLock) { if (displayId == Display.INVALID_DISPLAY) { if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) { @@ -1946,12 +1944,11 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private boolean userActivityNoUpdateLocked(final PowerGroup powerGroup, long eventTime, - @PowerManager.UserActivityEvent int event, int flags, int uid) { + int event, int flags, int uid) { final int groupId = powerGroup.getGroupId(); if (DEBUG_SPEW) { Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + groupId - + ", eventTime=" + eventTime - + ", event=" + PowerManager.userActivityEventToString(event) + + ", eventTime=" + eventTime + ", event=" + event + ", flags=0x" + Integer.toHexString(flags) + ", uid=" + uid); } @@ -1986,7 +1983,7 @@ public final class PowerManagerService extends SystemService if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) { if (eventTime > powerGroup.getLastUserActivityTimeNoChangeLightsLocked() && eventTime > powerGroup.getLastUserActivityTimeLocked()) { - powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime, event); + powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime); mDirty |= DIRTY_USER_ACTIVITY; if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) { mDirty |= DIRTY_QUIESCENT; @@ -1996,7 +1993,7 @@ public final class PowerManagerService extends SystemService } } else { if (eventTime > powerGroup.getLastUserActivityTimeLocked()) { - powerGroup.setLastUserActivityTimeLocked(eventTime, event); + powerGroup.setLastUserActivityTimeLocked(eventTime); mDirty |= DIRTY_USER_ACTIVITY; if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) { mDirty |= DIRTY_QUIESCENT; @@ -2023,8 +2020,7 @@ public final class PowerManagerService extends SystemService @WakeReason int reason, String details, int uid, String opPackageName, int opUid) { if (DEBUG_SPEW) { Slog.d(TAG, "wakePowerGroupLocked: eventTime=" + eventTime - + ", groupId=" + powerGroup.getGroupId() - + ", reason=" + PowerManager.wakeReasonToString(reason) + ", uid=" + uid); + + ", groupId=" + powerGroup.getGroupId() + ", uid=" + uid); } if (mForceSuspendActive || !mSystemReady) { return; @@ -2047,11 +2043,11 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private boolean dozePowerGroupLocked(final PowerGroup powerGroup, long eventTime, - @GoToSleepReason int reason, int uid) { + int reason, int uid) { if (DEBUG_SPEW) { Slog.d(TAG, "dozePowerGroup: eventTime=" + eventTime - + ", groupId=" + powerGroup.getGroupId() - + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid); + + ", groupId=" + powerGroup.getGroupId() + ", reason=" + reason + + ", uid=" + uid); } if (!mSystemReady || !mBootCompleted) { @@ -2062,12 +2058,10 @@ public final class PowerManagerService extends SystemService } @GuardedBy("mLock") - private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, - @GoToSleepReason int reason, int uid) { + private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, int reason, + int uid) { if (DEBUG_SPEW) { - Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime - + ", groupId=" + powerGroup.getGroupId() - + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid); + Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime + ", uid=" + uid); } if (!mBootCompleted || !mSystemReady) { return false; @@ -2128,10 +2122,7 @@ public final class PowerManagerService extends SystemService case WAKEFULNESS_DOZING: traceMethodName = "goToSleep"; Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason) - + " (uid " + uid + ", screenOffTimeout=" + mScreenOffTimeoutSetting - + ", activityTimeoutWM=" + mUserActivityTimeoutOverrideFromWindowManager - + ", maxDimRatio=" + mMaximumScreenDimRatioConfig - + ", maxDimDur=" + mMaximumScreenDimDurationConfig + ")..."); + + " (uid " + uid + ")..."); mLastGlobalSleepTime = eventTime; mLastGlobalSleepReason = reason; @@ -4216,7 +4207,7 @@ public final class PowerManagerService extends SystemService void onUserActivity() { synchronized (mLock) { mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP).setLastUserActivityTimeLocked( - mClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER); + mClock.uptimeMillis()); } } @@ -5599,8 +5590,7 @@ public final class PowerManagerService extends SystemService } @Override // Binder call - public void userActivity(int displayId, long eventTime, - @PowerManager.UserActivityEvent int event, int flags) { + public void userActivity(int displayId, long eventTime, int event, int flags) { final long now = mClock.uptimeMillis(); if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER) != PackageManager.PERMISSION_GRANTED From b1d8f9db174bf975a1b777af35c61d2ee65b4175 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Wed, 24 Aug 2022 21:02:37 +0000 Subject: [PATCH 20/45] Revert "Remove BatteryStats user activity types and use PowerManager ones instead." This reverts commit 79e517c3d45ce704ff43f068fbb63d24ab4693c6. Reason for revert: b/243434675 Change-Id: Ie2476f23715ed933064470ee2f50d550e92d46b8 (cherry picked from commit c969b1a51b23597add887c337aefac7ea4ebe537) Merged-In: Ie2476f23715ed933064470ee2f50d550e92d46b8 --- core/java/android/os/BatteryStats.java | 13 +++++- core/java/android/os/PowerManager.java | 38 ---------------- .../android/internal/os/BatteryStatsImpl.java | 11 +++-- .../com/android/server/power/Notifier.java | 3 +- .../com/android/server/power/PowerGroup.java | 27 +++--------- .../server/power/PowerManagerService.java | 44 +++++++------------ 6 files changed, 41 insertions(+), 95 deletions(-) diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 801d34d9d8848..06c35b5bec5d9 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -956,7 +956,16 @@ public abstract class BatteryStats implements Parcelable { public static final int NUM_WIFI_BATCHED_SCAN_BINS = 5; - public static final int NUM_USER_ACTIVITY_TYPES = PowerManager.USER_ACTIVITY_EVENT_MAX + 1; + /** + * Note that these must match the constants in android.os.PowerManager. + * Also, if the user activity types change, the BatteryStatsImpl.VERSION must + * also be bumped. + */ + static final String[] USER_ACTIVITY_TYPES = { + "other", "button", "touch", "accessibility", "attention" + }; + + public static final int NUM_USER_ACTIVITY_TYPES = USER_ACTIVITY_TYPES.length; public abstract void noteUserActivityLocked(int type); public abstract boolean hasUserActivity(); @@ -6168,7 +6177,7 @@ public abstract class BatteryStats implements Parcelable { } sb.append(val); sb.append(" "); - sb.append(PowerManager.userActivityEventToString(i)); + sb.append(Uid.USER_ACTIVITY_TYPES[i]); } } if (hasData) { diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 8a203e07ae6dd..13ca2c34b27ec 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -344,44 +344,6 @@ public final class PowerManager { */ public static final int USER_ACTIVITY_EVENT_DEVICE_STATE = 6; - /** - * @hide - */ - public static final int USER_ACTIVITY_EVENT_MAX = USER_ACTIVITY_EVENT_DEVICE_STATE; - - /** - * @hide - */ - @IntDef(prefix = { "USER_ACTIVITY_EVENT_" }, value = { - USER_ACTIVITY_EVENT_OTHER, - USER_ACTIVITY_EVENT_BUTTON, - USER_ACTIVITY_EVENT_TOUCH, - USER_ACTIVITY_EVENT_ACCESSIBILITY, - USER_ACTIVITY_EVENT_ATTENTION, - USER_ACTIVITY_EVENT_FACE_DOWN, - USER_ACTIVITY_EVENT_DEVICE_STATE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface UserActivityEvent{} - - /** - * - * Convert the user activity event to a string for debugging purposes. - * @hide - */ - public static String userActivityEventToString(@UserActivityEvent int userActivityEvent) { - switch (userActivityEvent) { - case USER_ACTIVITY_EVENT_OTHER: return "other"; - case USER_ACTIVITY_EVENT_BUTTON: return "button"; - case USER_ACTIVITY_EVENT_TOUCH: return "touch"; - case USER_ACTIVITY_EVENT_ACCESSIBILITY: return "accessibility"; - case USER_ACTIVITY_EVENT_ATTENTION: return "attention"; - case USER_ACTIVITY_EVENT_FACE_DOWN: return "faceDown"; - case USER_ACTIVITY_EVENT_DEVICE_STATE: return "deviceState"; - default: return Integer.toString(userActivityEvent); - } - } - /** * User activity flag: If already dimmed, extend the dim timeout * but do not brighten. This flag is useful for keeping the screen on diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 06473b5ee8dee..98d4c5976adc8 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -6144,8 +6144,7 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("this") - public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event, - long elapsedRealtimeMs, long uptimeMs) { + public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) { if (mOnBatteryInternal) { uid = mapUid(uid); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event); @@ -9957,14 +9956,14 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) { + public void noteUserActivityLocked(int type) { if (mUserActivityCounters == null) { initUserActivityLocked(); } - if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) { - mUserActivityCounters[event].stepAtomic(); + if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) { + mUserActivityCounters[type].stepAtomic(); } else { - Slog.w(TAG, "Unknown user activity event " + event + " was specified.", + Slog.w(TAG, "Unknown user activity type " + type + " was specified.", new Throwable()); } } diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index dad9584c67225..5a2fb18673ac1 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -571,8 +571,7 @@ public class Notifier { /** * Called when there has been user activity. */ - public void onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event, - int uid) { + public void onUserActivity(int displayGroupId, int event, int uid) { if (DEBUG) { Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid); } diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java index 9fe53fbfaf255..fec61ac8f2cf0 100644 --- a/services/core/java/com/android/server/power/PowerGroup.java +++ b/services/core/java/com/android/server/power/PowerGroup.java @@ -74,8 +74,6 @@ public class PowerGroup { private long mLastPowerOnTime; private long mLastUserActivityTime; private long mLastUserActivityTimeNoChangeLights; - @PowerManager.UserActivityEvent - private int mLastUserActivityEvent; /** Timestamp (milliseconds since boot) of the last time the power group was awoken.*/ private long mLastWakeTime; /** Timestamp (milliseconds since boot) of the last time the power group was put to sleep. */ @@ -246,7 +244,7 @@ public class PowerGroup { return true; } - boolean dozeLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) { + boolean dozeLocked(long eventTime, int uid, int reason) { if (eventTime < getLastWakeTimeLocked() || !isInteractive(mWakefulness)) { return false; } @@ -255,14 +253,9 @@ public class PowerGroup { try { reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX, Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN)); - long millisSinceLastUserActivity = eventTime - Math.max( - mLastUserActivityTimeNoChangeLights, mLastUserActivityTime); Slog.i(TAG, "Powering off display group due to " - + PowerManager.sleepReasonToString(reason) - + " (groupId= " + getGroupId() + ", uid= " + uid - + ", millisSinceLastUserActivity=" + millisSinceLastUserActivity - + ", lastUserActivityEvent=" + PowerManager.userActivityEventToString( - mLastUserActivityEvent) + ")..."); + + PowerManager.sleepReasonToString(reason) + " (groupId= " + getGroupId() + + ", uid= " + uid + ")..."); setSandmanSummonedLocked(/* isSandmanSummoned= */ true); setWakefulnessLocked(WAKEFULNESS_DOZING, eventTime, uid, reason, /* opUid= */ 0, @@ -273,16 +266,14 @@ public class PowerGroup { return true; } - boolean sleepLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) { + boolean sleepLocked(long eventTime, int uid, int reason) { if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) { return false; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "sleepPowerGroup"); try { - Slog.i(TAG, - "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ", reason=" - + PowerManager.sleepReasonToString(reason) + ")..."); + Slog.i(TAG, "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ")..."); setSandmanSummonedLocked(/* isSandmanSummoned= */ true); setWakefulnessLocked(WAKEFULNESS_ASLEEP, eventTime, uid, reason, /* opUid= */0, /* opPackageName= */ null, /* details= */ null); @@ -296,20 +287,16 @@ public class PowerGroup { return mLastUserActivityTime; } - void setLastUserActivityTimeLocked(long lastUserActivityTime, - @PowerManager.UserActivityEvent int event) { + void setLastUserActivityTimeLocked(long lastUserActivityTime) { mLastUserActivityTime = lastUserActivityTime; - mLastUserActivityEvent = event; } public long getLastUserActivityTimeNoChangeLightsLocked() { return mLastUserActivityTimeNoChangeLights; } - public void setLastUserActivityTimeNoChangeLightsLocked(long time, - @PowerManager.UserActivityEvent int event) { + public void setLastUserActivityTimeNoChangeLightsLocked(long time) { mLastUserActivityTimeNoChangeLights = time; - mLastUserActivityEvent = event; } public int getUserActivitySummaryLocked() { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index bc93cb30e449c..dbf05f1cd7c7f 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -1169,7 +1169,6 @@ public final class PowerManagerService extends SystemService return; } - Slog.i(TAG, "onFlip(): Face " + (isFaceDown ? "down." : "up.")); mIsFaceDown = isFaceDown; if (isFaceDown) { final long currentTime = mClock.uptimeMillis(); @@ -1889,13 +1888,12 @@ public final class PowerManagerService extends SystemService // Called from native code. @SuppressWarnings("unused") - private void userActivityFromNative(long eventTime, @PowerManager.UserActivityEvent int event, - int displayId, int flags) { + private void userActivityFromNative(long eventTime, int event, int displayId, int flags) { userActivityInternal(displayId, eventTime, event, flags, Process.SYSTEM_UID); } - private void userActivityInternal(int displayId, long eventTime, - @PowerManager.UserActivityEvent int event, int flags, int uid) { + private void userActivityInternal(int displayId, long eventTime, int event, int flags, + int uid) { synchronized (mLock) { if (displayId == Display.INVALID_DISPLAY) { if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) { @@ -1946,12 +1944,11 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private boolean userActivityNoUpdateLocked(final PowerGroup powerGroup, long eventTime, - @PowerManager.UserActivityEvent int event, int flags, int uid) { + int event, int flags, int uid) { final int groupId = powerGroup.getGroupId(); if (DEBUG_SPEW) { Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + groupId - + ", eventTime=" + eventTime - + ", event=" + PowerManager.userActivityEventToString(event) + + ", eventTime=" + eventTime + ", event=" + event + ", flags=0x" + Integer.toHexString(flags) + ", uid=" + uid); } @@ -1986,7 +1983,7 @@ public final class PowerManagerService extends SystemService if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) { if (eventTime > powerGroup.getLastUserActivityTimeNoChangeLightsLocked() && eventTime > powerGroup.getLastUserActivityTimeLocked()) { - powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime, event); + powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime); mDirty |= DIRTY_USER_ACTIVITY; if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) { mDirty |= DIRTY_QUIESCENT; @@ -1996,7 +1993,7 @@ public final class PowerManagerService extends SystemService } } else { if (eventTime > powerGroup.getLastUserActivityTimeLocked()) { - powerGroup.setLastUserActivityTimeLocked(eventTime, event); + powerGroup.setLastUserActivityTimeLocked(eventTime); mDirty |= DIRTY_USER_ACTIVITY; if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) { mDirty |= DIRTY_QUIESCENT; @@ -2023,8 +2020,7 @@ public final class PowerManagerService extends SystemService @WakeReason int reason, String details, int uid, String opPackageName, int opUid) { if (DEBUG_SPEW) { Slog.d(TAG, "wakePowerGroupLocked: eventTime=" + eventTime - + ", groupId=" + powerGroup.getGroupId() - + ", reason=" + PowerManager.wakeReasonToString(reason) + ", uid=" + uid); + + ", groupId=" + powerGroup.getGroupId() + ", uid=" + uid); } if (mForceSuspendActive || !mSystemReady) { return; @@ -2047,11 +2043,11 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private boolean dozePowerGroupLocked(final PowerGroup powerGroup, long eventTime, - @GoToSleepReason int reason, int uid) { + int reason, int uid) { if (DEBUG_SPEW) { Slog.d(TAG, "dozePowerGroup: eventTime=" + eventTime - + ", groupId=" + powerGroup.getGroupId() - + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid); + + ", groupId=" + powerGroup.getGroupId() + ", reason=" + reason + + ", uid=" + uid); } if (!mSystemReady || !mBootCompleted) { @@ -2062,12 +2058,10 @@ public final class PowerManagerService extends SystemService } @GuardedBy("mLock") - private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, - @GoToSleepReason int reason, int uid) { + private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, int reason, + int uid) { if (DEBUG_SPEW) { - Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime - + ", groupId=" + powerGroup.getGroupId() - + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid); + Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime + ", uid=" + uid); } if (!mBootCompleted || !mSystemReady) { return false; @@ -2128,10 +2122,7 @@ public final class PowerManagerService extends SystemService case WAKEFULNESS_DOZING: traceMethodName = "goToSleep"; Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason) - + " (uid " + uid + ", screenOffTimeout=" + mScreenOffTimeoutSetting - + ", activityTimeoutWM=" + mUserActivityTimeoutOverrideFromWindowManager - + ", maxDimRatio=" + mMaximumScreenDimRatioConfig - + ", maxDimDur=" + mMaximumScreenDimDurationConfig + ")..."); + + " (uid " + uid + ")..."); mLastGlobalSleepTime = eventTime; mLastGlobalSleepReason = reason; @@ -4216,7 +4207,7 @@ public final class PowerManagerService extends SystemService void onUserActivity() { synchronized (mLock) { mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP).setLastUserActivityTimeLocked( - mClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER); + mClock.uptimeMillis()); } } @@ -5599,8 +5590,7 @@ public final class PowerManagerService extends SystemService } @Override // Binder call - public void userActivity(int displayId, long eventTime, - @PowerManager.UserActivityEvent int event, int flags) { + public void userActivity(int displayId, long eventTime, int event, int flags) { final long now = mClock.uptimeMillis(); if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER) != PackageManager.PERMISSION_GRANTED From 8f2c279c6ebf2084bb4af3efdbbc88d17b5ab9e6 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Wed, 24 Aug 2022 21:02:37 +0000 Subject: [PATCH 21/45] Revert "Remove BatteryStats user activity types and use PowerManager ones instead." This reverts commit 79e517c3d45ce704ff43f068fbb63d24ab4693c6. Reason for revert: b/243434675 Change-Id: Ie2476f23715ed933064470ee2f50d550e92d46b8 Merged-In: I5cfdd6a7c21ed322f50d7605fdd470b41726f4cf (cherry picked from commit e8ab134de1bbc61b1454822df7951c23e2b49775) Merged-In: Ie2476f23715ed933064470ee2f50d550e92d46b8 --- core/java/android/os/BatteryStats.java | 13 +++++- core/java/android/os/PowerManager.java | 38 ---------------- .../android/internal/os/BatteryStatsImpl.java | 11 +++-- .../com/android/server/power/Notifier.java | 3 +- .../com/android/server/power/PowerGroup.java | 27 +++--------- .../server/power/PowerManagerService.java | 44 +++++++------------ 6 files changed, 41 insertions(+), 95 deletions(-) diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 801d34d9d8848..06c35b5bec5d9 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -956,7 +956,16 @@ public abstract class BatteryStats implements Parcelable { public static final int NUM_WIFI_BATCHED_SCAN_BINS = 5; - public static final int NUM_USER_ACTIVITY_TYPES = PowerManager.USER_ACTIVITY_EVENT_MAX + 1; + /** + * Note that these must match the constants in android.os.PowerManager. + * Also, if the user activity types change, the BatteryStatsImpl.VERSION must + * also be bumped. + */ + static final String[] USER_ACTIVITY_TYPES = { + "other", "button", "touch", "accessibility", "attention" + }; + + public static final int NUM_USER_ACTIVITY_TYPES = USER_ACTIVITY_TYPES.length; public abstract void noteUserActivityLocked(int type); public abstract boolean hasUserActivity(); @@ -6168,7 +6177,7 @@ public abstract class BatteryStats implements Parcelable { } sb.append(val); sb.append(" "); - sb.append(PowerManager.userActivityEventToString(i)); + sb.append(Uid.USER_ACTIVITY_TYPES[i]); } } if (hasData) { diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 8a203e07ae6dd..13ca2c34b27ec 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -344,44 +344,6 @@ public final class PowerManager { */ public static final int USER_ACTIVITY_EVENT_DEVICE_STATE = 6; - /** - * @hide - */ - public static final int USER_ACTIVITY_EVENT_MAX = USER_ACTIVITY_EVENT_DEVICE_STATE; - - /** - * @hide - */ - @IntDef(prefix = { "USER_ACTIVITY_EVENT_" }, value = { - USER_ACTIVITY_EVENT_OTHER, - USER_ACTIVITY_EVENT_BUTTON, - USER_ACTIVITY_EVENT_TOUCH, - USER_ACTIVITY_EVENT_ACCESSIBILITY, - USER_ACTIVITY_EVENT_ATTENTION, - USER_ACTIVITY_EVENT_FACE_DOWN, - USER_ACTIVITY_EVENT_DEVICE_STATE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface UserActivityEvent{} - - /** - * - * Convert the user activity event to a string for debugging purposes. - * @hide - */ - public static String userActivityEventToString(@UserActivityEvent int userActivityEvent) { - switch (userActivityEvent) { - case USER_ACTIVITY_EVENT_OTHER: return "other"; - case USER_ACTIVITY_EVENT_BUTTON: return "button"; - case USER_ACTIVITY_EVENT_TOUCH: return "touch"; - case USER_ACTIVITY_EVENT_ACCESSIBILITY: return "accessibility"; - case USER_ACTIVITY_EVENT_ATTENTION: return "attention"; - case USER_ACTIVITY_EVENT_FACE_DOWN: return "faceDown"; - case USER_ACTIVITY_EVENT_DEVICE_STATE: return "deviceState"; - default: return Integer.toString(userActivityEvent); - } - } - /** * User activity flag: If already dimmed, extend the dim timeout * but do not brighten. This flag is useful for keeping the screen on diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 06473b5ee8dee..98d4c5976adc8 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -6144,8 +6144,7 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("this") - public void noteUserActivityLocked(int uid, @PowerManager.UserActivityEvent int event, - long elapsedRealtimeMs, long uptimeMs) { + public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) { if (mOnBatteryInternal) { uid = mapUid(uid); getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event); @@ -9957,14 +9956,14 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public void noteUserActivityLocked(@PowerManager.UserActivityEvent int event) { + public void noteUserActivityLocked(int type) { if (mUserActivityCounters == null) { initUserActivityLocked(); } - if (event >= 0 && event < NUM_USER_ACTIVITY_TYPES) { - mUserActivityCounters[event].stepAtomic(); + if (type >= 0 && type < NUM_USER_ACTIVITY_TYPES) { + mUserActivityCounters[type].stepAtomic(); } else { - Slog.w(TAG, "Unknown user activity event " + event + " was specified.", + Slog.w(TAG, "Unknown user activity type " + type + " was specified.", new Throwable()); } } diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index dad9584c67225..5a2fb18673ac1 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -571,8 +571,7 @@ public class Notifier { /** * Called when there has been user activity. */ - public void onUserActivity(int displayGroupId, @PowerManager.UserActivityEvent int event, - int uid) { + public void onUserActivity(int displayGroupId, int event, int uid) { if (DEBUG) { Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid); } diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java index 9fe53fbfaf255..fec61ac8f2cf0 100644 --- a/services/core/java/com/android/server/power/PowerGroup.java +++ b/services/core/java/com/android/server/power/PowerGroup.java @@ -74,8 +74,6 @@ public class PowerGroup { private long mLastPowerOnTime; private long mLastUserActivityTime; private long mLastUserActivityTimeNoChangeLights; - @PowerManager.UserActivityEvent - private int mLastUserActivityEvent; /** Timestamp (milliseconds since boot) of the last time the power group was awoken.*/ private long mLastWakeTime; /** Timestamp (milliseconds since boot) of the last time the power group was put to sleep. */ @@ -246,7 +244,7 @@ public class PowerGroup { return true; } - boolean dozeLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) { + boolean dozeLocked(long eventTime, int uid, int reason) { if (eventTime < getLastWakeTimeLocked() || !isInteractive(mWakefulness)) { return false; } @@ -255,14 +253,9 @@ public class PowerGroup { try { reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX, Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN)); - long millisSinceLastUserActivity = eventTime - Math.max( - mLastUserActivityTimeNoChangeLights, mLastUserActivityTime); Slog.i(TAG, "Powering off display group due to " - + PowerManager.sleepReasonToString(reason) - + " (groupId= " + getGroupId() + ", uid= " + uid - + ", millisSinceLastUserActivity=" + millisSinceLastUserActivity - + ", lastUserActivityEvent=" + PowerManager.userActivityEventToString( - mLastUserActivityEvent) + ")..."); + + PowerManager.sleepReasonToString(reason) + " (groupId= " + getGroupId() + + ", uid= " + uid + ")..."); setSandmanSummonedLocked(/* isSandmanSummoned= */ true); setWakefulnessLocked(WAKEFULNESS_DOZING, eventTime, uid, reason, /* opUid= */ 0, @@ -273,16 +266,14 @@ public class PowerGroup { return true; } - boolean sleepLocked(long eventTime, int uid, @PowerManager.GoToSleepReason int reason) { + boolean sleepLocked(long eventTime, int uid, int reason) { if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) { return false; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "sleepPowerGroup"); try { - Slog.i(TAG, - "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ", reason=" - + PowerManager.sleepReasonToString(reason) + ")..."); + Slog.i(TAG, "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ")..."); setSandmanSummonedLocked(/* isSandmanSummoned= */ true); setWakefulnessLocked(WAKEFULNESS_ASLEEP, eventTime, uid, reason, /* opUid= */0, /* opPackageName= */ null, /* details= */ null); @@ -296,20 +287,16 @@ public class PowerGroup { return mLastUserActivityTime; } - void setLastUserActivityTimeLocked(long lastUserActivityTime, - @PowerManager.UserActivityEvent int event) { + void setLastUserActivityTimeLocked(long lastUserActivityTime) { mLastUserActivityTime = lastUserActivityTime; - mLastUserActivityEvent = event; } public long getLastUserActivityTimeNoChangeLightsLocked() { return mLastUserActivityTimeNoChangeLights; } - public void setLastUserActivityTimeNoChangeLightsLocked(long time, - @PowerManager.UserActivityEvent int event) { + public void setLastUserActivityTimeNoChangeLightsLocked(long time) { mLastUserActivityTimeNoChangeLights = time; - mLastUserActivityEvent = event; } public int getUserActivitySummaryLocked() { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index bc93cb30e449c..dbf05f1cd7c7f 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -1169,7 +1169,6 @@ public final class PowerManagerService extends SystemService return; } - Slog.i(TAG, "onFlip(): Face " + (isFaceDown ? "down." : "up.")); mIsFaceDown = isFaceDown; if (isFaceDown) { final long currentTime = mClock.uptimeMillis(); @@ -1889,13 +1888,12 @@ public final class PowerManagerService extends SystemService // Called from native code. @SuppressWarnings("unused") - private void userActivityFromNative(long eventTime, @PowerManager.UserActivityEvent int event, - int displayId, int flags) { + private void userActivityFromNative(long eventTime, int event, int displayId, int flags) { userActivityInternal(displayId, eventTime, event, flags, Process.SYSTEM_UID); } - private void userActivityInternal(int displayId, long eventTime, - @PowerManager.UserActivityEvent int event, int flags, int uid) { + private void userActivityInternal(int displayId, long eventTime, int event, int flags, + int uid) { synchronized (mLock) { if (displayId == Display.INVALID_DISPLAY) { if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) { @@ -1946,12 +1944,11 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private boolean userActivityNoUpdateLocked(final PowerGroup powerGroup, long eventTime, - @PowerManager.UserActivityEvent int event, int flags, int uid) { + int event, int flags, int uid) { final int groupId = powerGroup.getGroupId(); if (DEBUG_SPEW) { Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + groupId - + ", eventTime=" + eventTime - + ", event=" + PowerManager.userActivityEventToString(event) + + ", eventTime=" + eventTime + ", event=" + event + ", flags=0x" + Integer.toHexString(flags) + ", uid=" + uid); } @@ -1986,7 +1983,7 @@ public final class PowerManagerService extends SystemService if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) { if (eventTime > powerGroup.getLastUserActivityTimeNoChangeLightsLocked() && eventTime > powerGroup.getLastUserActivityTimeLocked()) { - powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime, event); + powerGroup.setLastUserActivityTimeNoChangeLightsLocked(eventTime); mDirty |= DIRTY_USER_ACTIVITY; if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) { mDirty |= DIRTY_QUIESCENT; @@ -1996,7 +1993,7 @@ public final class PowerManagerService extends SystemService } } else { if (eventTime > powerGroup.getLastUserActivityTimeLocked()) { - powerGroup.setLastUserActivityTimeLocked(eventTime, event); + powerGroup.setLastUserActivityTimeLocked(eventTime); mDirty |= DIRTY_USER_ACTIVITY; if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) { mDirty |= DIRTY_QUIESCENT; @@ -2023,8 +2020,7 @@ public final class PowerManagerService extends SystemService @WakeReason int reason, String details, int uid, String opPackageName, int opUid) { if (DEBUG_SPEW) { Slog.d(TAG, "wakePowerGroupLocked: eventTime=" + eventTime - + ", groupId=" + powerGroup.getGroupId() - + ", reason=" + PowerManager.wakeReasonToString(reason) + ", uid=" + uid); + + ", groupId=" + powerGroup.getGroupId() + ", uid=" + uid); } if (mForceSuspendActive || !mSystemReady) { return; @@ -2047,11 +2043,11 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private boolean dozePowerGroupLocked(final PowerGroup powerGroup, long eventTime, - @GoToSleepReason int reason, int uid) { + int reason, int uid) { if (DEBUG_SPEW) { Slog.d(TAG, "dozePowerGroup: eventTime=" + eventTime - + ", groupId=" + powerGroup.getGroupId() - + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid); + + ", groupId=" + powerGroup.getGroupId() + ", reason=" + reason + + ", uid=" + uid); } if (!mSystemReady || !mBootCompleted) { @@ -2062,12 +2058,10 @@ public final class PowerManagerService extends SystemService } @GuardedBy("mLock") - private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, - @GoToSleepReason int reason, int uid) { + private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, int reason, + int uid) { if (DEBUG_SPEW) { - Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime - + ", groupId=" + powerGroup.getGroupId() - + ", reason=" + PowerManager.sleepReasonToString(reason) + ", uid=" + uid); + Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime + ", uid=" + uid); } if (!mBootCompleted || !mSystemReady) { return false; @@ -2128,10 +2122,7 @@ public final class PowerManagerService extends SystemService case WAKEFULNESS_DOZING: traceMethodName = "goToSleep"; Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason) - + " (uid " + uid + ", screenOffTimeout=" + mScreenOffTimeoutSetting - + ", activityTimeoutWM=" + mUserActivityTimeoutOverrideFromWindowManager - + ", maxDimRatio=" + mMaximumScreenDimRatioConfig - + ", maxDimDur=" + mMaximumScreenDimDurationConfig + ")..."); + + " (uid " + uid + ")..."); mLastGlobalSleepTime = eventTime; mLastGlobalSleepReason = reason; @@ -4216,7 +4207,7 @@ public final class PowerManagerService extends SystemService void onUserActivity() { synchronized (mLock) { mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP).setLastUserActivityTimeLocked( - mClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER); + mClock.uptimeMillis()); } } @@ -5599,8 +5590,7 @@ public final class PowerManagerService extends SystemService } @Override // Binder call - public void userActivity(int displayId, long eventTime, - @PowerManager.UserActivityEvent int event, int flags) { + public void userActivity(int displayId, long eventTime, int event, int flags) { final long now = mClock.uptimeMillis(); if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER) != PackageManager.PERMISSION_GRANTED From 3da09aa6127034e0e43f9c5973d0dd4004ffee3f Mon Sep 17 00:00:00 2001 From: Beverly Date: Wed, 24 Aug 2022 19:41:20 +0000 Subject: [PATCH 22/45] Add falsing protection to the pulsing state Prox-gate the tap and double tap to wake gestures from pulsing/AoD2. Enable FalsingCollector logs: adb shell setprop log.tag.FalsingCollector DEBUG Test: manually trigger quickpickup (or receive a notification on AoD), cover the prox sensor, and then tap the screen - see device won't wake up Test: atest NotificationShadeWindowViewControllerTest BrightLineFalsingManagerTest PulsingGestureListenerTest Bug: 242125976 Change-Id: I520df509b7804d765807477968257c94f55ef634 (cherry picked from commit 2076b17a920dd2b0d626f92314e40c0730ddfa28) Merged-In: I520df509b7804d765807477968257c94f55ef634 --- .../systemui/plugins/FalsingManager.java | 6 + .../classifier/BrightLineFalsingManager.java | 8 + .../classifier/FalsingCollectorImpl.java | 6 +- .../classifier/FalsingManagerProxy.java | 5 + ...NotificationShadeWindowViewController.java | 56 +---- .../systemui/shade/PulsingGestureListener.kt | 111 ++++++++++ .../BrightLineFalsingManagerTest.java | 47 +++++ ...tificationShadeWindowViewControllerTest.kt | 11 +- .../NotificationShadeWindowViewTest.java | 6 +- .../shade/PulsingGestureListenerTest.kt | 199 ++++++++++++++++++ .../classifier/FalsingManagerFake.java | 10 + 11 files changed, 404 insertions(+), 61 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java index bd628ccb3c08d..1aaf19e8793f0 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java @@ -102,6 +102,12 @@ public interface FalsingManager { */ boolean isFalseDoubleTap(); + /** + * Whether the last proximity event reported NEAR. May be used to short circuit motion events + * that require the proximity sensor is not covered. + */ + boolean isProximityNear(); + boolean isClassifierEnabled(); boolean shouldEnforceBouncer(); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index e28a4755bd00f..31a2134851a2c 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -80,12 +80,14 @@ public class BrightLineFalsingManager implements FalsingManager { private final Collection mClassifiers; private final List mFalsingBeliefListeners = new ArrayList<>(); private List mFalsingTapListeners = new ArrayList<>(); + private ProximityEvent mLastProximityEvent; private boolean mDestroyed; private final SessionListener mSessionListener = new SessionListener() { @Override public void onSessionEnded() { + mLastProximityEvent = null; mClassifiers.forEach(FalsingClassifier::onSessionEnded); } @@ -336,6 +338,7 @@ public class BrightLineFalsingManager implements FalsingManager { public void onProximityEvent(ProximityEvent proximityEvent) { // TODO: some of these classifiers might allow us to abort early, meaning we don't have to // make these calls. + mLastProximityEvent = proximityEvent; mClassifiers.forEach((classifier) -> classifier.onProximityEvent(proximityEvent)); } @@ -347,6 +350,11 @@ public class BrightLineFalsingManager implements FalsingManager { } } + @Override + public boolean isProximityNear() { + return mLastProximityEvent != null && mLastProximityEvent.getCovered(); + } + @Override public boolean isUnlockingDisabled() { return false; diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index 56dd1e18f2454..23d87ff980ca6 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -47,9 +47,9 @@ import javax.inject.Inject; @SysUISingleton class FalsingCollectorImpl implements FalsingCollector { - private static final boolean DEBUG = false; - private static final String TAG = "FalsingManager"; - private static final String PROXIMITY_SENSOR_TAG = "FalsingManager"; + private static final String TAG = "FalsingCollector"; + private static final String PROXIMITY_SENSOR_TAG = "FalsingCollector"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final long GESTURE_PROCESSING_DELAY_MS = 100; private final FalsingDataProvider mFalsingDataProvider; diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index 609f1d6d9b896..5d04b5f774793 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -143,6 +143,11 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { return mInternalFalsingManager.isFalseDoubleTap(); } + @Override + public boolean isProximityNear() { + return mInternalFalsingManager.isProximityNear(); + } + @Override public boolean isClassifierEnabled() { return mInternalFalsingManager.isClassifierEnabled(); diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index b8546df75f5f4..fec76b65dd093 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -17,12 +17,9 @@ package com.android.systemui.shade; import android.app.StatusBarManager; -import android.hardware.display.AmbientDisplayConfiguration; import android.media.AudioManager; import android.media.session.MediaSessionLegacyHelper; import android.os.SystemClock; -import android.os.UserHandle; -import android.provider.Settings; import android.util.Log; import android.view.GestureDetector; import android.view.InputDevice; @@ -52,7 +49,6 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.window.StatusBarWindowStateController; -import com.android.systemui.tuner.TunerService; import java.io.PrintWriter; import java.util.Optional; @@ -66,7 +62,6 @@ import javax.inject.Inject; public class NotificationShadeWindowViewController { private static final String TAG = "NotifShadeWindowVC"; private final FalsingCollector mFalsingCollector; - private final TunerService mTunerService; private final SysuiStatusBarStateController mStatusBarStateController; private final NotificationShadeWindowView mView; private final NotificationShadeDepthController mDepthController; @@ -77,6 +72,7 @@ public class NotificationShadeWindowViewController { private final StatusBarWindowStateController mStatusBarWindowStateController; private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; private final AmbientState mAmbientState; + private final PulsingGestureListener mPulsingGestureListener; private GestureDetector mGestureDetector; private View mBrightnessMirror; @@ -88,8 +84,6 @@ public class NotificationShadeWindowViewController { private final CentralSurfaces mService; private final NotificationShadeWindowController mNotificationShadeWindowController; private DragDownHelper mDragDownHelper; - private boolean mDoubleTapEnabled; - private boolean mSingleTapEnabled; private boolean mExpandingBelowNotch; private final DockManager mDockManager; private final NotificationPanelViewController mNotificationPanelViewController; @@ -102,7 +96,6 @@ public class NotificationShadeWindowViewController { public NotificationShadeWindowViewController( LockscreenShadeTransitionController transitionController, FalsingCollector falsingCollector, - TunerService tunerService, SysuiStatusBarStateController statusBarStateController, DockManager dockManager, NotificationShadeDepthController depthController, @@ -117,10 +110,11 @@ public class NotificationShadeWindowViewController { CentralSurfaces centralSurfaces, NotificationShadeWindowController controller, KeyguardUnlockAnimationController keyguardUnlockAnimationController, - AmbientState ambientState) { + AmbientState ambientState, + PulsingGestureListener pulsingGestureListener + ) { mLockscreenShadeTransitionController = transitionController; mFalsingCollector = falsingCollector; - mTunerService = tunerService; mStatusBarStateController = statusBarStateController; mView = notificationShadeWindowView; mDockManager = dockManager; @@ -136,6 +130,7 @@ public class NotificationShadeWindowViewController { mNotificationShadeWindowController = controller; mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; mAmbientState = ambientState; + mPulsingGestureListener = pulsingGestureListener; // This view is not part of the newly inflated expanded status bar. mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container); @@ -151,46 +146,7 @@ public class NotificationShadeWindowViewController { /** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */ public void setupExpandedStatusBar() { mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller); - - TunerService.Tunable tunable = (key, newValue) -> { - AmbientDisplayConfiguration configuration = - new AmbientDisplayConfiguration(mView.getContext()); - switch (key) { - case Settings.Secure.DOZE_DOUBLE_TAP_GESTURE: - mDoubleTapEnabled = configuration.doubleTapGestureEnabled( - UserHandle.USER_CURRENT); - break; - case Settings.Secure.DOZE_TAP_SCREEN_GESTURE: - mSingleTapEnabled = configuration.tapGestureEnabled(UserHandle.USER_CURRENT); - } - }; - mTunerService.addTunable(tunable, - Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, - Settings.Secure.DOZE_TAP_SCREEN_GESTURE); - - GestureDetector.SimpleOnGestureListener gestureListener = - new GestureDetector.SimpleOnGestureListener() { - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { - if (mSingleTapEnabled && !mDockManager.isDocked()) { - mService.wakeUpIfDozing( - SystemClock.uptimeMillis(), mView, "SINGLE_TAP"); - return true; - } - return false; - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - if (mDoubleTapEnabled || mSingleTapEnabled) { - mService.wakeUpIfDozing( - SystemClock.uptimeMillis(), mView, "DOUBLE_TAP"); - return true; - } - return false; - } - }; - mGestureDetector = new GestureDetector(mView.getContext(), gestureListener); + mGestureDetector = new GestureDetector(mView.getContext(), mPulsingGestureListener); mLowLightClockController.ifPresent(controller -> controller.attachLowLightClockView(mView)); diff --git a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt new file mode 100644 index 0000000000000..621a6090f4a00 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade + +import android.hardware.display.AmbientDisplayConfiguration +import android.os.SystemClock +import android.os.UserHandle +import android.provider.Settings +import android.view.GestureDetector +import android.view.MotionEvent +import com.android.systemui.Dumpable +import com.android.systemui.dock.DockManager +import com.android.systemui.dump.DumpManager +import com.android.systemui.plugins.FalsingManager +import com.android.systemui.statusbar.phone.CentralSurfaces +import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent +import com.android.systemui.tuner.TunerService +import com.android.systemui.tuner.TunerService.Tunable +import java.io.PrintWriter +import javax.inject.Inject + +/** + * If tap and/or double tap to wake is enabled, this gestureListener will wake the display on + * tap/double tap when the device is pulsing (AoD 2). Taps are gated by the proximity sensor and + * falsing manager. + * + * Touches go through the [NotificationShadeWindowViewController] when the device is pulsing. + * Otherwise, if the device is dozing and NOT pulsing, wake-ups are handled by + * [com.android.systemui.doze.DozeSensors]. + */ +@CentralSurfacesComponent.CentralSurfacesScope +class PulsingGestureListener @Inject constructor( + private val notificationShadeWindowView: NotificationShadeWindowView, + private val falsingManager: FalsingManager, + private val dockManager: DockManager, + private val centralSurfaces: CentralSurfaces, + private val ambientDisplayConfiguration: AmbientDisplayConfiguration, + tunerService: TunerService, + dumpManager: DumpManager +) : GestureDetector.SimpleOnGestureListener(), Dumpable { + private var doubleTapEnabled = false + private var singleTapEnabled = false + + init { + val tunable = Tunable { key: String?, _: String? -> + when (key) { + Settings.Secure.DOZE_DOUBLE_TAP_GESTURE -> + doubleTapEnabled = ambientDisplayConfiguration.doubleTapGestureEnabled( + UserHandle.USER_CURRENT) + Settings.Secure.DOZE_TAP_SCREEN_GESTURE -> + singleTapEnabled = ambientDisplayConfiguration.tapGestureEnabled( + UserHandle.USER_CURRENT) + } + } + tunerService.addTunable(tunable, + Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, + Settings.Secure.DOZE_TAP_SCREEN_GESTURE) + + dumpManager.registerDumpable(this) + } + + override fun onSingleTapConfirmed(e: MotionEvent): Boolean { + if (singleTapEnabled && + !dockManager.isDocked && + !falsingManager.isProximityNear && + !falsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY) + ) { + centralSurfaces.wakeUpIfDozing( + SystemClock.uptimeMillis(), + notificationShadeWindowView, + "PULSING_SINGLE_TAP") + return true + } + return false + } + + override fun onDoubleTap(e: MotionEvent): Boolean { + if ((doubleTapEnabled || singleTapEnabled) && + !falsingManager.isProximityNear && + !falsingManager.isFalseDoubleTap + ) { + centralSurfaces.wakeUpIfDozing( + SystemClock.uptimeMillis(), + notificationShadeWindowView, + "PULSING_DOUBLE_TAP") + return true + } + return false + } + + override fun dump(pw: PrintWriter, args: Array) { + pw.println("singleTapEnabled=$singleTapEnabled") + pw.println("doubleTapEnabled=$doubleTapEnabled") + pw.println("isDocked=${dockManager.isDocked}") + pw.println("isProxCovered=${falsingManager.isProximityNear}") + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java index 55ee433c8d9de..94813497cb4c8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java @@ -32,6 +32,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.policy.KeyguardStateController; import org.junit.Before; @@ -111,5 +112,51 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse(); } + @Test + public void testIsProxNear_noProxEvents_defaultsToFalse() { + assertThat(mBrightLineFalsingManager.isProximityNear()).isFalse(); + } + @Test + public void testIsProxNear_receivesNearEvent() { + mBrightLineFalsingManager.onProximityEvent(new FalsingManager.ProximityEvent() { + @Override + public boolean getCovered() { + return true; + } + + @Override + public long getTimestampNs() { + return 0; + } + }); + assertThat(mBrightLineFalsingManager.isProximityNear()).isTrue(); + } + + @Test + public void testIsProxNear_receivesNearAndThenFarEvent() { + mBrightLineFalsingManager.onProximityEvent(new FalsingManager.ProximityEvent() { + @Override + public boolean getCovered() { + return true; + } + + @Override + public long getTimestampNs() { + return 0; + } + }); + mBrightLineFalsingManager.onProximityEvent(new FalsingManager.ProximityEvent() { + @Override + public boolean getCovered() { + return false; + } + + @Override + public long getTimestampNs() { + return 5; + } + }); + assertThat(mBrightLineFalsingManager.isProximityNear()).isFalse(); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt index 471918cfa695b..6d059b1cb7873 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -26,19 +26,18 @@ import com.android.systemui.classifier.FalsingCollectorFake import com.android.systemui.dock.DockManager import com.android.systemui.keyguard.KeyguardUnlockAnimationController import com.android.systemui.lowlightclock.LowLightClockController +import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler import com.android.systemui.statusbar.LockscreenShadeTransitionController import com.android.systemui.statusbar.NotificationShadeDepthController import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.stack.AmbientState import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController -import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.PhoneStatusBarViewController import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager import com.android.systemui.statusbar.window.StatusBarWindowStateController -import com.android.systemui.tuner.TunerService import com.google.common.truth.Truth.assertThat import java.util.Optional import org.junit.Before @@ -60,8 +59,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { @Mock private lateinit var view: NotificationShadeWindowView @Mock - private lateinit var tunserService: TunerService - @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController @Mock private lateinit var centralSurfaces: CentralSurfaces @@ -91,6 +88,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController @Mock private lateinit var lowLightClockController: LowLightClockController + @Mock + private lateinit var pulsingGestureListener: PulsingGestureListener private lateinit var interactionEventHandlerCaptor: ArgumentCaptor private lateinit var interactionEventHandler: InteractionEventHandler @@ -105,7 +104,6 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { underTest = NotificationShadeWindowViewController( lockscreenShadeTransitionController, FalsingCollectorFake(), - tunserService, sysuiStatusBarStateController, dockManager, notificationShadeDepthController, @@ -120,7 +118,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { centralSurfaces, notificationShadeWindowController, keyguardUnlockAnimationController, - ambientState + ambientState, + pulsingGestureListener ) underTest.setupExpandedStatusBar() diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java index fa16fefdf5a40..89a251808402c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java @@ -89,6 +89,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { @Mock private LowLightClockController mLowLightClockController; @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; @Mock private AmbientState mAmbientState; + @Mock private PulsingGestureListener mPulsingGestureListener; @Captor private ArgumentCaptor mInteractionEventHandlerCaptor; @@ -110,7 +111,6 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { mController = new NotificationShadeWindowViewController( mLockscreenShadeTransitionController, new FalsingCollectorFake(), - mTunerService, mStatusBarStateController, mDockManager, mNotificationShadeDepthController, @@ -125,7 +125,9 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { mCentralSurfaces, mNotificationShadeWindowController, mKeyguardUnlockAnimationController, - mAmbientState); + mAmbientState, + mPulsingGestureListener + ); mController.setupExpandedStatusBar(); mController.setDragDownHelper(mDragDownHelper); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt new file mode 100644 index 0000000000000..d2970a63a8601 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade + +import android.hardware.display.AmbientDisplayConfiguration +import android.provider.Settings.Secure.DOZE_DOUBLE_TAP_GESTURE +import android.provider.Settings.Secure.DOZE_TAP_SCREEN_GESTURE +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper +import android.view.MotionEvent +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.dock.DockManager +import com.android.systemui.dump.DumpManager +import com.android.systemui.plugins.FalsingManager +import com.android.systemui.statusbar.phone.CentralSurfaces +import com.android.systemui.tuner.TunerService +import com.android.systemui.tuner.TunerService.Tunable +import com.android.systemui.util.mockito.eq +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.anyLong +import org.mockito.ArgumentMatchers.anyObject +import org.mockito.ArgumentMatchers.anyString +import org.mockito.Mock +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@RunWithLooper(setAsMainLooper = true) +@SmallTest +class PulsingGestureListenerTest : SysuiTestCase() { + @Mock + private lateinit var view: NotificationShadeWindowView + @Mock + private lateinit var centralSurfaces: CentralSurfaces + @Mock + private lateinit var dockManager: DockManager + @Mock + private lateinit var falsingManager: FalsingManager + @Mock + private lateinit var ambientDisplayConfiguration: AmbientDisplayConfiguration + @Mock + private lateinit var tunerService: TunerService + @Mock + private lateinit var dumpManager: DumpManager + + private lateinit var tunableCaptor: ArgumentCaptor + private lateinit var underTest: PulsingGestureListener + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + underTest = PulsingGestureListener( + view, + falsingManager, + dockManager, + centralSurfaces, + ambientDisplayConfiguration, + tunerService, + dumpManager + ) + whenever(dockManager.isDocked).thenReturn(false) + } + + @Test + fun testGestureDetector_singleTapEnabled() { + // GIVEN tap is enabled, prox not covered + whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) + updateSettings() + whenever(falsingManager.isProximityNear).thenReturn(false) + + // GIVEN the falsing manager does NOT think the tap is a false tap + whenever(falsingManager.isFalseTap(anyInt())).thenReturn(false) + + // WHEN there's a tap + underTest.onSingleTapConfirmed(downEv) + + // THEN wake up device if dozing + verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString()) + } + + @Test + fun testGestureDetector_doubleTapEnabled() { + // GIVEN double tap is enabled, prox not covered + whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true) + updateSettings() + whenever(falsingManager.isProximityNear).thenReturn(false) + + // GIVEN the falsing manager does NOT think the tap is a false tap + whenever(falsingManager.isFalseDoubleTap).thenReturn(false) + + // WHEN there's a double tap + underTest.onDoubleTap(downEv) + + // THEN wake up device if dozing + verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString()) + } + + @Test + fun testGestureDetector_singleTapEnabled_falsing() { + // GIVEN tap is enabled, prox not covered + whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) + updateSettings() + whenever(falsingManager.isProximityNear).thenReturn(false) + + // GIVEN the falsing manager thinks the tap is a false tap + whenever(falsingManager.isFalseTap(anyInt())).thenReturn(true) + + // WHEN there's a tap + underTest.onSingleTapConfirmed(downEv) + + // THEN the device doesn't wake up + verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString()) + } + + @Test + fun testGestureDetector_doubleTapEnabled_falsing() { + // GIVEN double tap is enabled, prox not covered + whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true) + updateSettings() + whenever(falsingManager.isProximityNear).thenReturn(false) + + // GIVEN the falsing manager thinks the tap is a false tap + whenever(falsingManager.isFalseDoubleTap).thenReturn(true) + + // WHEN there's a tap + underTest.onDoubleTap(downEv) + + // THEN the device doesn't wake up + verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString()) + } + + @Test + fun testGestureDetector_singleTapEnabled_proxCovered() { + // GIVEN tap is enabled, not a false tap based on classifiers + whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) + updateSettings() + whenever(falsingManager.isFalseTap(anyInt())).thenReturn(false) + + // GIVEN prox is covered + whenever(falsingManager.isProximityNear()).thenReturn(true) + + // WHEN there's a tap + underTest.onSingleTapConfirmed(downEv) + + // THEN the device doesn't wake up + verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString()) + } + + @Test + fun testGestureDetector_doubleTapEnabled_proxCovered() { + // GIVEN double tap is enabled, not a false tap based on classifiers + whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true) + updateSettings() + whenever(falsingManager.isFalseDoubleTap).thenReturn(false) + + // GIVEN prox is covered + whenever(falsingManager.isProximityNear()).thenReturn(true) + + // WHEN there's a tap + underTest.onDoubleTap(downEv) + + // THEN the device doesn't wake up + verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString()) + } + + fun updateSettings() { + tunableCaptor = ArgumentCaptor.forClass(Tunable::class.java) + verify(tunerService).addTunable( + tunableCaptor.capture(), + eq(DOZE_DOUBLE_TAP_GESTURE), + eq(DOZE_TAP_SCREEN_GESTURE)) + tunableCaptor.value.onTuningChanged(DOZE_DOUBLE_TAP_GESTURE, "") + tunableCaptor.value.onTuningChanged(DOZE_TAP_SCREEN_GESTURE, "") + } +} + +private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java index 48b5c62da38f5..34c83bd41a022 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java @@ -40,6 +40,7 @@ public class FalsingManagerFake implements FalsingManager { private boolean mIsReportingEnabled; private boolean mIsFalseRobustTap; private boolean mDestroyed; + private boolean mIsProximityNear; private final List mFalsingBeliefListeners = new ArrayList<>(); private final List mTapListeners = new ArrayList<>(); @@ -82,6 +83,10 @@ public class FalsingManagerFake implements FalsingManager { mIsFalseDoubleTap = falseDoubleTap; } + public void setIsProximityNear(boolean proxNear) { + mIsProximityNear = proxNear; + } + @Override public boolean isSimpleTap() { checkDestroyed(); @@ -100,6 +105,11 @@ public class FalsingManagerFake implements FalsingManager { return mIsFalseDoubleTap; } + @Override + public boolean isProximityNear() { + return mIsProximityNear; + } + @VisibleForTesting public void setIsClassifierEnabled(boolean isClassifierEnabled) { mIsClassifierEnabled = isClassifierEnabled; From 4bf4fa18e01df92ae3eec84a8ab583f4b44b4985 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Thu, 25 Aug 2022 20:36:27 +0000 Subject: [PATCH 23/45] Revert "Improve enter split transition" This reverts commit 288d5550cca373358485498e4a1909f58006c9e6. Reason for revert: b/243634747 Change-Id: I3413f82999c068bb58aba8f7a7e40d95991f18c3 (cherry picked from commit af51b4d8a1c70abb3880e21d0ae72cf516ba5751) Merged-In: I3413f82999c068bb58aba8f7a7e40d95991f18c3 --- .../wm/shell/common/split/SplitLayout.java | 51 +++-------------- .../shell/splitscreen/StageCoordinator.java | 55 +++++++------------ .../shell/common/split/SplitLayoutTests.java | 3 +- 3 files changed, 28 insertions(+), 81 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index 83ba909e712d1..85c8ebf454c93 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -80,10 +80,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange public static final int PARALLAX_DISMISSING = 1; public static final int PARALLAX_ALIGN_CENTER = 2; - private static final int FLING_RESIZE_DURATION = 250; - private static final int FLING_SWITCH_DURATION = 350; - private static final int FLING_ENTER_DURATION = 350; - private static final int FLING_EXIT_DURATION = 350; + private static final int FLING_ANIMATION_DURATION = 250; private final int mDividerWindowWidth; private final int mDividerInsets; @@ -96,9 +93,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange private final Rect mBounds1 = new Rect(); // Bounds2 final position should be always at bottom or right private final Rect mBounds2 = new Rect(); - // The temp bounds outside of display bounds for side stage when split screen inactive to avoid - // flicker next time active split screen. - private final Rect mInvisibleBounds = new Rect(); private final Rect mWinBounds1 = new Rect(); private final Rect mWinBounds2 = new Rect(); private final SplitLayoutHandler mSplitLayoutHandler; @@ -147,10 +141,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange resetDividerPosition(); mDimNonImeSide = resources.getBoolean(R.bool.config_dimNonImeAttachedSide); - - mInvisibleBounds.set(mRootBounds); - mInvisibleBounds.offset(isLandscape() ? mRootBounds.right : 0, - isLandscape() ? 0 : mRootBounds.bottom); } private int getDividerInsets(Resources resources, Display display) { @@ -249,12 +239,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange rect.offset(-mRootBounds.left, -mRootBounds.top); } - /** Gets bounds size equal to root bounds but outside of screen, used for position side stage - * when split inactive to avoid flicker when next time active. */ - public void getInvisibleBounds(Rect rect) { - rect.set(mInvisibleBounds); - } - /** Returns leash of the current divider bar. */ @Nullable public SurfaceControl getDividerLeash() { @@ -300,10 +284,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null); initDividerPosition(mTempRect); - mInvisibleBounds.set(mRootBounds); - mInvisibleBounds.offset(isLandscape() ? mRootBounds.right : 0, - isLandscape() ? 0 : mRootBounds.bottom); - return true; } @@ -425,13 +405,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange mFreezeDividerWindow = freezeDividerWindow; } - /** Update current layout as divider put on start or end position. */ - public void setDividerAtBorder(boolean start) { - final int pos = start ? mDividerSnapAlgorithm.getDismissStartTarget().position - : mDividerSnapAlgorithm.getDismissEndTarget().position; - setDividePosition(pos, false /* applyLayoutChange */); - } - /** * Updates bounds with the passing position. Usually used to update recording bounds while * performing animation or dragging divider bar to resize the splits. @@ -476,17 +449,17 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) { switch (snapTarget.flag) { case FLAG_DISMISS_START: - flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION, + flingDividePosition(currentPosition, snapTarget.position, () -> mSplitLayoutHandler.onSnappedToDismiss(false /* bottomOrRight */, EXIT_REASON_DRAG_DIVIDER)); break; case FLAG_DISMISS_END: - flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION, + flingDividePosition(currentPosition, snapTarget.position, () -> mSplitLayoutHandler.onSnappedToDismiss(true /* bottomOrRight */, EXIT_REASON_DRAG_DIVIDER)); break; default: - flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION, + flingDividePosition(currentPosition, snapTarget.position, () -> setDividePosition(snapTarget.position, true /* applyLayoutChange */)); break; } @@ -543,20 +516,12 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange public void flingDividerToDismiss(boolean toEnd, int reason) { final int target = toEnd ? mDividerSnapAlgorithm.getDismissEndTarget().position : mDividerSnapAlgorithm.getDismissStartTarget().position; - flingDividePosition(getDividePosition(), target, FLING_EXIT_DURATION, + flingDividePosition(getDividePosition(), target, () -> mSplitLayoutHandler.onSnappedToDismiss(toEnd, reason)); } - /** Fling divider from current position to center position. */ - public void flingDividerToCenter() { - final int pos = mDividerSnapAlgorithm.getMiddleTarget().position; - flingDividePosition(getDividePosition(), pos, FLING_ENTER_DURATION, - () -> setDividePosition(pos, true /* applyLayoutChange */)); - } - @VisibleForTesting - void flingDividePosition(int from, int to, int duration, - @Nullable Runnable flingFinishedCallback) { + void flingDividePosition(int from, int to, @Nullable Runnable flingFinishedCallback) { if (from == to) { // No animation run, still callback to stop resizing. mSplitLayoutHandler.onLayoutSizeChanged(this); @@ -566,7 +531,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } ValueAnimator animator = ValueAnimator .ofInt(from, to) - .setDuration(duration); + .setDuration(FLING_ANIMATION_DURATION); animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); animator.addUpdateListener( animation -> updateDivideBounds((int) animation.getAnimatedValue())); @@ -623,7 +588,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange AnimatorSet set = new AnimatorSet(); set.playTogether(animator1, animator2, animator3); - set.setDuration(FLING_SWITCH_DURATION); + set.setDuration(FLING_ANIMATION_DURATION); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 21fc01e554c8e..7e83d2fa0a0b7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -25,7 +25,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; -import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; @@ -489,6 +488,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, final WindowContainerTransaction wct = new WindowContainerTransaction(); options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct); + // If split still not active, apply windows bounds first to avoid surface reset to + // wrong pos by SurfaceAnimator from wms. + // TODO(b/223325631): check is it still necessary after improve enter transition done. + if (!mMainStage.isActive()) { + updateWindowBounds(mSplitLayout, wct); + } + wct.sendPendingIntent(intent, fillInIntent, options); mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct); } @@ -635,7 +641,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, wct.startTask(sideTaskId, sideOptions); } // Using legacy transitions, so we can't use blast sync since it conflicts. - mSyncQueue.queue(wct); + mTaskOrganizer.applyTransaction(wct); mSyncQueue.runInSync(t -> { setDividerVisibility(true, t); updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); @@ -887,13 +893,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mShouldUpdateRecents = false; mIsDividerRemoteAnimating = false; - mSplitLayout.getInvisibleBounds(mTempRect1); if (childrenToTop == null) { mSideStage.removeAllTasks(wct, false /* toTop */); mMainStage.deactivate(wct, false /* toTop */); wct.reorder(mRootTaskInfo.token, false /* onTop */); - wct.setForceTranslucent(mRootTaskInfo.token, true); - wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1); onTransitionAnimationComplete(); } else { // Expand to top side split as full screen for fading out decor animation and dismiss @@ -904,32 +907,27 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, ? mSideStage : mMainStage; tempFullStage.resetBounds(wct); wct.setSmallestScreenWidthDp(tempFullStage.mRootTaskInfo.token, - SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); + mRootTaskInfo.configuration.smallestScreenWidthDp); dismissStage.dismiss(wct, false /* toTop */); } mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { t.setWindowCrop(mMainStage.mRootLeash, null) .setWindowCrop(mSideStage.mRootLeash, null); + t.setPosition(mMainStage.mRootLeash, 0, 0) + .setPosition(mSideStage.mRootLeash, 0, 0); t.hide(mMainStage.mDimLayer).hide(mSideStage.mDimLayer); setDividerVisibility(false, t); - if (childrenToTop == null) { - t.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.right); - } else { - // In this case, exit still under progress, fade out the split decor after first WCT - // done and do remaining WCT after animation finished. + // In this case, exit still under progress, fade out the split decor after first WCT + // done and do remaining WCT after animation finished. + if (childrenToTop != null) { childrenToTop.fadeOutDecor(() -> { WindowContainerTransaction finishedWCT = new WindowContainerTransaction(); mIsExiting = false; childrenToTop.dismiss(finishedWCT, true /* toTop */); finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */); - finishedWCT.setForceTranslucent(mRootTaskInfo.token, true); - finishedWCT.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1); - mSyncQueue.queue(finishedWCT); - mSyncQueue.runInSync(at -> { - at.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.right); - }); + mTaskOrganizer.applyTransaction(finishedWCT); onTransitionAnimationComplete(); }); } @@ -998,7 +996,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mMainStage.activate(wct, true /* includingTopTask */); updateWindowBounds(mSplitLayout, wct); wct.reorder(mRootTaskInfo.token, true); - wct.setForceTranslucent(mRootTaskInfo.token, false); } void finishEnterSplitScreen(SurfaceControl.Transaction t) { @@ -1224,13 +1221,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Make the stages adjacent to each other so they occlude what's behind them. wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token); wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token); - wct.setForceTranslucent(mRootTaskInfo.token, true); - mSplitLayout.getInvisibleBounds(mTempRect1); - wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1); - mSyncQueue.queue(wct); - mSyncQueue.runInSync(t -> { - t.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.top); - }); + mTaskOrganizer.applyTransaction(wct); } private void onRootTaskVanished() { @@ -1386,17 +1377,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // TODO (b/238697912) : Add the validation to prevent entering non-recovered status final WindowContainerTransaction wct = new WindowContainerTransaction(); mSplitLayout.init(); - mSplitLayout.setDividerAtBorder(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT); - mMainStage.activate(wct, true /* includingTopTask */); - updateWindowBounds(mSplitLayout, wct); - wct.reorder(mRootTaskInfo.token, true); - wct.setForceTranslucent(mRootTaskInfo.token, false); + prepareEnterSplitScreen(wct); mSyncQueue.queue(wct); - mSyncQueue.runInSync(t -> { - updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); - - mSplitLayout.flingDividerToCenter(); - }); + mSyncQueue.runInSync(t -> + updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */)); } if (mMainStageListener.mHasChildren && mSideStageListener.mHasChildren) { mShouldUpdateRecents = true; @@ -1838,7 +1822,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // properly for the animation itself. mSplitLayout.release(); mSplitLayout.resetDividerPosition(); - mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT; mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED; } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java index 695550dd8fa53..95725bbfd8552 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java @@ -159,8 +159,7 @@ public class SplitLayoutTests extends ShellTestCase { } private void waitDividerFlingFinished() { - verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), anyInt(), - mRunnableCaptor.capture()); + verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), mRunnableCaptor.capture()); mRunnableCaptor.getValue().run(); } From b50cf593bba200caeed2ca043d1fc5341ee9b4e9 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Mon, 29 Aug 2022 18:32:27 +0000 Subject: [PATCH 24/45] Revert "Port lux and nit mappings from device config to display specific configs" This reverts commit 716bd5ae8aa66aa044a0706774732a50fcb117f4. Reason for revert: b/244130109 Change-Id: Ieb3736c258f1e7c3b6106b2d8f13d2af0c5cabcb (cherry picked from commit c55fa32f89164c42cd4386389fa1f7cdc9a559ff) Merged-In: Ieb3736c258f1e7c3b6106b2d8f13d2af0c5cabcb --- core/res/res/values/config.xml | 5 +- .../display/BrightnessMappingStrategy.java | 6 +- .../server/display/DisplayDeviceConfig.java | 113 +----------------- .../display-device-config/autobrightness.xsd | 33 +++++ .../display-device-config.xsd | 71 +---------- .../display-device-config/schema/current.txt | 15 --- .../display/LocalDisplayAdapterTest.java | 6 - .../display/DisplayDeviceConfigTest.java | 107 ++--------------- 8 files changed, 56 insertions(+), 300 deletions(-) create mode 100644 services/core/xsd/display-device-config/autobrightness.xsd diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 88206270ca7fc..8152b79c86591 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1565,7 +1565,8 @@ false + + + + + + + + + + + + + + \ No newline at end of file diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd index 98f83d8c0d093..bea5e2c2de748 100644 --- a/services/core/xsd/display-device-config/display-device-config.xsd +++ b/services/core/xsd/display-device-config/display-device-config.xsd @@ -23,6 +23,7 @@ + @@ -342,74 +343,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt index e5d26177b725b..e9a9269467641 100644 --- a/services/core/xsd/display-device-config/schema/current.txt +++ b/services/core/xsd/display-device-config/schema/current.txt @@ -5,10 +5,8 @@ package com.android.server.display.config { ctor public AutoBrightness(); method public final java.math.BigInteger getBrighteningLightDebounceMillis(); method public final java.math.BigInteger getDarkeningLightDebounceMillis(); - method public final com.android.server.display.config.DisplayBrightnessMapping getDisplayBrightnessMapping(); method public final void setBrighteningLightDebounceMillis(java.math.BigInteger); method public final void setDarkeningLightDebounceMillis(java.math.BigInteger); - method public final void setDisplayBrightnessMapping(com.android.server.display.config.DisplayBrightnessMapping); } public class BrightnessThresholds { @@ -45,19 +43,6 @@ package com.android.server.display.config { method public java.util.List getDensity(); } - public class DisplayBrightnessMapping { - ctor public DisplayBrightnessMapping(); - method public final java.util.List getDisplayBrightnessPoint(); - } - - public class DisplayBrightnessPoint { - ctor public DisplayBrightnessPoint(); - method public final java.math.BigInteger getLux(); - method public final java.math.BigInteger getNits(); - method public final void setLux(java.math.BigInteger); - method public final void setNits(java.math.BigInteger); - } - public class DisplayConfiguration { ctor public DisplayConfiguration(); method @NonNull public final com.android.server.display.config.Thresholds getAmbientBrightnessChangeThresholds(); diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index 220cd890e045d..617321beadd2b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -149,12 +149,6 @@ public class LocalDisplayAdapterTest { .thenReturn(mockArray); when(mMockedResources.obtainTypedArray(R.array.config_roundedCornerBottomRadiusArray)) .thenReturn(mockArray); - when(mMockedResources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)) - .thenReturn(mockArray); - when(mMockedResources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessLevels)) - .thenReturn(mockArray); } @After diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java index 261b882319d82..03ea6137074d0 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java @@ -19,19 +19,16 @@ package com.android.server.display; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.anyFloat; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; -import android.content.res.TypedArray; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -55,16 +52,22 @@ public final class DisplayDeviceConfigTest { private Resources mResources; @Before - public void setUp() { + public void setUp() throws IOException { MockitoAnnotations.initMocks(this); when(mContext.getResources()).thenReturn(mResources); mockDeviceConfigs(); + try { + Path tempFile = Files.createTempFile("display_config", ".tmp"); + Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8)); + mDisplayDeviceConfig = new DisplayDeviceConfig(mContext); + mDisplayDeviceConfig.initFromFile(tempFile.toFile()); + } catch (IOException e) { + throw new IOException("Failed to setup the display device config.", e); + } } @Test - public void testConfigValuesFromDisplayConfig() throws IOException { - setupDisplayDeviceConfigFromDisplayConfigFile(); - + public void testConfigValues() { assertEquals(mDisplayDeviceConfig.getAmbientHorizonLong(), 5000); assertEquals(mDisplayDeviceConfig.getAmbientHorizonShort(), 50); assertEquals(mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis(), 3000); @@ -85,24 +88,10 @@ public final class DisplayDeviceConfigTest { assertEquals(mDisplayDeviceConfig.getScreenDarkeningMinThreshold(), 0.002, 0.000001f); assertEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLightDebounce(), 2000); assertEquals(mDisplayDeviceConfig.getAutoBrightnessDarkeningLightDebounce(), 1000); - assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new - float[]{50.0f, 80.0f}, 0.0f); - assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new - float[]{45.0f, 75.0f}, 0.0f); + // Todo(brup): Add asserts for BrightnessThrottlingData, DensityMapping, // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor. - } - - @Test - public void testConfigValuesFromDeviceConfig() { - setupDisplayDeviceConfigFromDeviceConfigFile(); - assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new - float[]{0.0f, 110.0f, 500.0f}, 0.0f); - assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new - float[]{2.0f, 200.0f, 600.0f}, 0.0f); - // Todo(brup): Add asserts for BrightnessThrottlingData, DensityMapping, - // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor. - + // Also add test for the case where optional display configs are null } private String getContent() { @@ -125,16 +114,6 @@ public final class DisplayDeviceConfigTest { + "\n" + "2000\n" + "1000\n" - + "\n" - + "\n" - + "50\n" - + "45\n" - + "\n" - + "\n" - + "80\n" - + "75\n" - + "\n" - + "\n" + "\n" + "\n" + "0.62\n" @@ -206,64 +185,4 @@ public final class DisplayDeviceConfigTest { when(mResources.getFloat(com.android.internal.R.dimen .config_screenBrightnessSettingMaximumFloat)).thenReturn(1.0f); } - - private void setupDisplayDeviceConfigFromDisplayConfigFile() throws IOException { - Path tempFile = Files.createTempFile("display_config", ".tmp"); - Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8)); - mDisplayDeviceConfig = new DisplayDeviceConfig(mContext); - mDisplayDeviceConfig.initFromFile(tempFile.toFile()); - } - - private void setupDisplayDeviceConfigFromDeviceConfigFile() { - TypedArray screenBrightnessNits = createFloatTypedArray(new float[]{2.0f, 250.0f, 650.0f}); - when(mResources.obtainTypedArray( - com.android.internal.R.array.config_screenBrightnessNits)) - .thenReturn(screenBrightnessNits); - TypedArray screenBrightnessBacklight = createFloatTypedArray(new - float[]{0.0f, 120.0f, 255.0f}); - when(mResources.obtainTypedArray( - com.android.internal.R.array.config_screenBrightnessBacklight)) - .thenReturn(screenBrightnessBacklight); - when(mResources.getIntArray(com.android.internal.R.array - .config_screenBrightnessBacklight)).thenReturn(new int[]{0, 120, 255}); - - when(mResources.getIntArray(com.android.internal.R.array - .config_autoBrightnessLevels)).thenReturn(new int[]{30, 80}); - when(mResources.getIntArray(com.android.internal.R.array - .config_autoBrightnessDisplayValuesNits)).thenReturn(new int[]{25, 55}); - - TypedArray screenBrightnessLevelNits = createFloatTypedArray(new - float[]{2.0f, 200.0f, 600.0f}); - when(mResources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)) - .thenReturn(screenBrightnessLevelNits); - TypedArray screenBrightnessLevelLux = createFloatTypedArray(new - float[]{0.0f, 110.0f, 500.0f}); - when(mResources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessLevels)) - .thenReturn(screenBrightnessLevelLux); - - mDisplayDeviceConfig = DisplayDeviceConfig.create(mContext, true); - - } - - private TypedArray createFloatTypedArray(float[] vals) { - TypedArray mockArray = mock(TypedArray.class); - when(mockArray.length()).thenAnswer(invocation -> { - return vals.length; - }); - when(mockArray.getFloat(anyInt(), anyFloat())).thenAnswer(invocation -> { - final float def = (float) invocation.getArguments()[1]; - if (vals == null) { - return def; - } - int idx = (int) invocation.getArguments()[0]; - if (idx >= 0 && idx < vals.length) { - return vals[idx]; - } else { - return def; - } - }); - return mockArray; - } } From 5bf8901e1468ae037cf7b949c2295c6ab28c8c00 Mon Sep 17 00:00:00 2001 From: Neha Jain Date: Mon, 29 Aug 2022 18:32:27 +0000 Subject: [PATCH 25/45] Revert "Port lux and nit mappings from device config to display specific configs" This reverts commit 716bd5ae8aa66aa044a0706774732a50fcb117f4. Reason for revert: b/244130109 Change-Id: Ieb3736c258f1e7c3b6106b2d8f13d2af0c5cabcb (cherry picked from commit c55fa32f89164c42cd4386389fa1f7cdc9a559ff) Merged-In: Ieb3736c258f1e7c3b6106b2d8f13d2af0c5cabcb --- core/res/res/values/config.xml | 5 +- .../display/BrightnessMappingStrategy.java | 6 +- .../server/display/DisplayDeviceConfig.java | 113 +----------------- .../display-device-config/autobrightness.xsd | 33 +++++ .../display-device-config.xsd | 71 +---------- .../display-device-config/schema/current.txt | 15 --- .../display/LocalDisplayAdapterTest.java | 6 - .../display/DisplayDeviceConfigTest.java | 107 ++--------------- 8 files changed, 56 insertions(+), 300 deletions(-) create mode 100644 services/core/xsd/display-device-config/autobrightness.xsd diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 88206270ca7fc..8152b79c86591 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1565,7 +1565,8 @@ false + + + + + + + + + + + + + + \ No newline at end of file diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd index 98f83d8c0d093..bea5e2c2de748 100644 --- a/services/core/xsd/display-device-config/display-device-config.xsd +++ b/services/core/xsd/display-device-config/display-device-config.xsd @@ -23,6 +23,7 @@ + @@ -342,74 +343,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt index e5d26177b725b..e9a9269467641 100644 --- a/services/core/xsd/display-device-config/schema/current.txt +++ b/services/core/xsd/display-device-config/schema/current.txt @@ -5,10 +5,8 @@ package com.android.server.display.config { ctor public AutoBrightness(); method public final java.math.BigInteger getBrighteningLightDebounceMillis(); method public final java.math.BigInteger getDarkeningLightDebounceMillis(); - method public final com.android.server.display.config.DisplayBrightnessMapping getDisplayBrightnessMapping(); method public final void setBrighteningLightDebounceMillis(java.math.BigInteger); method public final void setDarkeningLightDebounceMillis(java.math.BigInteger); - method public final void setDisplayBrightnessMapping(com.android.server.display.config.DisplayBrightnessMapping); } public class BrightnessThresholds { @@ -45,19 +43,6 @@ package com.android.server.display.config { method public java.util.List getDensity(); } - public class DisplayBrightnessMapping { - ctor public DisplayBrightnessMapping(); - method public final java.util.List getDisplayBrightnessPoint(); - } - - public class DisplayBrightnessPoint { - ctor public DisplayBrightnessPoint(); - method public final java.math.BigInteger getLux(); - method public final java.math.BigInteger getNits(); - method public final void setLux(java.math.BigInteger); - method public final void setNits(java.math.BigInteger); - } - public class DisplayConfiguration { ctor public DisplayConfiguration(); method @NonNull public final com.android.server.display.config.Thresholds getAmbientBrightnessChangeThresholds(); diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index 220cd890e045d..617321beadd2b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -149,12 +149,6 @@ public class LocalDisplayAdapterTest { .thenReturn(mockArray); when(mMockedResources.obtainTypedArray(R.array.config_roundedCornerBottomRadiusArray)) .thenReturn(mockArray); - when(mMockedResources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)) - .thenReturn(mockArray); - when(mMockedResources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessLevels)) - .thenReturn(mockArray); } @After diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java index 261b882319d82..03ea6137074d0 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java @@ -19,19 +19,16 @@ package com.android.server.display; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.anyFloat; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; -import android.content.res.TypedArray; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -55,16 +52,22 @@ public final class DisplayDeviceConfigTest { private Resources mResources; @Before - public void setUp() { + public void setUp() throws IOException { MockitoAnnotations.initMocks(this); when(mContext.getResources()).thenReturn(mResources); mockDeviceConfigs(); + try { + Path tempFile = Files.createTempFile("display_config", ".tmp"); + Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8)); + mDisplayDeviceConfig = new DisplayDeviceConfig(mContext); + mDisplayDeviceConfig.initFromFile(tempFile.toFile()); + } catch (IOException e) { + throw new IOException("Failed to setup the display device config.", e); + } } @Test - public void testConfigValuesFromDisplayConfig() throws IOException { - setupDisplayDeviceConfigFromDisplayConfigFile(); - + public void testConfigValues() { assertEquals(mDisplayDeviceConfig.getAmbientHorizonLong(), 5000); assertEquals(mDisplayDeviceConfig.getAmbientHorizonShort(), 50); assertEquals(mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis(), 3000); @@ -85,24 +88,10 @@ public final class DisplayDeviceConfigTest { assertEquals(mDisplayDeviceConfig.getScreenDarkeningMinThreshold(), 0.002, 0.000001f); assertEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLightDebounce(), 2000); assertEquals(mDisplayDeviceConfig.getAutoBrightnessDarkeningLightDebounce(), 1000); - assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new - float[]{50.0f, 80.0f}, 0.0f); - assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new - float[]{45.0f, 75.0f}, 0.0f); + // Todo(brup): Add asserts for BrightnessThrottlingData, DensityMapping, // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor. - } - - @Test - public void testConfigValuesFromDeviceConfig() { - setupDisplayDeviceConfigFromDeviceConfigFile(); - assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new - float[]{0.0f, 110.0f, 500.0f}, 0.0f); - assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new - float[]{2.0f, 200.0f, 600.0f}, 0.0f); - // Todo(brup): Add asserts for BrightnessThrottlingData, DensityMapping, - // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor. - + // Also add test for the case where optional display configs are null } private String getContent() { @@ -125,16 +114,6 @@ public final class DisplayDeviceConfigTest { + "\n" + "2000\n" + "1000\n" - + "\n" - + "\n" - + "50\n" - + "45\n" - + "\n" - + "\n" - + "80\n" - + "75\n" - + "\n" - + "\n" + "\n" + "\n" + "0.62\n" @@ -206,64 +185,4 @@ public final class DisplayDeviceConfigTest { when(mResources.getFloat(com.android.internal.R.dimen .config_screenBrightnessSettingMaximumFloat)).thenReturn(1.0f); } - - private void setupDisplayDeviceConfigFromDisplayConfigFile() throws IOException { - Path tempFile = Files.createTempFile("display_config", ".tmp"); - Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8)); - mDisplayDeviceConfig = new DisplayDeviceConfig(mContext); - mDisplayDeviceConfig.initFromFile(tempFile.toFile()); - } - - private void setupDisplayDeviceConfigFromDeviceConfigFile() { - TypedArray screenBrightnessNits = createFloatTypedArray(new float[]{2.0f, 250.0f, 650.0f}); - when(mResources.obtainTypedArray( - com.android.internal.R.array.config_screenBrightnessNits)) - .thenReturn(screenBrightnessNits); - TypedArray screenBrightnessBacklight = createFloatTypedArray(new - float[]{0.0f, 120.0f, 255.0f}); - when(mResources.obtainTypedArray( - com.android.internal.R.array.config_screenBrightnessBacklight)) - .thenReturn(screenBrightnessBacklight); - when(mResources.getIntArray(com.android.internal.R.array - .config_screenBrightnessBacklight)).thenReturn(new int[]{0, 120, 255}); - - when(mResources.getIntArray(com.android.internal.R.array - .config_autoBrightnessLevels)).thenReturn(new int[]{30, 80}); - when(mResources.getIntArray(com.android.internal.R.array - .config_autoBrightnessDisplayValuesNits)).thenReturn(new int[]{25, 55}); - - TypedArray screenBrightnessLevelNits = createFloatTypedArray(new - float[]{2.0f, 200.0f, 600.0f}); - when(mResources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessDisplayValuesNits)) - .thenReturn(screenBrightnessLevelNits); - TypedArray screenBrightnessLevelLux = createFloatTypedArray(new - float[]{0.0f, 110.0f, 500.0f}); - when(mResources.obtainTypedArray( - com.android.internal.R.array.config_autoBrightnessLevels)) - .thenReturn(screenBrightnessLevelLux); - - mDisplayDeviceConfig = DisplayDeviceConfig.create(mContext, true); - - } - - private TypedArray createFloatTypedArray(float[] vals) { - TypedArray mockArray = mock(TypedArray.class); - when(mockArray.length()).thenAnswer(invocation -> { - return vals.length; - }); - when(mockArray.getFloat(anyInt(), anyFloat())).thenAnswer(invocation -> { - final float def = (float) invocation.getArguments()[1]; - if (vals == null) { - return def; - } - int idx = (int) invocation.getArguments()[0]; - if (idx >= 0 && idx < vals.length) { - return vals[idx]; - } else { - return def; - } - }); - return mockArray; - } } From 9f1bb9950fcdd848d341fa3ccdf754f3fd135935 Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Mon, 5 Sep 2022 10:30:14 +0000 Subject: [PATCH 26/45] Fix no response after entered split screen Make sure to update stage root's bounds and reset the surface position of opening apps to prevent double offset instead. Fix: 245055674 Bug: 244671191 Test: enter split screen by long pressing on shortcut, anotehr side can receive touch events after entered split screen. Change-Id: Ie186cfa3b1406514ce8c33cd7321b8b9df40af26 (cherry picked from commit 768ee2c04cc8ca9bb48b7564920cb88a98c86387) Merged-In: Ie186cfa3b1406514ce8c33cd7321b8b9df40af26 --- .../shell/splitscreen/StageCoordinator.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 8d405f4f6fcf3..199007d7f577e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -589,17 +589,17 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return; } - // The surfaces of splitting tasks were placed with window bounds when preparing the - // transition, so update divider surface separately. - final RemoteAnimationTarget dividerTarget = getDividerBarLegacyTarget(); - mSplitLayout.getRefDividerBounds(mTempRect1); - t.setLayer(dividerTarget.leash, Integer.MAX_VALUE) - .setPosition(dividerTarget.leash, mTempRect1.left, mTempRect1.top); - setDividerVisibility(true, t); + // Wrap the divider bar into non-apps target to animate together. + nonApps = ArrayUtils.appendElement(RemoteAnimationTarget.class, nonApps, + getDividerBarLegacyTarget()); + updateSurfaceBounds(mSplitLayout, t, false); + setDividerVisibility(true, t); for (int i = 0; i < apps.length; ++i) { if (apps[i].mode == MODE_OPENING) { t.show(apps[i].leash); + // Reset the surface position of the opening app to prevent double-offset. + t.setPosition(apps[i].leash, 0, 0); } } t.apply(); @@ -614,9 +614,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, }; Transitions.setRunningRemoteTransitionDelegate(adapter.getCallingApplication()); try { - adapter.getRunner().onAnimationStart(transit, apps, wallpapers, - ArrayUtils.appendElement(RemoteAnimationTarget.class, nonApps, - dividerTarget), wrapCallback); + adapter.getRunner().onAnimationStart( + transit, apps, wallpapers, nonApps, wrapCallback); } catch (RemoteException e) { Slog.e(TAG, "Error starting remote animation", e); } From 26e4efb9259df4517975703297ca253ab09ed157 Mon Sep 17 00:00:00 2001 From: Andrey Epin Date: Thu, 8 Sep 2022 17:29:22 +0000 Subject: [PATCH 27/45] Revert "Load direct-share icons asynchronously" This reverts commit 5650e0c3c8e1bf63ceb117ae83b46a42598e8333. Reason for revert: broken functionality b/245681929 Fix: 245681929 Change-Id: I50fce5cca55ee40e66c0915759bfa930848588b9 (cherry picked from commit 70a4601f625ec810faab1b14ec1df2565f01959e) Merged-In: I50fce5cca55ee40e66c0915759bfa930848588b9 --- .../internal/app/ChooserListAdapter.java | 135 +++------------ .../internal/app/ResolverListAdapter.java | 9 +- .../app/chooser/SelectableTargetInfo.java | 33 +--- .../internal/app/ChooserListAdapterTest.kt | 155 ------------------ 4 files changed, 28 insertions(+), 304 deletions(-) delete mode 100644 core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index e57b90ad16127..1ec5325623ec1 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -43,7 +43,6 @@ import android.view.ViewGroup; import android.widget.TextView; import com.android.internal.R; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.app.chooser.ChooserTargetInfo; import com.android.internal.app.chooser.DisplayResolveInfo; @@ -87,7 +86,7 @@ public class ChooserListAdapter extends ResolverListAdapter { private final ChooserActivityLogger mChooserActivityLogger; private int mNumShortcutResults = 0; - private final Map mIconLoaders = new HashMap<>(); + private Map mIconLoaders = new HashMap<>(); private boolean mApplySharingAppLimits; // Reserve spots for incoming direct share targets by adding placeholders @@ -105,8 +104,6 @@ public class ChooserListAdapter extends ResolverListAdapter { private AppPredictor mAppPredictor; private AppPredictor.Callback mAppPredictorCallback; - private LoadDirectShareIconTaskProvider mTestLoadDirectShareTaskProvider; - // For pinned direct share labels, if the text spans multiple lines, the TextView will consume // the full width, even if the characters actually take up less than that. Measure the actual // line widths and constrain the View's width based upon that so that the pin doesn't end up @@ -243,6 +240,7 @@ public class ChooserListAdapter extends ResolverListAdapter { mListViewDataChanged = false; } + private void createPlaceHolders() { mNumShortcutResults = 0; mServiceTargets.clear(); @@ -267,25 +265,31 @@ public class ChooserListAdapter extends ResolverListAdapter { return; } - if (info instanceof DisplayResolveInfo) { - DisplayResolveInfo dri = (DisplayResolveInfo) info; - holder.bindLabel(dri.getDisplayLabel(), dri.getExtendedInfo(), alwaysShowSubLabel()); - startDisplayResolveInfoIconLoading(holder, dri); - } else { + if (!(info instanceof DisplayResolveInfo)) { holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo(), alwaysShowSubLabel()); + holder.bindIcon(info); if (info instanceof SelectableTargetInfo) { - SelectableTargetInfo selectableInfo = (SelectableTargetInfo) info; // direct share targets should append the application name for a better readout - DisplayResolveInfo rInfo = selectableInfo.getDisplayResolveInfo(); + DisplayResolveInfo rInfo = ((SelectableTargetInfo) info).getDisplayResolveInfo(); CharSequence appName = rInfo != null ? rInfo.getDisplayLabel() : ""; - CharSequence extendedInfo = selectableInfo.getExtendedInfo(); - String contentDescription = String.join(" ", selectableInfo.getDisplayLabel(), + CharSequence extendedInfo = info.getExtendedInfo(); + String contentDescription = String.join(" ", info.getDisplayLabel(), extendedInfo != null ? extendedInfo : "", appName); holder.updateContentDescription(contentDescription); - startSelectableTargetInfoIconLoading(holder, selectableInfo); + } + } else { + DisplayResolveInfo dri = (DisplayResolveInfo) info; + holder.bindLabel(dri.getDisplayLabel(), dri.getExtendedInfo(), alwaysShowSubLabel()); + LoadIconTask task = mIconLoaders.get(dri); + if (task == null) { + task = new LoadIconTask(dri, holder); + mIconLoaders.put(dri, task); + task.execute(); } else { - holder.bindIcon(info); + // The holder was potentially changed as the underlying items were + // reshuffled, so reset the target holder + task.setViewHolder(holder); } } @@ -326,32 +330,6 @@ public class ChooserListAdapter extends ResolverListAdapter { } } - private void startDisplayResolveInfoIconLoading(ViewHolder holder, DisplayResolveInfo info) { - LoadIconTask task = (LoadIconTask) mIconLoaders.get(info); - if (task == null) { - task = new LoadIconTask(info, holder); - mIconLoaders.put(info, task); - task.execute(); - } else { - // The holder was potentially changed as the underlying items were - // reshuffled, so reset the target holder - task.setViewHolder(holder); - } - } - - private void startSelectableTargetInfoIconLoading( - ViewHolder holder, SelectableTargetInfo info) { - LoadDirectShareIconTask task = (LoadDirectShareIconTask) mIconLoaders.get(info); - if (task == null) { - task = mTestLoadDirectShareTaskProvider == null - ? new LoadDirectShareIconTask(info) - : mTestLoadDirectShareTaskProvider.get(); - mIconLoaders.put(info, task); - task.loadIcon(); - } - task.setViewHolder(holder); - } - void updateAlphabeticalList() { new AsyncTask>() { @Override @@ -366,7 +344,7 @@ public class ChooserListAdapter extends ResolverListAdapter { Map consolidated = new HashMap<>(); for (DisplayResolveInfo info : allTargets) { String resolvedTarget = info.getResolvedComponentName().getPackageName() - + '#' + info.getDisplayLabel(); + + '#' + info.getDisplayLabel(); DisplayResolveInfo multiDri = consolidated.get(resolvedTarget); if (multiDri == null) { consolidated.put(resolvedTarget, info); @@ -375,7 +353,7 @@ public class ChooserListAdapter extends ResolverListAdapter { } else { // create consolidated target from the single DisplayResolveInfo MultiDisplayResolveInfo multiDisplayResolveInfo = - new MultiDisplayResolveInfo(resolvedTarget, multiDri); + new MultiDisplayResolveInfo(resolvedTarget, multiDri); multiDisplayResolveInfo.addTarget(info); consolidated.put(resolvedTarget, multiDisplayResolveInfo); } @@ -761,25 +739,11 @@ public class ChooserListAdapter extends ResolverListAdapter { } } - /** - * An alias for onBindView to use with unit tests. - */ - @VisibleForTesting - public void testViewBind(View view, TargetInfo info, int position) { - onBindView(view, info, position); - } - - @VisibleForTesting - public void setTestLoadDirectShareTaskProvider(LoadDirectShareIconTaskProvider provider) { - mTestLoadDirectShareTaskProvider = provider; - } - /** * Necessary methods to communicate between {@link ChooserListAdapter} * and {@link ChooserActivity}. */ - @VisibleForTesting - public interface ChooserListCommunicator extends ResolverListCommunicator { + interface ChooserListCommunicator extends ResolverListCommunicator { int getMaxRankedTargets(); @@ -787,59 +751,4 @@ public class ChooserListAdapter extends ResolverListAdapter { boolean isSendAction(Intent targetIntent); } - - /** - * Loads direct share targets icons. - */ - @VisibleForTesting - public class LoadDirectShareIconTask extends AsyncTask { - private final SelectableTargetInfo mTargetInfo; - private ViewHolder mViewHolder; - - private LoadDirectShareIconTask(SelectableTargetInfo targetInfo) { - mTargetInfo = targetInfo; - } - - @Override - protected Void doInBackground(Void... voids) { - mTargetInfo.loadIcon(); - return null; - } - - @Override - protected void onPostExecute(Void arg) { - if (mViewHolder != null) { - mViewHolder.bindIcon(mTargetInfo); - notifyDataSetChanged(); - } - } - - /** - * Specifies a view holder that will be updated when the task is completed. - */ - public void setViewHolder(ViewHolder viewHolder) { - mViewHolder = viewHolder; - mViewHolder.bindIcon(mTargetInfo); - notifyDataSetChanged(); - } - - /** - * An alias for execute to use with unit tests. - */ - public void loadIcon() { - execute(); - } - } - - /** - * An interface for the unit tests to override icon loading task creation - */ - @VisibleForTesting - public interface LoadDirectShareIconTaskProvider { - /** - * Provides an instance of the task. - * @return - */ - LoadDirectShareIconTask get(); - } } diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index 3a3baa726f173..66fff5c13ab73 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -834,11 +834,7 @@ public class ResolverListAdapter extends BaseAdapter { void onHandlePackagesChanged(ResolverListAdapter listAdapter); } - /** - * A view holder. - */ - @VisibleForTesting - public static class ViewHolder { + static class ViewHolder { public View itemView; public Drawable defaultItemViewBackground; @@ -846,8 +842,7 @@ public class ResolverListAdapter extends BaseAdapter { public TextView text2; public ImageView icon; - @VisibleForTesting - public ViewHolder(View view) { + ViewHolder(View view) { itemView = view; defaultItemViewBackground = view.getBackground(); text = (TextView) view.findViewById(com.android.internal.R.id.text1); diff --git a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java index 37eab40ba2b8a..264e4f76d35df 100644 --- a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java +++ b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java @@ -37,7 +37,6 @@ import android.service.chooser.ChooserTarget; import android.text.SpannableStringBuilder; import android.util.Log; -import com.android.internal.annotations.GuardedBy; import com.android.internal.app.ChooserActivity; import com.android.internal.app.ResolverActivity; import com.android.internal.app.ResolverListAdapter.ActivityInfoPresentationGetter; @@ -60,11 +59,8 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { private final String mDisplayLabel; private final PackageManager mPm; private final SelectableTargetInfoCommunicator mSelectableTargetInfoCommunicator; - @GuardedBy("this") - private ShortcutInfo mShortcutInfo; private Drawable mBadgeIcon = null; private CharSequence mBadgeContentDescription; - @GuardedBy("this") private Drawable mDisplayIcon; private final Intent mFillInIntent; private final int mFillInFlags; @@ -82,7 +78,6 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { mModifiedScore = modifiedScore; mPm = mContext.getPackageManager(); mSelectableTargetInfoCommunicator = selectableTargetInfoComunicator; - mShortcutInfo = shortcutInfo; mIsPinned = shortcutInfo != null && shortcutInfo.isPinned(); if (sourceInfo != null) { final ResolveInfo ri = sourceInfo.getResolveInfo(); @@ -97,6 +92,8 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { } } } + // TODO(b/121287224): do this in the background thread, and only for selected targets + mDisplayIcon = getChooserTargetIconDrawable(chooserTarget, shortcutInfo); if (sourceInfo != null) { mBackupResolveInfo = null; @@ -121,10 +118,7 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { mChooserTarget = other.mChooserTarget; mBadgeIcon = other.mBadgeIcon; mBadgeContentDescription = other.mBadgeContentDescription; - synchronized (other) { - mShortcutInfo = other.mShortcutInfo; - mDisplayIcon = other.mDisplayIcon; - } + mDisplayIcon = other.mDisplayIcon; mFillInIntent = fillInIntent; mFillInFlags = flags; mModifiedScore = other.mModifiedScore; @@ -147,25 +141,6 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { return mSourceInfo; } - /** - * Load display icon, if needed. - */ - public void loadIcon() { - ShortcutInfo shortcutInfo; - Drawable icon; - synchronized (this) { - shortcutInfo = mShortcutInfo; - icon = mDisplayIcon; - } - if (icon == null && shortcutInfo != null) { - icon = getChooserTargetIconDrawable(mChooserTarget, shortcutInfo); - synchronized (this) { - mDisplayIcon = icon; - mShortcutInfo = null; - } - } - } - private Drawable getChooserTargetIconDrawable(ChooserTarget target, @Nullable ShortcutInfo shortcutInfo) { Drawable directShareIcon = null; @@ -295,7 +270,7 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { } @Override - public synchronized Drawable getDisplayIcon(Context context) { + public Drawable getDisplayIcon(Context context) { return mDisplayIcon; } diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt b/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt deleted file mode 100644 index f027e0b50c18d..0000000000000 --- a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.app - -import android.content.ComponentName -import android.content.pm.PackageManager -import android.os.Bundle -import android.service.chooser.ChooserTarget -import android.view.View -import android.widget.FrameLayout -import android.widget.ImageView -import android.widget.TextView -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import com.android.internal.R -import com.android.internal.app.chooser.SelectableTargetInfo -import com.android.internal.app.chooser.SelectableTargetInfo.SelectableTargetInfoCommunicator -import com.android.server.testutils.any -import com.android.server.testutils.mock -import com.android.server.testutils.whenever -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito.anyInt -import org.mockito.Mockito.doNothing -import org.mockito.Mockito.times -import org.mockito.Mockito.verify - -@RunWith(AndroidJUnit4::class) -class ChooserListAdapterTest { - private val packageManager = mock { - whenever(resolveActivity(any(), anyInt())).thenReturn(mock()) - } - private val context = InstrumentationRegistry.getInstrumentation().getContext() - private val resolverListController = mock() - private val chooserListCommunicator = mock { - whenever(maxRankedTargets).thenReturn(0) - } - private val selectableTargetInfoCommunicator = - mock { - whenever(targetIntent).thenReturn(mock()) - } - private val chooserActivityLogger = mock() - - private val testSubject = ChooserListAdapter( - context, - emptyList(), - emptyArray(), - emptyList(), - false, - resolverListController, - chooserListCommunicator, - selectableTargetInfoCommunicator, - packageManager, - chooserActivityLogger - ) - - @Test - fun testDirectShareTargetLoadingIconIsStarted() { - val view = createView() - val viewHolder = ResolverListAdapter.ViewHolder(view) - view.tag = viewHolder - val targetInfo = createSelectableTargetInfo() - val iconTask = mock { - doNothing().whenever(this).loadIcon() - } - testSubject.setTestLoadDirectShareTaskProvider( - mock { - whenever(get()).thenReturn(iconTask) - } - ) - testSubject.testViewBind(view, targetInfo, 0) - - verify(iconTask, times(1)).loadIcon() - verify(iconTask, times(1)).setViewHolder(viewHolder) - } - - @Test - fun testOnlyOneTaskPerTarget() { - val view = createView() - val viewHolderOne = ResolverListAdapter.ViewHolder(view) - view.tag = viewHolderOne - val targetInfo = createSelectableTargetInfo() - val iconTaskOne = mock { - doNothing().whenever(this).loadIcon() - } - val testTaskProvider = mock { - whenever(get()).thenReturn(iconTaskOne) - } - testSubject.setTestLoadDirectShareTaskProvider( - testTaskProvider - ) - testSubject.testViewBind(view, targetInfo, 0) - - val viewHolderTwo = ResolverListAdapter.ViewHolder(view) - view.tag = viewHolderTwo - whenever(testTaskProvider.get()).thenReturn(mock()) - - testSubject.testViewBind(view, targetInfo, 0) - - verify(iconTaskOne, times(1)).loadIcon() - verify(iconTaskOne, times(1)).setViewHolder(viewHolderOne) - verify(iconTaskOne, times(1)).setViewHolder(viewHolderTwo) - verify(testTaskProvider, times(1)).get() - } - - private fun createSelectableTargetInfo(): SelectableTargetInfo = - SelectableTargetInfo( - context, - null, - createChooserTarget(), - 1f, - selectableTargetInfoCommunicator, - null - ) - - private fun createChooserTarget(): ChooserTarget = - ChooserTarget( - "Title", - null, - 1f, - ComponentName("package", "package.Class"), - Bundle() - ) - - private fun createView(): View { - val view = FrameLayout(context) - TextView(context).apply { - id = R.id.text1 - view.addView(this) - } - TextView(context).apply { - id = R.id.text2 - view.addView(this) - } - ImageView(context).apply { - id = R.id.icon - view.addView(this) - } - return view - } -} From 0b97c67133ee18c2bceabf642fd31e957081f25c Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 15 Sep 2022 04:37:19 +0000 Subject: [PATCH 28/45] Revert "[Bluetooth] Convert BluetoothController logs to log buffer" This reverts commit 2d0a8f3b061110bd50c45b2dd56de6971e25042f. Reason for revert: b/246876230 It looks like the log are not working because the device can be null. This mean the log never worked before too. Change-Id: Ia786886420db3dbcdb31e4f1a641088b2fedf897 (cherry picked from commit 297a766b23f5576b73c7d1b0581f5925dbbc1de6) Merged-In: Ia786886420db3dbcdb31e4f1a641088b2fedf897 --- .../bluetooth/BluetoothCallback.java | 44 +------- .../systemui/bluetooth/BluetoothLogger.kt | 102 ------------------ .../android/systemui/keyboard/KeyboardUI.java | 2 +- .../systemui/log/dagger/BluetoothLog.kt | 22 ---- .../log/dagger/KeyguardUpdateMonitorLog.kt | 5 - .../systemui/log/dagger/LogModule.java | 10 -- .../policy/BluetoothControllerImpl.java | 56 +++++----- .../policy/BluetoothControllerImplTest.java | 2 - 8 files changed, 34 insertions(+), 209 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt delete mode 100644 packages/SystemUI/src/com/android/systemui/log/dagger/BluetoothLog.kt diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java index cbdac6145a170..3152e65d5a366 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java @@ -16,20 +16,6 @@ package com.android.settingslib.bluetooth; -import static android.bluetooth.BluetoothAdapter.STATE_CONNECTED; -import static android.bluetooth.BluetoothAdapter.STATE_CONNECTING; -import static android.bluetooth.BluetoothAdapter.STATE_DISCONNECTED; -import static android.bluetooth.BluetoothAdapter.STATE_DISCONNECTING; -import static android.bluetooth.BluetoothAdapter.STATE_OFF; -import static android.bluetooth.BluetoothAdapter.STATE_ON; -import static android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF; -import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON; - -import android.annotation.IntDef; -import android.annotation.Nullable; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; /** * BluetoothCallback provides a callback interface for the settings @@ -47,7 +33,7 @@ public interface BluetoothCallback { * {@link android.bluetooth.BluetoothAdapter#STATE_ON}, * {@link android.bluetooth.BluetoothAdapter#STATE_TURNING_OFF}. */ - default void onBluetoothStateChanged(@AdapterState int bluetoothState) {} + default void onBluetoothStateChanged(int bluetoothState) {} /** * It will be called when the local Bluetooth adapter has started @@ -103,9 +89,7 @@ public interface BluetoothCallback { * {@link android.bluetooth.BluetoothAdapter#STATE_CONNECTED}, * {@link android.bluetooth.BluetoothAdapter#STATE_DISCONNECTING}. */ - default void onConnectionStateChanged( - @Nullable CachedBluetoothDevice cachedDevice, - @ConnectionState int state) {} + default void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {} /** * It will be called when device been set as active for {@code bluetoothProfile} @@ -140,10 +124,8 @@ public interface BluetoothCallback { * {@link android.bluetooth.BluetoothProfile#STATE_DISCONNECTING}. * @param bluetoothProfile the BluetoothProfile id. */ - default void onProfileConnectionStateChanged( - CachedBluetoothDevice cachedDevice, - @ConnectionState int state, - int bluetoothProfile) { + default void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, + int state, int bluetoothProfile) { } /** @@ -158,22 +140,4 @@ public interface BluetoothCallback { */ default void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { } - - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "STATE_" }, value = { - STATE_DISCONNECTED, - STATE_CONNECTING, - STATE_CONNECTED, - STATE_DISCONNECTING, - }) - @interface ConnectionState {} - - @IntDef(prefix = { "STATE_" }, value = { - STATE_OFF, - STATE_TURNING_ON, - STATE_ON, - STATE_TURNING_OFF, - }) - @Retention(RetentionPolicy.SOURCE) - @interface AdapterState {} } diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt deleted file mode 100644 index b5da7b6a34876..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.bluetooth - -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.log.LogBuffer -import com.android.systemui.log.LogLevel -import com.android.systemui.log.dagger.BluetoothLog -import javax.inject.Inject - -/** Helper class for logging bluetooth events. */ -@SysUISingleton -class BluetoothLogger @Inject constructor(@BluetoothLog private val logBuffer: LogBuffer) { - fun logActiveDeviceChanged(address: String, profileId: Int) = - logBuffer.log( - TAG, - LogLevel.DEBUG, - { - str1 = address - int1 = profileId - }, - { "ActiveDeviceChanged. address=$str1 profileId=$int1" } - ) - - fun logDeviceConnectionStateChanged(address: String?, state: String) = - logBuffer.log( - TAG, - LogLevel.DEBUG, - { - str1 = address - str2 = state - }, - { "DeviceConnectionStateChanged. address=$str1 state=$str2" } - ) - - fun logAclConnectionStateChanged(address: String, state: String) = - logBuffer.log( - TAG, - LogLevel.DEBUG, - { - str1 = address - str2 = state - }, - { "AclConnectionStateChanged. address=$str1 state=$str2" } - ) - - fun logProfileConnectionStateChanged(address: String, state: String, profileId: Int) = - logBuffer.log( - TAG, - LogLevel.DEBUG, - { - str1 = address - str2 = state - int1 = profileId - }, - { "ProfileConnectionStateChanged. address=$str1 state=$str2 profileId=$int1" } - ) - - fun logStateChange(state: String) = - logBuffer.log( - TAG, - LogLevel.DEBUG, - { str1 = state }, - { "BluetoothStateChanged. state=$str1" } - ) - - fun logBondStateChange(address: String, state: Int) = - logBuffer.log( - TAG, - LogLevel.DEBUG, - { - str1 = address - int1 = state - }, - { "DeviceBondStateChanged. address=$str1 state=$int1" } - ) - - fun logDeviceAdded(address: String) = - logBuffer.log(TAG, LogLevel.DEBUG, { str1 = address }, { "DeviceAdded. address=$str1" }) - - fun logDeviceDeleted(address: String) = - logBuffer.log(TAG, LogLevel.DEBUG, { str1 = address }, { "DeviceDeleted. address=$str1" }) - - fun logDeviceAttributesChanged() = - logBuffer.log(TAG, LogLevel.DEBUG, {}, { "DeviceAttributesChanged." }) -} - -private const val TAG = "BluetoothLog" diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java index 659f286b24c9b..a3dc77993d304 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java +++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java @@ -601,7 +601,7 @@ public class KeyboardUI extends CoreStartable implements InputManager.OnTabletMo private final class BluetoothCallbackHandler implements BluetoothCallback { @Override - public void onBluetoothStateChanged(@BluetoothCallback.AdapterState int bluetoothState) { + public void onBluetoothStateChanged(int bluetoothState) { mHandler.obtainMessage(MSG_ON_BLUETOOTH_STATE_CHANGED, bluetoothState, 0).sendToTarget(); } diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/BluetoothLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/BluetoothLog.kt deleted file mode 100644 index 4887b6a14658e..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/BluetoothLog.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.log.dagger - -import javax.inject.Qualifier - -/** A [com.android.systemui.log.LogBuffer] for bluetooth. */ -@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class BluetoothLog diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt index b551125fccc78..323ee21953ea1 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt @@ -1,9 +1,4 @@ package com.android.systemui.log.dagger -import javax.inject.Qualifier - /** A [com.android.systemui.log.LogBuffer] for KeyguardUpdateMonitor. */ -@Qualifier -@MustBeDocumented -@Retention(AnnotationRetention.RUNTIME) annotation class KeyguardUpdateMonitorLog diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index eeba6b3b60563..c2a87649adef5 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -305,14 +305,4 @@ public class LogModule { public static LogBuffer provideKeyguardUpdateMonitorLogBuffer(LogBufferFactory factory) { return factory.create("KeyguardUpdateMonitorLog", 200); } - - /** - * Provides a {@link LogBuffer} for bluetooth-related logs. - */ - @Provides - @SysUISingleton - @BluetoothLog - public static LogBuffer providerBluetoothLogBuffer(LogBufferFactory factory) { - return factory.create("BluetoothLog", 50); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java index c7ea3c62b7504..e7fa6d2390121 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java @@ -27,6 +27,7 @@ import android.os.Looper; import android.os.Message; import android.os.UserHandle; import android.os.UserManager; +import android.util.Log; import androidx.annotation.NonNull; @@ -36,7 +37,6 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; -import com.android.systemui.bluetooth.BluetoothLogger; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -57,9 +57,9 @@ import javax.inject.Inject; public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback, CachedBluetoothDevice.Callback, LocalBluetoothProfileManager.ServiceListener { private static final String TAG = "BluetoothController"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final DumpManager mDumpManager; - private final BluetoothLogger mLogger; private final LocalBluetoothManager mLocalBluetoothManager; private final UserManager mUserManager; private final int mCurrentUser; @@ -70,7 +70,6 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa private final List mConnectedDevices = new ArrayList<>(); private boolean mEnabled; - @ConnectionState private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED; private boolean mAudioProfileOnly; private boolean mIsActive; @@ -84,12 +83,10 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa public BluetoothControllerImpl( Context context, DumpManager dumpManager, - BluetoothLogger logger, @Background Looper bgLooper, @Main Looper mainLooper, @Nullable LocalBluetoothManager localBluetoothManager) { mDumpManager = dumpManager; - mLogger = logger; mLocalBluetoothManager = localBluetoothManager; mBgHandler = new Handler(bgLooper); mHandler = new H(mainLooper); @@ -119,7 +116,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa return; } pw.print(" mEnabled="); pw.println(mEnabled); - pw.print(" mConnectionState="); pw.println(connectionStateToString(mConnectionState)); + pw.print(" mConnectionState="); pw.println(stateToString(mConnectionState)); pw.print(" mAudioProfileOnly="); pw.println(mAudioProfileOnly); pw.print(" mIsActive="); pw.println(mIsActive); pw.print(" mConnectedDevices="); pw.println(getConnectedDevices()); @@ -130,7 +127,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa } } - private static String connectionStateToString(@ConnectionState int state) { + private static String stateToString(int state) { switch (state) { case BluetoothAdapter.STATE_CONNECTED: return "CONNECTED"; @@ -323,8 +320,8 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa } @Override - public void onBluetoothStateChanged(@AdapterState int bluetoothState) { - mLogger.logStateChange(BluetoothAdapter.nameForState(bluetoothState)); + public void onBluetoothStateChanged(int bluetoothState) { + if (DEBUG) Log.d(TAG, "BluetoothStateChanged=" + stateToString(bluetoothState)); mEnabled = bluetoothState == BluetoothAdapter.STATE_ON || bluetoothState == BluetoothAdapter.STATE_TURNING_ON; mState = bluetoothState; @@ -334,7 +331,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { - mLogger.logDeviceAdded(cachedDevice.getAddress()); + if (DEBUG) Log.d(TAG, "DeviceAdded=" + cachedDevice.getAddress()); cachedDevice.registerCallback(this); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); @@ -342,7 +339,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { - mLogger.logDeviceDeleted(cachedDevice.getAddress()); + if (DEBUG) Log.d(TAG, "DeviceDeleted=" + cachedDevice.getAddress()); mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); @@ -350,7 +347,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { - mLogger.logBondStateChange(cachedDevice.getAddress(), bondState); + if (DEBUG) Log.d(TAG, "DeviceBondStateChanged=" + cachedDevice.getAddress()); mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); @@ -358,29 +355,29 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onDeviceAttributesChanged() { - mLogger.logDeviceAttributesChanged(); + if (DEBUG) Log.d(TAG, "DeviceAttributesChanged"); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); } @Override - public void onConnectionStateChanged( - @Nullable CachedBluetoothDevice cachedDevice, - @ConnectionState int state) { - String address = cachedDevice == null ? null : cachedDevice.getAddress(); - mLogger.logDeviceConnectionStateChanged(address, connectionStateToString(state)); + public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { + if (DEBUG) { + Log.d(TAG, "ConnectionStateChanged=" + cachedDevice.getAddress() + " " + + stateToString(state)); + } mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); } @Override - public void onProfileConnectionStateChanged( - CachedBluetoothDevice cachedDevice, - @ConnectionState int state, - int bluetoothProfile) { - mLogger.logProfileConnectionStateChanged( - cachedDevice.getAddress(), connectionStateToString(state), bluetoothProfile); + public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, + int state, int bluetoothProfile) { + if (DEBUG) { + Log.d(TAG, "ProfileConnectionStateChanged=" + cachedDevice.getAddress() + " " + + stateToString(state) + " profileId=" + bluetoothProfile); + } mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); @@ -388,15 +385,20 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { - mLogger.logActiveDeviceChanged(activeDevice.getAddress(), bluetoothProfile); + if (DEBUG) { + Log.d(TAG, "ActiveDeviceChanged=" + activeDevice.getAddress() + + " profileId=" + bluetoothProfile); + } updateActive(); mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); } @Override public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { - mLogger.logAclConnectionStateChanged( - cachedDevice.getAddress(), connectionStateToString(state)); + if (DEBUG) { + Log.d(TAG, "ACLConnectionStateChanged=" + cachedDevice.getAddress() + " " + + stateToString(state)); + } mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java index cf5e8781a5512..3dd36d134cf71 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java @@ -41,7 +41,6 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.systemui.SysuiTestCase; -import com.android.systemui.bluetooth.BluetoothLogger; import com.android.systemui.dump.DumpManager; import org.junit.Before; @@ -82,7 +81,6 @@ public class BluetoothControllerImplTest extends SysuiTestCase { mBluetoothControllerImpl = new BluetoothControllerImpl(mContext, mMockDumpManager, - mock(BluetoothLogger.class), mTestableLooper.getLooper(), mTestableLooper.getLooper(), mMockBluetoothManager); From d9915d9f40354934ab6a5e3af211d96ba14f3607 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 15 Sep 2022 20:48:09 +0000 Subject: [PATCH 29/45] Revert "Removing unused surface transaction wrappers" Revert submission 19933596-tcompat Reason for revert: b/246899728 Reverted Changes: I31123dff7:Using Transaction directly instead of building sur... I2e2526d21:Removing unused surface transaction wrappers Change-Id: I44944ccd94def3b5925f1008f0b8d47387594f2b (cherry picked from commit 2460910c8c454bc2d3c9ae35bd32eeb590851788) Merged-In: I44944ccd94def3b5925f1008f0b8d47387594f2b --- ...SyncRtSurfaceTransactionApplierCompat.java | 380 ++++++++++++++++++ .../shared/system/TransactionCompat.java | 108 +++++ 2 files changed, 488 insertions(+) create mode 100644 packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java create mode 100644 packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java new file mode 100644 index 0000000000000..30c062b66da94 --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2018 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.shared.system; + +import android.graphics.HardwareRenderer; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.os.Handler; +import android.os.Handler.Callback; +import android.os.Message; +import android.os.Trace; +import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction; +import android.view.View; +import android.view.ViewRootImpl; + +import java.util.function.Consumer; + +/** + * Helper class to apply surface transactions in sync with RenderThread. + * + * NOTE: This is a modification of {@link android.view.SyncRtSurfaceTransactionApplier}, we can't + * currently reference that class from the shared lib as it is hidden. + */ +public class SyncRtSurfaceTransactionApplierCompat { + + public static final int FLAG_ALL = 0xffffffff; + public static final int FLAG_ALPHA = 1; + public static final int FLAG_MATRIX = 1 << 1; + public static final int FLAG_WINDOW_CROP = 1 << 2; + public static final int FLAG_LAYER = 1 << 3; + public static final int FLAG_CORNER_RADIUS = 1 << 4; + public static final int FLAG_BACKGROUND_BLUR_RADIUS = 1 << 5; + public static final int FLAG_VISIBILITY = 1 << 6; + public static final int FLAG_RELATIVE_LAYER = 1 << 7; + public static final int FLAG_SHADOW_RADIUS = 1 << 8; + + private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0; + + private final SurfaceControl mBarrierSurfaceControl; + private final ViewRootImpl mTargetViewRootImpl; + private final Handler mApplyHandler; + + private int mSequenceNumber = 0; + private int mPendingSequenceNumber = 0; + private Runnable mAfterApplyCallback; + + /** + * @param targetView The view in the surface that acts as synchronization anchor. + */ + public SyncRtSurfaceTransactionApplierCompat(View targetView) { + mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null; + mBarrierSurfaceControl = mTargetViewRootImpl != null + ? mTargetViewRootImpl.getSurfaceControl() : null; + + mApplyHandler = new Handler(new Callback() { + @Override + public boolean handleMessage(Message msg) { + if (msg.what == MSG_UPDATE_SEQUENCE_NUMBER) { + onApplyMessage(msg.arg1); + return true; + } + return false; + } + }); + } + + private void onApplyMessage(int seqNo) { + mSequenceNumber = seqNo; + if (mSequenceNumber == mPendingSequenceNumber && mAfterApplyCallback != null) { + Runnable r = mAfterApplyCallback; + mAfterApplyCallback = null; + r.run(); + } + } + + /** + * Schedules applying surface parameters on the next frame. + * + * @param params The surface parameters to apply. DO NOT MODIFY the list after passing into + * this method to avoid synchronization issues. + */ + public void scheduleApply(final SyncRtSurfaceTransactionApplierCompat.SurfaceParams... params) { + if (mTargetViewRootImpl == null || mTargetViewRootImpl.getView() == null) { + return; + } + + mPendingSequenceNumber++; + final int toApplySeqNo = mPendingSequenceNumber; + mTargetViewRootImpl.registerRtFrameCallback(new HardwareRenderer.FrameDrawingCallback() { + @Override + public void onFrameDraw(long frame) { + if (mBarrierSurfaceControl == null || !mBarrierSurfaceControl.isValid()) { + Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0) + .sendToTarget(); + return; + } + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Sync transaction frameNumber=" + frame); + Transaction t = new Transaction(); + for (int i = params.length - 1; i >= 0; i--) { + SyncRtSurfaceTransactionApplierCompat.SurfaceParams surfaceParams = + params[i]; + surfaceParams.applyTo(t); + } + if (mTargetViewRootImpl != null) { + mTargetViewRootImpl.mergeWithNextTransaction(t, frame); + } else { + t.apply(); + } + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0) + .sendToTarget(); + } + }); + + // Make sure a frame gets scheduled. + mTargetViewRootImpl.getView().invalidate(); + } + + /** + * Calls the runnable when any pending apply calls have completed + */ + public void addAfterApplyCallback(final Runnable afterApplyCallback) { + if (mSequenceNumber == mPendingSequenceNumber) { + afterApplyCallback.run(); + } else { + if (mAfterApplyCallback == null) { + mAfterApplyCallback = afterApplyCallback; + } else { + final Runnable oldCallback = mAfterApplyCallback; + mAfterApplyCallback = new Runnable() { + @Override + public void run() { + afterApplyCallback.run(); + oldCallback.run(); + } + }; + } + } + } + + public static void applyParams(TransactionCompat t, + SyncRtSurfaceTransactionApplierCompat.SurfaceParams params) { + params.applyTo(t.mTransaction); + } + + /** + * Creates an instance of SyncRtSurfaceTransactionApplier, deferring until the target view is + * attached if necessary. + */ + public static void create(final View targetView, + final Consumer callback) { + if (targetView == null) { + // No target view, no applier + callback.accept(null); + } else if (targetView.getViewRootImpl() != null) { + // Already attached, we're good to go + callback.accept(new SyncRtSurfaceTransactionApplierCompat(targetView)); + } else { + // Haven't been attached before we can get the view root + targetView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + targetView.removeOnAttachStateChangeListener(this); + callback.accept(new SyncRtSurfaceTransactionApplierCompat(targetView)); + } + + @Override + public void onViewDetachedFromWindow(View v) { + // Do nothing + } + }); + } + } + + public static class SurfaceParams { + public static class Builder { + final SurfaceControl surface; + int flags; + float alpha; + float cornerRadius; + int backgroundBlurRadius; + Matrix matrix; + Rect windowCrop; + int layer; + SurfaceControl relativeTo; + int relativeLayer; + boolean visible; + float shadowRadius; + + /** + * @param surface The surface to modify. + */ + public Builder(SurfaceControl surface) { + this.surface = surface; + } + + /** + * @param alpha The alpha value to apply to the surface. + * @return this Builder + */ + public Builder withAlpha(float alpha) { + this.alpha = alpha; + flags |= FLAG_ALPHA; + return this; + } + + /** + * @param matrix The matrix to apply to the surface. + * @return this Builder + */ + public Builder withMatrix(Matrix matrix) { + this.matrix = new Matrix(matrix); + flags |= FLAG_MATRIX; + return this; + } + + /** + * @param windowCrop The window crop to apply to the surface. + * @return this Builder + */ + public Builder withWindowCrop(Rect windowCrop) { + this.windowCrop = new Rect(windowCrop); + flags |= FLAG_WINDOW_CROP; + return this; + } + + /** + * @param layer The layer to assign the surface. + * @return this Builder + */ + public Builder withLayer(int layer) { + this.layer = layer; + flags |= FLAG_LAYER; + return this; + } + + /** + * @param relativeTo The surface that's set relative layer to. + * @param relativeLayer The relative layer. + * @return this Builder + */ + public Builder withRelativeLayerTo(SurfaceControl relativeTo, int relativeLayer) { + this.relativeTo = relativeTo; + this.relativeLayer = relativeLayer; + flags |= FLAG_RELATIVE_LAYER; + return this; + } + + /** + * @param radius the Radius for rounded corners to apply to the surface. + * @return this Builder + */ + public Builder withCornerRadius(float radius) { + this.cornerRadius = radius; + flags |= FLAG_CORNER_RADIUS; + return this; + } + + /** + * @param radius the Radius for the shadows to apply to the surface. + * @return this Builder + */ + public Builder withShadowRadius(float radius) { + this.shadowRadius = radius; + flags |= FLAG_SHADOW_RADIUS; + return this; + } + + /** + * @param radius the Radius for blur to apply to the background surfaces. + * @return this Builder + */ + public Builder withBackgroundBlur(int radius) { + this.backgroundBlurRadius = radius; + flags |= FLAG_BACKGROUND_BLUR_RADIUS; + return this; + } + + /** + * @param visible The visibility to apply to the surface. + * @return this Builder + */ + public Builder withVisibility(boolean visible) { + this.visible = visible; + flags |= FLAG_VISIBILITY; + return this; + } + + /** + * @return a new SurfaceParams instance + */ + public SurfaceParams build() { + return new SurfaceParams(surface, flags, alpha, matrix, windowCrop, layer, + relativeTo, relativeLayer, cornerRadius, backgroundBlurRadius, visible, + shadowRadius); + } + } + + private SurfaceParams(SurfaceControl surface, int flags, float alpha, Matrix matrix, + Rect windowCrop, int layer, SurfaceControl relativeTo, int relativeLayer, + float cornerRadius, int backgroundBlurRadius, boolean visible, float shadowRadius) { + this.flags = flags; + this.surface = surface; + this.alpha = alpha; + this.matrix = matrix; + this.windowCrop = windowCrop; + this.layer = layer; + this.relativeTo = relativeTo; + this.relativeLayer = relativeLayer; + this.cornerRadius = cornerRadius; + this.backgroundBlurRadius = backgroundBlurRadius; + this.visible = visible; + this.shadowRadius = shadowRadius; + } + + private final int flags; + private final float[] mTmpValues = new float[9]; + + public final SurfaceControl surface; + public final float alpha; + public final float cornerRadius; + public final int backgroundBlurRadius; + public final Matrix matrix; + public final Rect windowCrop; + public final int layer; + public final SurfaceControl relativeTo; + public final int relativeLayer; + public final boolean visible; + public final float shadowRadius; + + public void applyTo(SurfaceControl.Transaction t) { + if ((flags & FLAG_MATRIX) != 0) { + t.setMatrix(surface, matrix, mTmpValues); + } + if ((flags & FLAG_WINDOW_CROP) != 0) { + t.setWindowCrop(surface, windowCrop); + } + if ((flags & FLAG_ALPHA) != 0) { + t.setAlpha(surface, alpha); + } + if ((flags & FLAG_LAYER) != 0) { + t.setLayer(surface, layer); + } + if ((flags & FLAG_CORNER_RADIUS) != 0) { + t.setCornerRadius(surface, cornerRadius); + } + if ((flags & FLAG_BACKGROUND_BLUR_RADIUS) != 0) { + t.setBackgroundBlurRadius(surface, backgroundBlurRadius); + } + if ((flags & FLAG_VISIBILITY) != 0) { + if (visible) { + t.show(surface); + } else { + t.hide(surface); + } + } + if ((flags & FLAG_RELATIVE_LAYER) != 0) { + t.setRelativeLayer(surface, relativeTo, relativeLayer); + } + if ((flags & FLAG_SHADOW_RADIUS) != 0) { + t.setShadowRadius(surface, shadowRadius); + } + } + } +} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java new file mode 100644 index 0000000000000..43a882a5f6be7 --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2018 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.shared.system; + +import android.graphics.Matrix; +import android.graphics.Rect; +import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction; + +public class TransactionCompat { + + final Transaction mTransaction; + + final float[] mTmpValues = new float[9]; + + public TransactionCompat() { + mTransaction = new Transaction(); + } + + public void apply() { + mTransaction.apply(); + } + + public TransactionCompat show(SurfaceControl surfaceControl) { + mTransaction.show(surfaceControl); + return this; + } + + public TransactionCompat hide(SurfaceControl surfaceControl) { + mTransaction.hide(surfaceControl); + return this; + } + + public TransactionCompat setPosition(SurfaceControl surfaceControl, float x, float y) { + mTransaction.setPosition(surfaceControl, x, y); + return this; + } + + public TransactionCompat setSize(SurfaceControl surfaceControl, int w, int h) { + mTransaction.setBufferSize(surfaceControl, w, h); + return this; + } + + public TransactionCompat setLayer(SurfaceControl surfaceControl, int z) { + mTransaction.setLayer(surfaceControl, z); + return this; + } + + public TransactionCompat setAlpha(SurfaceControl surfaceControl, float alpha) { + mTransaction.setAlpha(surfaceControl, alpha); + return this; + } + + public TransactionCompat setOpaque(SurfaceControl surfaceControl, boolean opaque) { + mTransaction.setOpaque(surfaceControl, opaque); + return this; + } + + public TransactionCompat setMatrix(SurfaceControl surfaceControl, float dsdx, float dtdx, + float dtdy, float dsdy) { + mTransaction.setMatrix(surfaceControl, dsdx, dtdx, dtdy, dsdy); + return this; + } + + public TransactionCompat setMatrix(SurfaceControl surfaceControl, Matrix matrix) { + mTransaction.setMatrix(surfaceControl, matrix, mTmpValues); + return this; + } + + public TransactionCompat setWindowCrop(SurfaceControl surfaceControl, Rect crop) { + mTransaction.setWindowCrop(surfaceControl, crop); + return this; + } + + public TransactionCompat setCornerRadius(SurfaceControl surfaceControl, float radius) { + mTransaction.setCornerRadius(surfaceControl, radius); + return this; + } + + public TransactionCompat setBackgroundBlurRadius(SurfaceControl surfaceControl, int radius) { + mTransaction.setBackgroundBlurRadius(surfaceControl, radius); + return this; + } + + public TransactionCompat setColor(SurfaceControl surfaceControl, float[] color) { + mTransaction.setColor(surfaceControl, color); + return this; + } + + public static void setRelativeLayer(Transaction t, SurfaceControl surfaceControl, + SurfaceControl relativeTo, int z) { + t.setRelativeLayer(surfaceControl, relativeTo, z); + } +} From 68f0e3c1b96b3fde4ef2872cda2c603fb64e4511 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Fri, 30 Sep 2022 10:47:47 -0700 Subject: [PATCH 30/45] [Bouncer] ensure bouncer not shown with doze state. When doze state is no longer dozing, we were not resetting the bouncer view. Here, when dozing state changes, we want to ensure that the bouncer is not shown. Fixes: 237822716 Test: Added a unit test and test manually. Change-Id: If085851b5e3c8b15cdd4b0a2fce8cbb5e8f48035 (cherry picked from commit f348307f7ba56ac38d746cde837638dd623156c6) Merged-In: If085851b5e3c8b15cdd4b0a2fce8cbb5e8f48035 --- .../phone/StatusBarKeyguardViewManager.java | 5 ++++ .../StatusBarKeyguardViewManagerTest.java | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 9d5392af3127c..a0578fac2033e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -733,6 +733,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (dozing || mBouncer.needsFullscreenBouncer() || mOccluded) { reset(dozing /* hideBouncerWhenShowing */); } + + if (bouncerIsOrWillBeShowing()) { + // Ensure bouncer is not shown when dozing state changes. + hideBouncer(false); + } updateStates(); if (!dozing) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index dcce61b86ced3..f52bfcaaaa448 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -23,9 +23,11 @@ import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -525,4 +527,26 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { mBouncerExpansionCallback.onVisibilityChanged(false); verify(mCentralSurfaces).setBouncerShowingOverDream(false); } + + + @Test + public void testSetDozing_bouncerShowing_Dozing() { + clearInvocations(mBouncer); + when(mBouncer.isShowing()).thenReturn(true); + doAnswer(invocation -> { + when(mBouncer.isShowing()).thenReturn(false); + return null; + }).when(mBouncer).hide(false); + mStatusBarKeyguardViewManager.onDozingChanged(true); + verify(mBouncer, times(1)).hide(false); + } + + @Test + public void testSetDozing_bouncerShowing_notDozing() { + mStatusBarKeyguardViewManager.onDozingChanged(true); + when(mBouncer.isShowing()).thenReturn(true); + clearInvocations(mBouncer); + mStatusBarKeyguardViewManager.onDozingChanged(false); + verify(mBouncer, times(1)).hide(false); + } } From 4c5b296cb12ba7cd60b7a78a21be2934b94b8b86 Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Tue, 9 Aug 2022 16:39:07 -0700 Subject: [PATCH 31/45] Logging second order reasons for process starts Currently the reason is described as the hosting type and name of the lifecycle component that is being started. Adding a field to describe the trigger that led to the component being invoked. Starting with logging when an alarm caused a broadcast to start in the app. Other examples of triggers that can be added are jobs for services, push-messages for broadcasts, etc. Test: make statsd_testdrive statsd_testdrive 169 Bug: 242928495 Change-Id: Iffa03bd99f9ef6907444b3e3204d2a2f13e28102 Merged-In: Iffa03bd99f9ef6907444b3e3204d2a2f13e28102 (cherry picked from commit 64d4919530e55f508e3a146fc7eaa13a2fa8e4f5) Merged-In: Iffa03bd99f9ef6907444b3e3204d2a2f13e28102 --- .../server/am/ActivityManagerService.java | 3 +- .../com/android/server/am/BroadcastQueue.java | 3 +- .../com/android/server/am/HostingRecord.java | 50 +++++++++++++++---- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d4b760f3866f7..df5113b16f497 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5008,7 +5008,8 @@ public class ActivityManagerService extends IActivityManager.Stub hostingRecord.getType(), hostingRecord.getName(), shortAction, - HostingRecord.getHostingTypeIdStatsd(hostingRecord.getType())); + HostingRecord.getHostingTypeIdStatsd(hostingRecord.getType()), + HostingRecord.getTriggerTypeForStatsd(hostingRecord.getTriggerType())); return true; } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 58569495f70d9..72a64d75c2702 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -1921,7 +1921,8 @@ public final class BroadcastQueue { info.activityInfo.applicationInfo, true, r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, new HostingRecord(HostingRecord.HOSTING_TYPE_BROADCAST, r.curComponent, - r.intent.getAction()), + r.intent.getAction(), (r.alarm ? HostingRecord.TRIGGER_TYPE_ALARM + : HostingRecord.TRIGGER_TYPE_UNKNOWN)), isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY, (r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false); if (r.curApp == null) { diff --git a/services/core/java/com/android/server/am/HostingRecord.java b/services/core/java/com/android/server/am/HostingRecord.java index f88a8ce83d022..bad13eaeeee64 100644 --- a/services/core/java/com/android/server/am/HostingRecord.java +++ b/services/core/java/com/android/server/am/HostingRecord.java @@ -21,6 +21,8 @@ import android.annotation.Nullable; import android.content.ComponentName; import android.os.ProcessStartTime; +import com.android.internal.util.FrameworkStatsLog; + /** * This class describes various information required to start a process. * @@ -32,6 +34,9 @@ import android.os.ProcessStartTime; * * The {@code mHostingZygote} field describes from which Zygote the new process should be spawned. * + * The {@code mTriggerType} field describes the trigger that started this processs. This could be + * an alarm or a push-message for a broadcast, for example. This is purely for logging and stats. + * * {@code mDefiningPackageName} contains the packageName of the package that defines the * component we want to start; this can be different from the packageName and uid in the * ApplicationInfo that we're creating the process with, in case the service is a @@ -71,7 +76,10 @@ public final class HostingRecord { public static final String HOSTING_TYPE_TOP_ACTIVITY = "top-activity"; public static final String HOSTING_TYPE_EMPTY = ""; - private @NonNull final String mHostingType; + public static final String TRIGGER_TYPE_UNKNOWN = "unknown"; + public static final String TRIGGER_TYPE_ALARM = "alarm"; + + @NonNull private final String mHostingType; private final String mHostingName; private final int mHostingZygote; private final String mDefiningPackageName; @@ -79,11 +87,12 @@ public final class HostingRecord { private final boolean mIsTopApp; private final String mDefiningProcessName; @Nullable private final String mAction; + @NonNull private final String mTriggerType; public HostingRecord(@NonNull String hostingType) { this(hostingType, null /* hostingName */, REGULAR_ZYGOTE, null /* definingPackageName */, -1 /* mDefiningUid */, false /* isTopApp */, null /* definingProcessName */, - null /* action */); + null /* action */, TRIGGER_TYPE_UNKNOWN); } public HostingRecord(@NonNull String hostingType, ComponentName hostingName) { @@ -91,22 +100,23 @@ public final class HostingRecord { } public HostingRecord(@NonNull String hostingType, ComponentName hostingName, - @Nullable String action) { + @Nullable String action, @Nullable String triggerType) { this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE, null /* definingPackageName */, -1 /* mDefiningUid */, false /* isTopApp */, - null /* definingProcessName */, action); + null /* definingProcessName */, action, triggerType); } public HostingRecord(@NonNull String hostingType, ComponentName hostingName, String definingPackageName, int definingUid, String definingProcessName) { this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE, definingPackageName, - definingUid, false /* isTopApp */, definingProcessName, null /* action */); + definingUid, false /* isTopApp */, definingProcessName, null /* action */, + TRIGGER_TYPE_UNKNOWN); } public HostingRecord(@NonNull String hostingType, ComponentName hostingName, boolean isTopApp) { this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE, null /* definingPackageName */, -1 /* mDefiningUid */, isTopApp /* isTopApp */, - null /* definingProcessName */, null /* action */); + null /* definingProcessName */, null /* action */, TRIGGER_TYPE_UNKNOWN); } public HostingRecord(@NonNull String hostingType, String hostingName) { @@ -121,12 +131,12 @@ public final class HostingRecord { private HostingRecord(@NonNull String hostingType, String hostingName, int hostingZygote) { this(hostingType, hostingName, hostingZygote, null /* definingPackageName */, -1 /* mDefiningUid */, false /* isTopApp */, null /* definingProcessName */, - null /* action */); + null /* action */, TRIGGER_TYPE_UNKNOWN); } private HostingRecord(@NonNull String hostingType, String hostingName, int hostingZygote, String definingPackageName, int definingUid, boolean isTopApp, - String definingProcessName, @Nullable String action) { + String definingProcessName, @Nullable String action, String triggerType) { mHostingType = hostingType; mHostingName = hostingName; mHostingZygote = hostingZygote; @@ -135,6 +145,7 @@ public final class HostingRecord { mIsTopApp = isTopApp; mDefiningProcessName = definingProcessName; mAction = action; + mTriggerType = triggerType; } public @NonNull String getType() { @@ -188,6 +199,11 @@ public final class HostingRecord { return mAction; } + /** Returns the type of trigger that led to this process start. */ + public @NonNull String getTriggerType() { + return mTriggerType; + } + /** * Creates a HostingRecord for a process that must spawn from the webview zygote * @param hostingName name of the component to be hosted in this process @@ -197,7 +213,7 @@ public final class HostingRecord { String definingPackageName, int definingUid, String definingProcessName) { return new HostingRecord(HostingRecord.HOSTING_TYPE_EMPTY, hostingName.toShortString(), WEBVIEW_ZYGOTE, definingPackageName, definingUid, false /* isTopApp */, - definingProcessName, null /* action */); + definingProcessName, null /* action */, TRIGGER_TYPE_UNKNOWN); } /** @@ -211,7 +227,7 @@ public final class HostingRecord { int definingUid, String definingProcessName) { return new HostingRecord(HostingRecord.HOSTING_TYPE_EMPTY, hostingName.toShortString(), APP_ZYGOTE, definingPackageName, definingUid, false /* isTopApp */, - definingProcessName, null /* action */); + definingProcessName, null /* action */, TRIGGER_TYPE_UNKNOWN); } /** @@ -267,4 +283,18 @@ public final class HostingRecord { return ProcessStartTime.HOSTING_TYPE_UNKNOWN; } } + + /** + * Map the string triggerType to enum TriggerType defined in ProcessStartTime proto. + * @param triggerType + * @return enum TriggerType defined in ProcessStartTime proto + */ + public static int getTriggerTypeForStatsd(@NonNull String triggerType) { + switch(triggerType) { + case TRIGGER_TYPE_ALARM: + return FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM; + default: + return FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN; + } + } } From e8cdbaebf71724a2a04997bf5a015cdd7fe51d64 Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Tue, 9 Aug 2022 18:24:00 -0700 Subject: [PATCH 32/45] Cleaning up duplicate proto for ProcessStartTime There is no need to maintain two copies of the same proto message. Moving framework to directly use the canonical proto used by statsd. Test: m -j statsd_testdrive out/host/linux-x86/bin/statsd_testdrive 169 Bug: 242928495 Change-Id: Ie2bdd2151dae26a611c3905342bb49ddddf2788d Merged-In: Ie2bdd2151dae26a611c3905342bb49ddddf2788d (cherry picked from commit e6073bc3ce37f0a29018ee0e02a0376f4c37da62) (cherry picked from commit 83327c47f549db792e43f12385847f2b9b0006e5) Merged-In: Ie2bdd2151dae26a611c3905342bb49ddddf2788d --- core/proto/android/os/processstarttime.proto | 92 ------------------- .../com/android/server/am/HostingRecord.java | 55 +++++++---- 2 files changed, 35 insertions(+), 112 deletions(-) delete mode 100644 core/proto/android/os/processstarttime.proto diff --git a/core/proto/android/os/processstarttime.proto b/core/proto/android/os/processstarttime.proto deleted file mode 100644 index d0f8baee7da22..0000000000000 --- a/core/proto/android/os/processstarttime.proto +++ /dev/null @@ -1,92 +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. - */ - -syntax = "proto2"; -package android.os; - -option java_multiple_files = true; - -// This message is used for statsd logging and should be kept in sync with -// frameworks/proto_logging/stats/atoms.proto -/** - * Logs information about process start time. - * - * Logged from: - * frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java - */ -message ProcessStartTime { - // The uid of the ProcessRecord. - optional int32 uid = 1; - - // The process pid. - optional int32 pid = 2; - - // The process name. - // Usually package name, "system" for system server. - // Provided by ActivityManagerService. - optional string process_name = 3; - - enum StartType { - UNKNOWN = 0; - WARM = 1; - HOT = 2; - COLD = 3; - } - - // The start type. - optional StartType type = 4; - - // The elapsed realtime at the start of the process. - optional int64 process_start_time_millis = 5; - - // Number of milliseconds it takes to reach bind application. - optional int32 bind_application_delay_millis = 6; - - // Number of milliseconds it takes to finish start of the process. - optional int32 process_start_delay_millis = 7; - - // hostingType field in ProcessRecord, the component type such as "activity", - // "service", "content provider", "broadcast" or other strings. - optional string hosting_type = 8; - - // hostingNameStr field in ProcessRecord. The component class name that runs - // in this process. - optional string hosting_name = 9; - - // Broadcast action name. - optional string broadcast_action_name = 10; - - enum HostingTypeId { - HOSTING_TYPE_UNKNOWN = 0; - HOSTING_TYPE_ACTIVITY = 1; - HOSTING_TYPE_ADDED_APPLICATION = 2; - HOSTING_TYPE_BACKUP = 3; - HOSTING_TYPE_BROADCAST = 4; - HOSTING_TYPE_CONTENT_PROVIDER = 5; - HOSTING_TYPE_LINK_FAIL = 6; - HOSTING_TYPE_ON_HOLD = 7; - HOSTING_TYPE_NEXT_ACTIVITY = 8; - HOSTING_TYPE_NEXT_TOP_ACTIVITY = 9; - HOSTING_TYPE_RESTART = 10; - HOSTING_TYPE_SERVICE = 11; - HOSTING_TYPE_SYSTEM = 12; - HOSTING_TYPE_TOP_ACTIVITY = 13; - HOSTING_TYPE_EMPTY = 14; - } - - optional HostingTypeId hosting_type_id = 11; -} - diff --git a/services/core/java/com/android/server/am/HostingRecord.java b/services/core/java/com/android/server/am/HostingRecord.java index bad13eaeeee64..efc2a2719dad1 100644 --- a/services/core/java/com/android/server/am/HostingRecord.java +++ b/services/core/java/com/android/server/am/HostingRecord.java @@ -16,12 +16,27 @@ package com.android.server.am; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ACTIVITY; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ADDED_APPLICATION; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BACKUP; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BROADCAST; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_CONTENT_PROVIDER; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_EMPTY; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_LINK_FAIL; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_ACTIVITY; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_TOP_ACTIVITY; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ON_HOLD; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_RESTART; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SERVICE; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SYSTEM; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_TOP_ACTIVITY; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TYPE__UNKNOWN; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; -import android.os.ProcessStartTime; - -import com.android.internal.util.FrameworkStatsLog; /** * This class describes various information required to start a process. @@ -252,35 +267,35 @@ public final class HostingRecord { public static int getHostingTypeIdStatsd(@NonNull String hostingType) { switch(hostingType) { case HOSTING_TYPE_ACTIVITY: - return ProcessStartTime.HOSTING_TYPE_ACTIVITY; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ACTIVITY; case HOSTING_TYPE_ADDED_APPLICATION: - return ProcessStartTime.HOSTING_TYPE_ADDED_APPLICATION; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ADDED_APPLICATION; case HOSTING_TYPE_BACKUP: - return ProcessStartTime.HOSTING_TYPE_BACKUP; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BACKUP; case HOSTING_TYPE_BROADCAST: - return ProcessStartTime.HOSTING_TYPE_BROADCAST; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BROADCAST; case HOSTING_TYPE_CONTENT_PROVIDER: - return ProcessStartTime.HOSTING_TYPE_CONTENT_PROVIDER; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_CONTENT_PROVIDER; case HOSTING_TYPE_LINK_FAIL: - return ProcessStartTime.HOSTING_TYPE_LINK_FAIL; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_LINK_FAIL; case HOSTING_TYPE_ON_HOLD: - return ProcessStartTime.HOSTING_TYPE_ON_HOLD; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ON_HOLD; case HOSTING_TYPE_NEXT_ACTIVITY: - return ProcessStartTime.HOSTING_TYPE_NEXT_ACTIVITY; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_ACTIVITY; case HOSTING_TYPE_NEXT_TOP_ACTIVITY: - return ProcessStartTime.HOSTING_TYPE_NEXT_TOP_ACTIVITY; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_TOP_ACTIVITY; case HOSTING_TYPE_RESTART: - return ProcessStartTime.HOSTING_TYPE_RESTART; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_RESTART; case HOSTING_TYPE_SERVICE: - return ProcessStartTime.HOSTING_TYPE_SERVICE; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SERVICE; case HOSTING_TYPE_SYSTEM: - return ProcessStartTime.HOSTING_TYPE_SYSTEM; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SYSTEM; case HOSTING_TYPE_TOP_ACTIVITY: - return ProcessStartTime.HOSTING_TYPE_TOP_ACTIVITY; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_TOP_ACTIVITY; case HOSTING_TYPE_EMPTY: - return ProcessStartTime.HOSTING_TYPE_EMPTY; + return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_EMPTY; default: - return ProcessStartTime.HOSTING_TYPE_UNKNOWN; + return PROCESS_START_TIME__TYPE__UNKNOWN; } } @@ -292,9 +307,9 @@ public final class HostingRecord { public static int getTriggerTypeForStatsd(@NonNull String triggerType) { switch(triggerType) { case TRIGGER_TYPE_ALARM: - return FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM; + return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM; default: - return FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN; + return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN; } } } From 4dcd07135d124fcde16a1df3d2f99de2c8e13bb9 Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Wed, 17 Aug 2022 17:37:14 -0700 Subject: [PATCH 33/45] Add push messaging as a trigger for proc start Adding identification for process starts when the trigger was a push_message. When the push_message was over quota it may be deferred, but counting it separately is still useful, as it could still cause cold process starts. Test: Manual: Run `./out/host/linux-x86/bin/statsd_testdrive 169` Then use a sample app to send it an FCM message when it is not running. Bug: 242928495 Change-Id: I55c56601af4eb60173ae039d8de7f9e7916c81e8 Merged-In: I55c56601af4eb60173ae039d8de7f9e7916c81e8 (cherry picked from commit 84c7a05dbbe94c5727a2e861399ece8393a542a2) (cherry picked from commit 8fcf1d63c6ebe3e05fcfa28c227888e6fa627ca9) Merged-In: I55c56601af4eb60173ae039d8de7f9e7916c81e8 --- core/java/android/app/BroadcastOptions.java | 22 +++++++++++++++++++ .../com/android/server/am/BroadcastQueue.java | 13 +++++++++-- .../android/server/am/BroadcastRecord.java | 6 +++++ .../com/android/server/am/HostingRecord.java | 8 +++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java index f0e14483d98a7..aa5fa5b19117a 100644 --- a/core/java/android/app/BroadcastOptions.java +++ b/core/java/android/app/BroadcastOptions.java @@ -528,6 +528,28 @@ public class BroadcastOptions extends ComponentOptions { return mIsAlarmBroadcast; } + /** + * Did this broadcast originate from a push message from the server? + * + * @return true if this broadcast is a push message, false otherwise. + * @hide + */ + public boolean isPushMessagingBroadcast() { + return mTemporaryAppAllowlistReasonCode == PowerExemptionManager.REASON_PUSH_MESSAGING; + } + + /** + * Did this broadcast originate from a push message from the server which was over the allowed + * quota? + * + * @return true if this broadcast is a push message over quota, false otherwise. + * @hide + */ + public boolean isPushMessagingOverQuotaBroadcast() { + return mTemporaryAppAllowlistReasonCode + == PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA; + } + /** {@hide} */ public long getRequireCompatChangeId() { return mRequireCompatChangeId; diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 72a64d75c2702..f366cec96f9de 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -1921,8 +1921,7 @@ public final class BroadcastQueue { info.activityInfo.applicationInfo, true, r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, new HostingRecord(HostingRecord.HOSTING_TYPE_BROADCAST, r.curComponent, - r.intent.getAction(), (r.alarm ? HostingRecord.TRIGGER_TYPE_ALARM - : HostingRecord.TRIGGER_TYPE_UNKNOWN)), + r.intent.getAction(), getHostingRecordTriggerType(r)), isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY, (r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false); if (r.curApp == null) { @@ -1945,6 +1944,16 @@ public final class BroadcastQueue { mPendingBroadcastRecvIndex = recIdx; } + private String getHostingRecordTriggerType(BroadcastRecord r) { + if (r.alarm) { + return HostingRecord.TRIGGER_TYPE_ALARM; + } else if (r.pushMessage) { + return HostingRecord.TRIGGER_TYPE_PUSH_MESSAGE; + } else if (r.pushMessageOverQuota) { + return HostingRecord.TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA; + } + return HostingRecord.TRIGGER_TYPE_UNKNOWN; + } @Nullable private String getTargetPackage(BroadcastRecord r) { diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index ce4528bca8871..baaae1d7a5559 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -71,6 +71,8 @@ final class BroadcastRecord extends Binder { final boolean ordered; // serialize the send to receivers? final boolean sticky; // originated from existing sticky data? final boolean alarm; // originated from an alarm triggering? + final boolean pushMessage; // originated from a push message? + final boolean pushMessageOverQuota; // originated from a push message which was over quota? final boolean initialSticky; // initial broadcast from register to sticky? final int userId; // user id this broadcast was for final String resolvedType; // the resolved data type @@ -309,6 +311,8 @@ final class BroadcastRecord extends Binder { mBackgroundActivityStartsToken = backgroundActivityStartsToken; this.timeoutExempt = timeoutExempt; alarm = options != null && options.isAlarmBroadcast(); + pushMessage = options != null && options.isPushMessagingBroadcast(); + pushMessageOverQuota = options != null && options.isPushMessagingOverQuotaBroadcast(); } /** @@ -362,6 +366,8 @@ final class BroadcastRecord extends Binder { mBackgroundActivityStartsToken = from.mBackgroundActivityStartsToken; timeoutExempt = from.timeoutExempt; alarm = from.alarm; + pushMessage = from.pushMessage; + pushMessageOverQuota = from.pushMessageOverQuota; } /** diff --git a/services/core/java/com/android/server/am/HostingRecord.java b/services/core/java/com/android/server/am/HostingRecord.java index efc2a2719dad1..2498f763ff775 100644 --- a/services/core/java/com/android/server/am/HostingRecord.java +++ b/services/core/java/com/android/server/am/HostingRecord.java @@ -30,6 +30,8 @@ import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HO import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SERVICE; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SYSTEM; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_TOP_ACTIVITY; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_PUSH_MESSAGE; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_PUSH_MESSAGE_OVER_QUOTA; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TYPE__UNKNOWN; @@ -93,6 +95,8 @@ public final class HostingRecord { public static final String TRIGGER_TYPE_UNKNOWN = "unknown"; public static final String TRIGGER_TYPE_ALARM = "alarm"; + public static final String TRIGGER_TYPE_PUSH_MESSAGE = "push_message"; + public static final String TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA = "push_message_over_quota"; @NonNull private final String mHostingType; private final String mHostingName; @@ -308,6 +312,10 @@ public final class HostingRecord { switch(triggerType) { case TRIGGER_TYPE_ALARM: return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM; + case TRIGGER_TYPE_PUSH_MESSAGE: + return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_PUSH_MESSAGE; + case TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA: + return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_PUSH_MESSAGE_OVER_QUOTA; default: return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN; } From 6f2282196a2274e3b7f80882e70da5b1534169ff Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Thu, 25 Aug 2022 17:01:57 -0700 Subject: [PATCH 34/45] Add trigger type job for logging process starts Also renaming some trigger type fields to be consistent. Test: Manually after running: m -j statsd_testdrive && statsd_testdrive 169 Bug: 242928495 Change-Id: I577f940bf09e3ce7b8da87496af413058f324455 Merged-In: I577f940bf09e3ce7b8da87496af413058f324455 (cherry picked from commit e6ab4d719901432e137539c04f92ce4927bc2242) (cherry picked from commit cff11ef25e4b30266e3f9f1e3fb60f40918a72c2) Merged-In: I577f940bf09e3ce7b8da87496af413058f324455 --- .../com/android/server/am/ActiveServices.java | 11 ++++++++++- .../com/android/server/am/HostingRecord.java | 17 +++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 9840e0ff90ced..9669c060b7169 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -4219,7 +4219,8 @@ public final class ActiveServices { final String procName = r.processName; HostingRecord hostingRecord = new HostingRecord( HostingRecord.HOSTING_TYPE_SERVICE, r.instanceName, - r.definingPackageName, r.definingUid, r.serviceInfo.processName); + r.definingPackageName, r.definingUid, r.serviceInfo.processName, + getHostingRecordTriggerType(r)); ProcessRecord app; if (!isolated) { @@ -4323,6 +4324,14 @@ public final class ActiveServices { return null; } + private String getHostingRecordTriggerType(ServiceRecord r) { + if (Manifest.permission.BIND_JOB_SERVICE.equals(r.permission) + && r.mRecentCallingUid == SYSTEM_UID) { + return HostingRecord.TRIGGER_TYPE_JOB; + } + return HostingRecord.TRIGGER_TYPE_UNKNOWN; + } + private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) throws TransactionTooLargeException { for (int i=r.bindings.size()-1; i>=0; i--) { diff --git a/services/core/java/com/android/server/am/HostingRecord.java b/services/core/java/com/android/server/am/HostingRecord.java index 2498f763ff775..30811a175bac7 100644 --- a/services/core/java/com/android/server/am/HostingRecord.java +++ b/services/core/java/com/android/server/am/HostingRecord.java @@ -30,9 +30,10 @@ import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HO import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SERVICE; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SYSTEM; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_TOP_ACTIVITY; -import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_PUSH_MESSAGE; -import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_PUSH_MESSAGE_OVER_QUOTA; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_JOB; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE; +import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN; import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TYPE__UNKNOWN; @@ -97,6 +98,7 @@ public final class HostingRecord { public static final String TRIGGER_TYPE_ALARM = "alarm"; public static final String TRIGGER_TYPE_PUSH_MESSAGE = "push_message"; public static final String TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA = "push_message_over_quota"; + public static final String TRIGGER_TYPE_JOB = "job"; @NonNull private final String mHostingType; private final String mHostingName; @@ -126,10 +128,11 @@ public final class HostingRecord { } public HostingRecord(@NonNull String hostingType, ComponentName hostingName, - String definingPackageName, int definingUid, String definingProcessName) { + String definingPackageName, int definingUid, String definingProcessName, + String triggerType) { this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE, definingPackageName, definingUid, false /* isTopApp */, definingProcessName, null /* action */, - TRIGGER_TYPE_UNKNOWN); + triggerType); } public HostingRecord(@NonNull String hostingType, ComponentName hostingName, boolean isTopApp) { @@ -313,9 +316,11 @@ public final class HostingRecord { case TRIGGER_TYPE_ALARM: return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM; case TRIGGER_TYPE_PUSH_MESSAGE: - return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_PUSH_MESSAGE; + return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE; case TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA: - return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_PUSH_MESSAGE_OVER_QUOTA; + return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA; + case TRIGGER_TYPE_JOB: + return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_JOB; default: return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN; } From fe481372524c13ee37f962371ef182239f5bd8be Mon Sep 17 00:00:00 2001 From: Derek Jedral Date: Wed, 5 Oct 2022 18:58:10 +0000 Subject: [PATCH 35/45] Revert "Fix TrustAgent showing unclear string." This reverts commit 140516bf656b0b011868c306d4e099da58decae4. Reason for revert: Bug where users cannot use biometrics to re-auth after trustagent timeout. Bug: 251078638 Change-Id: I6254196327e09381eaa047e6444034ada6030113 (cherry picked from commit f60d171a4b4d3ef235023391a77829538f6b339f) Merged-In: I6254196327e09381eaa047e6444034ada6030113 --- .../com/android/internal/widget/LockPatternUtils.java | 9 +-------- .../src/com/android/keyguard/KeyguardPasswordView.java | 3 --- .../android/keyguard/KeyguardPatternViewController.java | 3 --- .../com/android/keyguard/KeyguardPinBasedInputView.java | 3 --- .../src/com/android/keyguard/KeyguardSecurityView.java | 6 ------ .../android/systemui/keyguard/KeyguardViewMediator.java | 4 ---- .../com/android/server/trust/TrustManagerService.java | 4 ++-- 7 files changed, 3 insertions(+), 29 deletions(-) diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index a4da8de448809..1235b602cde97 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -1522,8 +1522,7 @@ public class LockPatternUtils { STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN, - STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT, - SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED}) + STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT}) @Retention(RetentionPolicy.SOURCE) public @interface StrongAuthFlags {} @@ -1575,12 +1574,6 @@ public class LockPatternUtils { */ public static final int STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT = 0x80; - /** - * Some authentication is required because the trustagent either timed out or was disabled - * manually. - */ - public static final int SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED = 0x100; - /** * Strong auth flags that do not prevent biometric methods from being accepted as auth. * If any other flags are set, biometric authentication is disabled. diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java index 1e5c53de4446c..2cc5ccdc3fa13 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java @@ -24,7 +24,6 @@ import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT; -import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; import android.animation.Animator; @@ -107,8 +106,6 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView { return R.string.kg_prompt_reason_timeout_password; case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT: return R.string.kg_prompt_reason_timeout_password; - case PROMPT_REASON_TRUSTAGENT_EXPIRED: - return R.string.kg_prompt_reason_timeout_password; case PROMPT_REASON_NONE: return 0; default: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java index 5b223242670c5..987164557a7ad 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java @@ -330,9 +330,6 @@ public class KeyguardPatternViewController case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT: mMessageAreaController.setMessage(R.string.kg_prompt_reason_timeout_pattern); break; - case PROMPT_REASON_TRUSTAGENT_EXPIRED: - mMessageAreaController.setMessage(R.string.kg_prompt_reason_timeout_pattern); - break; case PROMPT_REASON_NONE: break; default: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java index 0a91150e6c399..c46e33d9fd532 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -22,7 +22,6 @@ import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT; -import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; import android.animation.Animator; @@ -124,8 +123,6 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView return R.string.kg_prompt_reason_timeout_pin; case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT: return R.string.kg_prompt_reason_timeout_pin; - case PROMPT_REASON_TRUSTAGENT_EXPIRED: - return R.string.kg_prompt_reason_timeout_pin; case PROMPT_REASON_NONE: return 0; default: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java index 9d0a8acf02b4b..ac00e9453c975 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java @@ -60,12 +60,6 @@ public interface KeyguardSecurityView { */ int PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT = 7; - /** - * Some auth is required because the trustagent expired either from timeout or manually by - * the user - */ - int PROMPT_REASON_TRUSTAGENT_EXPIRED = 8; - /** * Reset the view and prepare to take input. This should do things like clearing the * password or pattern and clear error messages. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 38b98eb45aec2..12101d1189f74 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -25,7 +25,6 @@ import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NAV_BA import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_OCCLUSION; import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD; import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_UNLOCK_ANIMATION; -import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; @@ -804,9 +803,6 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, } else if (trustAgentsEnabled && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) { return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; - } else if (trustAgentsEnabled - && (strongAuth & SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED) != 0) { - return KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED; } else if (any && ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0 || mUpdateMonitor.isFingerprintLockedOut())) { return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT; diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index f888ff60b12a1..7170773edca4f 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -687,7 +687,7 @@ public class TrustManagerService extends SystemService { */ public void lockUser(int userId) { mLockPatternUtils.requireStrongAuth( - StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED, userId); + StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId); try { WindowManagerGlobal.getWindowManagerService().lockNow(null); } catch (RemoteException e) { @@ -2084,7 +2084,7 @@ public class TrustManagerService extends SystemService { if (mStrongAuthTracker.isTrustAllowedForUser(mUserId)) { if (DEBUG) Slog.d(TAG, "Revoking all trust because of trust timeout"); mLockPatternUtils.requireStrongAuth( - mStrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED, mUserId); + mStrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, mUserId); } maybeLockScreen(mUserId); } From 9b794f6dff19f144c590f5c86f51a22179583d77 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Fri, 7 Oct 2022 16:28:30 +0000 Subject: [PATCH 36/45] Revert "[Bouncer] ensure bouncer not shown with doze state." This reverts commit f348307f7ba56ac38d746cde837638dd623156c6. Reason for revert: Causing sim related regressions on the release branch Change-Id: I0cd9830056c41971f7f0f7f33f2567aa40969c19 (cherry picked from commit bbd23aef704512a47553fe0008436f7c544af3fe) Merged-In: I0cd9830056c41971f7f0f7f33f2567aa40969c19 --- .../phone/StatusBarKeyguardViewManager.java | 5 ---- .../StatusBarKeyguardViewManagerTest.java | 24 ------------------- 2 files changed, 29 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index a0578fac2033e..9d5392af3127c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -733,11 +733,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (dozing || mBouncer.needsFullscreenBouncer() || mOccluded) { reset(dozing /* hideBouncerWhenShowing */); } - - if (bouncerIsOrWillBeShowing()) { - // Ensure bouncer is not shown when dozing state changes. - hideBouncer(false); - } updateStates(); if (!dozing) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index f52bfcaaaa448..dcce61b86ced3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -23,11 +23,9 @@ import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -527,26 +525,4 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { mBouncerExpansionCallback.onVisibilityChanged(false); verify(mCentralSurfaces).setBouncerShowingOverDream(false); } - - - @Test - public void testSetDozing_bouncerShowing_Dozing() { - clearInvocations(mBouncer); - when(mBouncer.isShowing()).thenReturn(true); - doAnswer(invocation -> { - when(mBouncer.isShowing()).thenReturn(false); - return null; - }).when(mBouncer).hide(false); - mStatusBarKeyguardViewManager.onDozingChanged(true); - verify(mBouncer, times(1)).hide(false); - } - - @Test - public void testSetDozing_bouncerShowing_notDozing() { - mStatusBarKeyguardViewManager.onDozingChanged(true); - when(mBouncer.isShowing()).thenReturn(true); - clearInvocations(mBouncer); - mStatusBarKeyguardViewManager.onDozingChanged(false); - verify(mBouncer, times(1)).hide(false); - } } From 9acc4b7bad79a307fdf4183cf50a236d5e7f1759 Mon Sep 17 00:00:00 2001 From: Oli Lan Date: Fri, 2 Sep 2022 13:29:39 +0000 Subject: [PATCH 37/45] Validate package name passed to setApplicationRestrictions. (Reland) This adds validation that the package name passed to setApplicationRestrictions is in the correct format. This will avoid an issue where a path could be entered resulting in a file being written to an unexpected place. Bug: 239701237 Merged-In: I1ab2b7228470f10ec26fe3a608ae540cfc9e9a96 Change-Id: I56c2fc14f906cdad80181ab577e2ebc276c151c1 (cherry picked from commit 1b9b59c63bffc675a042cba6cd666831abef2c3e) Merged-In: I56c2fc14f906cdad80181ab577e2ebc276c151c1 --- .../android/server/pm/UserManagerService.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 00fb0651adc4e..c2dd32667bc2f 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -95,6 +95,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; +import android.util.EventLog; import android.util.IndentingPrintWriter; import android.util.IntArray; import android.util.Slog; @@ -4970,6 +4971,13 @@ public class UserManagerService extends IUserManager.Stub { public void setApplicationRestrictions(String packageName, Bundle restrictions, @UserIdInt int userId) { checkSystemOrRoot("set application restrictions"); + String validationResult = validateName(packageName); + if (validationResult != null) { + if (packageName.contains("../")) { + EventLog.writeEvent(0x534e4554, "239701237", -1, ""); + } + throw new IllegalArgumentException("Invalid package name: " + validationResult); + } if (restrictions != null) { restrictions.setDefusable(true); } @@ -4996,6 +5004,39 @@ public class UserManagerService extends IUserManager.Stub { mContext.sendBroadcastAsUser(changeIntent, UserHandle.of(userId)); } + /** + * Check if the given name is valid. + * + * Note: the logic is taken from FrameworkParsingPackageUtils in master, edited to remove + * unnecessary parts. Copied here for a security fix. + * + * @param name The name to check. + * @return null if it's valid, error message if not + */ + @VisibleForTesting + static String validateName(String name) { + final int n = name.length(); + boolean front = true; + for (int i = 0; i < n; i++) { + final char c = name.charAt(i); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + front = false; + continue; + } + if (!front) { + if ((c >= '0' && c <= '9') || c == '_') { + continue; + } + if (c == '.') { + front = true; + continue; + } + } + return "bad character '" + c + "'"; + } + return null; + } + private int getUidForPackage(String packageName) { final long ident = Binder.clearCallingIdentity(); try { From d5122bfaf18f1503e73c1a3a177a56d0f604a008 Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Tue, 20 Sep 2022 15:47:09 -0700 Subject: [PATCH 38/45] Ignore malformed shortcuts After an app publishes a shortcut that contains malformed intent, the system can be stuck in boot-loop due to uncaught exception caused by parsing the malformed intent. This CL ignores that particular malformed entry. Since shortcuts are constantly writes back into the xml from system memory, the malformed entry will be removed from the xml the next time system persists shortcuts from memory to file system. Bug: 246540168 Test: manual Change-Id: I9492fcbd499ab2792c1d08884e3af394c5a4c79f (cherry picked from commit 5238a70be8c3348f9592de5e625f6311e4d51032) Merged-In: I9492fcbd499ab2792c1d08884e3af394c5a4c79f --- .../java/com/android/server/pm/ShortcutPackage.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index 0c601bfde05ac..890c89152a7ce 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -1962,10 +1962,15 @@ class ShortcutPackage extends ShortcutPackageItem { continue; case TAG_SHORTCUT: - final ShortcutInfo si = parseShortcut(parser, packageName, - shortcutUser.getUserId(), fromBackup); - // Don't use addShortcut(), we don't need to save the icon. - ret.mShortcuts.put(si.getId(), si); + try { + final ShortcutInfo si = parseShortcut(parser, packageName, + shortcutUser.getUserId(), fromBackup); + // Don't use addShortcut(), we don't need to save the icon. + ret.mShortcuts.put(si.getId(), si); + } catch (Exception e) { + // b/246540168 malformed shortcuts should be ignored + Slog.e(TAG, "Failed parsing shortcut.", e); + } continue; case TAG_SHARE_TARGET: ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser)); From 1e41d33566f84f624f6a755e4493432d5bd82915 Mon Sep 17 00:00:00 2001 From: Hao Ke Date: Tue, 4 Oct 2022 19:43:58 +0000 Subject: [PATCH 39/45] Add safety checks on KEY_INTENT mismatch. For many years, Parcel mismatch typed exploits has been using the AccoungManagerService's passing of KEY_INTENT workflow, as a foothold of launching arbitrary intents. We are adding an extra check on the service side to simulate the final deserialization of the KEY_INTENT value, to make sure the client side won't get a mismatched KEY_INTENT value. Bug: 250588548 Bug: 240138294 Test: atest CtsAccountManagerTestCases Test: local test, also see b/250588548 Change-Id: I433e34f6e21ce15c89825044a15b1dec46bb25cc (cherry picked from commit ba27731d04d95bf4b17c41a5d85aac09c39b9329) Merged-In: I433e34f6e21ce15c89825044a15b1dec46bb25cc --- .../accounts/AccountManagerService.java | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 6b731c319c4b8..c128b5ead4068 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -89,6 +89,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.stats.devicepolicy.DevicePolicyEnums; import android.text.TextUtils; +import android.util.EventLog; import android.util.Log; import android.util.Pair; import android.util.Slog; @@ -3100,7 +3101,7 @@ public class AccountManagerService */ if (!checkKeyIntent( Binder.getCallingUid(), - intent)) { + result)) { onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "invalid intent in bundle returned"); return; @@ -3519,7 +3520,7 @@ public class AccountManagerService && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { if (!checkKeyIntent( Binder.getCallingUid(), - intent)) { + result)) { onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "invalid intent in bundle returned"); return; @@ -4870,7 +4871,13 @@ public class AccountManagerService * into launching arbitrary intents on the device via by tricking to click authenticator * supplied entries in the system Settings app. */ - protected boolean checkKeyIntent(int authUid, Intent intent) { + protected boolean checkKeyIntent(int authUid, Bundle bundle) { + if (!checkKeyIntentParceledCorrectly(bundle)) { + EventLog.writeEvent(0x534e4554, "250588548", authUid, ""); + return false; + } + + Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class); // Explicitly set an empty ClipData to ensure that we don't offer to // promote any Uris contained inside for granting purposes if (intent.getClipData() == null) { @@ -4905,6 +4912,25 @@ public class AccountManagerService } } + /** + * Simulate the client side's deserialization of KEY_INTENT value, to make sure they don't + * violate our security policy. + * + * In particular we want to make sure the Authenticator doesn't trick users + * into launching arbitrary intents on the device via exploiting any other Parcel read/write + * mismatch problems. + */ + private boolean checkKeyIntentParceledCorrectly(Bundle bundle) { + Parcel p = Parcel.obtain(); + p.writeBundle(bundle); + p.setDataPosition(0); + Bundle simulateBundle = p.readBundle(); + p.recycle(); + Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class); + return (intent.filterEquals(simulateBundle.getParcelable(AccountManager.KEY_INTENT, + Intent.class))); + } + private boolean isExportedSystemActivity(ActivityInfo activityInfo) { String className = activityInfo.name; return "android".equals(activityInfo.packageName) && @@ -5051,7 +5077,7 @@ public class AccountManagerService && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { if (!checkKeyIntent( Binder.getCallingUid(), - intent)) { + result)) { onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "invalid intent in bundle returned"); return; From 569c3023f839bca077cd3cccef0a3bef9c31af63 Mon Sep 17 00:00:00 2001 From: Hani Kazmi Date: Tue, 27 Sep 2022 10:19:45 +0000 Subject: [PATCH 40/45] Update Parcel readLazyValue to ignore negative object lengths Addresses a security vulnerability where a (-8) length object would cause dataPosition to be reset back to the statt of the value, and be re-read again. Bug: 240138294 Test: atest ParcelTest BundleTest AmbiguousBundlesTest Test: manually ran PoC Change-Id: I1ab1df6f2a802d8cdf02c89c12959b09d7b1a5c4 Merged-In: I1ab1df6f2a802d8cdf02c89c12959b09d7b1a5c4 (cherry picked from commit 8e01230dd264d652c6f4c82d850da5afc4768bdc) Merged-In: I1ab1df6f2a802d8cdf02c89c12959b09d7b1a5c4 --- core/java/android/os/Parcel.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 3d701389a98ea..a7349f9e473e9 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -4388,6 +4388,9 @@ public final class Parcel { int type = readInt(); if (isLengthPrefixed(type)) { int objectLength = readInt(); + if (objectLength < 0) { + return null; + } int end = MathUtils.addOrThrow(dataPosition(), objectLength); int valueLength = end - start; setDataPosition(end); From beafe0590127c50f2ed8ae91fa7f295bc3b5441e Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Thu, 6 Oct 2022 11:39:15 -0400 Subject: [PATCH 41/45] Revert change in qs padding in portrait When not using combined headers, the padding should be smaller as the old headers take less vertical space. Test: manual, with and without flag Test: atest com.android.systemui.qs Fixes: 251235055 Change-Id: Ic56f2eceae76e3613737f02f4c511bec9766fe95 (cherry picked from commit e6b106bc75afd8db5f62b37c7418e6bdf71cf440) Merged-In: Ic56f2eceae76e3613737f02f4c511bec9766fe95 --- packages/SystemUI/res/values-land/dimens.xml | 1 + .../SystemUI/res/values-sw600dp/dimens.xml | 1 + packages/SystemUI/res/values/dimens.xml | 3 ++- .../src/com/android/systemui/qs/QSPanel.java | 9 ++++++- .../systemui/qs/QSPanelController.java | 6 ++++- .../systemui/qs/QSPanelControllerTest.kt | 5 +++- .../com/android/systemui/qs/QSPanelTest.kt | 26 +++++++++++++++++++ 7 files changed, 47 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml index 9d7b01c8d252f..49ef330dcc528 100644 --- a/packages/SystemUI/res/values-land/dimens.xml +++ b/packages/SystemUI/res/values-land/dimens.xml @@ -59,4 +59,5 @@ 348dp @dimen/qqs_layout_margin_top + @dimen/qs_panel_padding_top diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index 5dcbeb5c85cf2..599bf30a5135c 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -68,6 +68,7 @@ 0dp 8dp + @dimen/qs_panel_padding_top 472dp diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index f7019dcd06ee1..b8fabbec6c2b6 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -559,7 +559,8 @@ 6dp 4dp @dimen/footer_actions_height - 80dp + 48dp + 80dp 14sp 36sp diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 184089f7eef47..6517ff33a49df 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -105,6 +105,7 @@ public class QSPanel extends LinearLayout implements Tunable { private final Rect mClippingRect = new Rect(); private ViewGroup mMediaHostView; private boolean mShouldMoveMediaOnExpansion = true; + private boolean mUsingCombinedHeaders = false; public QSPanel(Context context, AttributeSet attrs) { super(context, attrs); @@ -148,6 +149,10 @@ public class QSPanel extends LinearLayout implements Tunable { } } + void setUsingCombinedHeaders(boolean usingCombinedHeaders) { + mUsingCombinedHeaders = usingCombinedHeaders; + } + protected void setHorizontalContentContainerClipping() { mHorizontalContentContainer.setClipChildren(true); mHorizontalContentContainer.setClipToPadding(false); @@ -371,7 +376,9 @@ public class QSPanel extends LinearLayout implements Tunable { protected void updatePadding() { final Resources res = mContext.getResources(); - int paddingTop = res.getDimensionPixelSize(R.dimen.qs_panel_padding_top); + int paddingTop = res.getDimensionPixelSize( + mUsingCombinedHeaders ? R.dimen.qs_panel_padding_top_combined_headers + : R.dimen.qs_panel_padding_top); int paddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom); setPaddingRelative(getPaddingStart(), paddingTop, diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java index 18bd6b7b3c320..f6db775a77490 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -17,6 +17,7 @@ package com.android.systemui.qs; import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE; +import static com.android.systemui.flags.Flags.COMBINED_QS_HEADERS; import static com.android.systemui.media.dagger.MediaModule.QS_PANEL; import static com.android.systemui.qs.QSPanel.QS_SHOW_BRIGHTNESS; import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER; @@ -27,6 +28,7 @@ import android.view.View; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.media.MediaHost; import com.android.systemui.media.MediaHostState; @@ -79,7 +81,8 @@ public class QSPanelController extends QSPanelControllerBase { QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory, BrightnessSliderController.Factory brightnessSliderFactory, FalsingManager falsingManager, - StatusBarKeyguardViewManager statusBarKeyguardViewManager) { + StatusBarKeyguardViewManager statusBarKeyguardViewManager, + FeatureFlags featureFlags) { super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, uiEventLogger, qsLogger, dumpManager); mTunerService = tunerService; @@ -93,6 +96,7 @@ public class QSPanelController extends QSPanelControllerBase { mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController); mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController); mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; + mView.setUsingCombinedHeaders(featureFlags.isEnabled(COMBINED_QS_HEADERS)); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt index 5eb9a9862340a..e539705d9eded 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt @@ -6,6 +6,7 @@ import com.android.internal.logging.MetricsLogger import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager +import com.android.systemui.flags.FeatureFlags import com.android.systemui.media.MediaHost import com.android.systemui.media.MediaHostState import com.android.systemui.plugins.FalsingManager @@ -52,6 +53,7 @@ class QSPanelControllerTest : SysuiTestCase() { @Mock private lateinit var tile: QSTile @Mock private lateinit var otherTile: QSTile @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager + @Mock private lateinit var featureFlags: FeatureFlags private lateinit var controller: QSPanelController @@ -82,7 +84,8 @@ class QSPanelControllerTest : SysuiTestCase() { brightnessControllerFactory, brightnessSliderFactory, falsingManager, - statusBarKeyguardViewManager + statusBarKeyguardViewManager, + featureFlags ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt index 2db58be156656..7c930b196d683 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt @@ -158,6 +158,32 @@ class QSPanelTest : SysuiTestCase() { assertThat(qsPanel.paddingBottom).isEqualTo(padding) } + @Test + fun testTopPadding_notCombinedHeaders() { + qsPanel.setUsingCombinedHeaders(false) + val padding = 10 + val paddingCombined = 100 + context.orCreateTestableResources.addOverride(R.dimen.qs_panel_padding_top, padding) + context.orCreateTestableResources.addOverride( + R.dimen.qs_panel_padding_top_combined_headers, paddingCombined) + + qsPanel.updatePadding() + assertThat(qsPanel.paddingTop).isEqualTo(padding) + } + + @Test + fun testTopPadding_combinedHeaders() { + qsPanel.setUsingCombinedHeaders(true) + val padding = 10 + val paddingCombined = 100 + context.orCreateTestableResources.addOverride(R.dimen.qs_panel_padding_top, padding) + context.orCreateTestableResources.addOverride( + R.dimen.qs_panel_padding_top_combined_headers, paddingCombined) + + qsPanel.updatePadding() + assertThat(qsPanel.paddingTop).isEqualTo(paddingCombined) + } + @Test fun testSetSquishinessFraction_noCrash() { qsPanel.addView(qsPanel.mTileLayout as View, 0) From 88b9e2b92b5c4d58de97241a2ab6c9c08a129073 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 6 Oct 2022 00:48:19 +0000 Subject: [PATCH 42/45] Allow Android Auto to move to trusted. Seems like there is a bug with how TrustManagerService deals with automotive now that there is the possibility for renewable trust, preventing the automotive companion from being unlocked by the phone. To fix this, we'll update canMoveToTrusted to also allow automotive trustagents to automatically move to trusted (if the right other conditions are met). Test: Manually for automotive Fixes: 250703401 Change-Id: I906be77a2f09582095d24797aebdb0eda420eee6 (cherry picked from commit 2fa61e04624ec9ccbfb9945b7b911ca564b6b6fb) Merged-In: I906be77a2f09582095d24797aebdb0eda420eee6 --- .../java/com/android/server/trust/TrustManagerService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 7170773edca4f..2888b9a2d3ccf 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -602,9 +602,12 @@ public class TrustManagerService extends SystemService { synchronized (mUserTrustState) { wasTrusted = (mUserTrustState.get(userId) == TrustState.TRUSTED); wasTrustable = (mUserTrustState.get(userId) == TrustState.TRUSTABLE); + boolean isAutomotive = getContext().getPackageManager().hasSystemFeature( + PackageManager.FEATURE_AUTOMOTIVE); boolean renewingTrust = wasTrustable && ( (flags & TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) != 0); - boolean canMoveToTrusted = alreadyUnlocked || isFromUnlock || renewingTrust; + boolean canMoveToTrusted = + alreadyUnlocked || isFromUnlock || renewingTrust || isAutomotive; boolean upgradingTrustForCurrentUser = (userId == mCurrentUser); if (trustedByAtLeastOneAgent && wasTrusted) { From 2b99c7ab95bb0e81461e8249f4bd148d20987824 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Thu, 6 Oct 2022 13:28:51 -0700 Subject: [PATCH 43/45] [Bouncer] Flag off bouncer interactor. Do not invoke the bouncer interactor if the flag is off. Fixes: 250498666 Test: Manual test. Added a unit test. Change-Id: I44b7be029b1a1cd1dbd356499252fa3aee6edccb (cherry picked from commit 46b09796610fed0ebbc517494c0ad122f934127b) Merged-In: I44b7be029b1a1cd1dbd356499252fa3aee6edccb --- .../phone/StatusBarKeyguardViewManager.java | 87 ++++++++++++------- .../StatusBarKeyguardViewManagerTest.java | 9 ++ 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 9d5392af3127c..ec7b8204b8643 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -405,8 +405,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } else if (mNotificationPanelViewController.isUnlockHintRunning()) { if (mBouncer != null) { mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); + } else { + mBouncerInteractor.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); } - mBouncerInteractor.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) { // Don't expand to the bouncer. Instead transition back to the lock screen (see // CentralSurfaces#showBouncerOrLockScreenIfKeyguard) @@ -414,8 +415,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } else if (bouncerNeedsScrimming()) { if (mBouncer != null) { mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); + } else { + mBouncerInteractor.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); } - mBouncerInteractor.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); } else if (mShowing && !hideBouncerOverDream) { if (!isWakeAndUnlocking() && !(mBiometricUnlockController.getMode() == MODE_DISMISS_BOUNCER) @@ -423,8 +425,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb && !isUnlockCollapsing()) { if (mBouncer != null) { mBouncer.setExpansion(fraction); + } else { + mBouncerInteractor.setExpansion(fraction); } - mBouncerInteractor.setExpansion(fraction); } if (fraction != KeyguardBouncer.EXPANSION_HIDDEN && tracking && !mKeyguardStateController.canDismissLockScreen() @@ -432,16 +435,18 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb && !bouncerIsAnimatingAway()) { if (mBouncer != null) { mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */); + } else { + mBouncerInteractor.show(/* isScrimmed= */false); } - mBouncerInteractor.show(/* isScrimmed= */false); } } else if (!mShowing && isBouncerInTransit()) { // Keyguard is not visible anymore, but expansion animation was still running. // We need to hide the bouncer, otherwise it will be stuck in transit. if (mBouncer != null) { mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); + } else { + mBouncerInteractor.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); } - mBouncerInteractor.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); } else if (mPulsing && fraction == KeyguardBouncer.EXPANSION_VISIBLE) { // Panel expanded while pulsing but didn't translate the bouncer (because we are // unlocked.) Let's simply wake-up to dismiss the lock screen. @@ -487,8 +492,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mCentralSurfaces.hideKeyguard(); if (mBouncer != null) { mBouncer.show(true /* resetSecuritySelection */); + } else { + mBouncerInteractor.show(true); } - mBouncerInteractor.show(true); } else { mCentralSurfaces.showKeyguard(); if (hideBouncerWhenShowing) { @@ -529,8 +535,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb void hideBouncer(boolean destroyView) { if (mBouncer != null) { mBouncer.hide(destroyView); + } else { + mBouncerInteractor.hide(); } - mBouncerInteractor.hide(); if (mShowing) { // If we were showing the bouncer and then aborting, we need to also clear out any // potential actions unless we actually unlocked. @@ -551,8 +558,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (mShowing && !isBouncerShowing()) { if (mBouncer != null) { mBouncer.show(false /* resetSecuritySelection */, scrimmed); + } else { + mBouncerInteractor.show(scrimmed); } - mBouncerInteractor.show(scrimmed); } updateStates(); } @@ -588,9 +596,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (mBouncer != null) { mBouncer.setDismissAction(mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); + } else { + mBouncerInteractor.setDismissAction(mAfterKeyguardGoneAction, + mKeyguardGoneCancelAction); } - mBouncerInteractor.setDismissAction(mAfterKeyguardGoneAction, - mKeyguardGoneCancelAction); mAfterKeyguardGoneAction = null; mKeyguardGoneCancelAction = null; } @@ -603,17 +612,21 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (afterKeyguardGone) { // we'll handle the dismiss action after keyguard is gone, so just show the // bouncer - mBouncerInteractor.show(/* isScrimmed= */true); - if (mBouncer != null) mBouncer.show(false /* resetSecuritySelection */); + if (mBouncer != null) { + mBouncer.show(false /* resetSecuritySelection */); + } else { + mBouncerInteractor.show(/* isScrimmed= */true); + } } else { // after authentication success, run dismiss action with the option to defer // hiding the keyguard based on the return value of the OnDismissAction - mBouncerInteractor.setDismissAction( - mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); - mBouncerInteractor.show(/* isScrimmed= */true); if (mBouncer != null) { mBouncer.showWithDismissAction(mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); + } else { + mBouncerInteractor.setDismissAction( + mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); + mBouncerInteractor.show(/* isScrimmed= */true); } // bouncer will handle the dismiss action, so we no longer need to track it here mAfterKeyguardGoneAction = null; @@ -717,8 +730,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void onFinishedGoingToSleep() { if (mBouncer != null) { mBouncer.onScreenTurnedOff(); + } else { + mBouncerInteractor.onScreenTurnedOff(); } - mBouncerInteractor.onScreenTurnedOff(); } @Override @@ -830,8 +844,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (bouncerIsShowing()) { if (mBouncer != null) { mBouncer.startPreHideAnimation(finishRunnable); + } else { + mBouncerInteractor.startDisappearAnimation(finishRunnable); } - mBouncerInteractor.startDisappearAnimation(finishRunnable); mCentralSurfaces.onBouncerPreHideAnimation(); // We update the state (which will show the keyguard) only if an animation will run on @@ -1102,13 +1117,15 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (bouncerDismissible || !showing || remoteInputActive) { if (mBouncer != null) { mBouncer.setBackButtonEnabled(true); + } else { + mBouncerInteractor.setBackButtonEnabled(true); } - mBouncerInteractor.setBackButtonEnabled(true); } else { if (mBouncer != null) { mBouncer.setBackButtonEnabled(false); + } else { + mBouncerInteractor.setBackButtonEnabled(false); } - mBouncerInteractor.setBackButtonEnabled(false); } } @@ -1274,8 +1291,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void notifyKeyguardAuthenticated(boolean strongAuth) { if (mBouncer != null) { mBouncer.notifyKeyguardAuthenticated(strongAuth); + } else { + mBouncerInteractor.notifyKeyguardAuthenticated(strongAuth); } - mBouncerInteractor.notifyKeyguardAuthenticated(strongAuth); if (mAlternateAuthInterceptor != null && isShowingAlternateAuthOrAnimating()) { resetAlternateAuth(false); @@ -1292,8 +1310,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } else { if (mBouncer != null) { mBouncer.showMessage(message, colorState); + } else { + mBouncerInteractor.showMessage(message, colorState); } - mBouncerInteractor.showMessage(message, colorState); } } @@ -1340,8 +1359,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void updateResources() { if (mBouncer != null) { mBouncer.updateResources(); + } else { + mBouncerInteractor.updateResources(); } - mBouncerInteractor.updateResources(); } public void dump(PrintWriter pw) { @@ -1426,9 +1446,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void updateKeyguardPosition(float x) { if (mBouncer != null) { mBouncer.updateKeyguardPosition(x); + } else { + mBouncerInteractor.setKeyguardPosition(x); } - - mBouncerInteractor.setKeyguardPosition(x); } private static class DismissWithActionRequest { @@ -1470,9 +1490,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public boolean isBouncerInTransit() { if (mBouncer != null) { return mBouncer.inTransit(); + } else { + return mBouncerInteractor.isInTransit(); } - - return mBouncerInteractor.isInTransit(); } /** @@ -1481,9 +1501,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public boolean bouncerIsShowing() { if (mBouncer != null) { return mBouncer.isShowing(); + } else { + return mBouncerInteractor.isFullyShowing(); } - - return mBouncerInteractor.isFullyShowing(); } /** @@ -1492,9 +1512,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public boolean bouncerIsScrimmed() { if (mBouncer != null) { return mBouncer.isScrimmed(); + } else { + return mBouncerInteractor.isScrimmed(); } - - return mBouncerInteractor.isScrimmed(); } /** @@ -1503,9 +1523,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public boolean bouncerIsAnimatingAway() { if (mBouncer != null) { return mBouncer.isAnimatingAway(); + } else { + return mBouncerInteractor.isAnimatingAway(); } - return mBouncerInteractor.isAnimatingAway(); } /** @@ -1514,9 +1535,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public boolean bouncerWillDismissWithAction() { if (mBouncer != null) { return mBouncer.willDismissWithAction(); + } else { + return mBouncerInteractor.willDismissWithAction(); } - - return mBouncerInteractor.willDismissWithAction(); } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index dcce61b86ced3..5a12fcb1b4d88 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.phone; +import static com.android.systemui.flags.Flags.MODERN_BOUNCER; + import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -525,4 +527,11 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { mBouncerExpansionCallback.onVisibilityChanged(false); verify(mCentralSurfaces).setBouncerShowingOverDream(false); } + + @Test + public void flag_off_DoesNotCallBouncerInteractor() { + when(mFeatureFlags.isEnabled(MODERN_BOUNCER)).thenReturn(false); + mStatusBarKeyguardViewManager.hideBouncer(false); + verify(mBouncerInteractor, never()).hide(); + } } From 18cc8e142636c2c1fc21b7502ff48068ac16ddc9 Mon Sep 17 00:00:00 2001 From: John Wu Date: Tue, 27 Sep 2022 17:11:32 +0000 Subject: [PATCH 44/45] Use setIdentifier instead of dynamic categories Change I27987301ebf393de6f781b17ed7bc789789c01ab introduced the usage of dynamic categories to prevent the pending intent from being cached. This is incompatible with the new T explicit intent filter enforcement, as a dynamic category can never match any intent-filter. Switch to use the PendingIntent#setIdentifier API introduced in API 29, specifically designed for this use case. Bug: 249043995 Test: m + manual Change-Id: I2bbe4e554ef337299138f2a7691eeffc60e18e9d (cherry picked from commit 8afc387eb1fe5061250e88d5666ae47c11ab5b07) Merged-In: I2bbe4e554ef337299138f2a7691eeffc60e18e9d --- .../systemui/statusbar/notification/InstantAppNotifier.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java index 59022c0ffbf22..6514d5b6f0808 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java @@ -289,7 +289,7 @@ public class InstantAppNotifier extends CoreStartable .setComponent(aiaComponent) .setAction(Intent.ACTION_VIEW) .addCategory(Intent.CATEGORY_BROWSABLE) - .addCategory("unique:" + System.currentTimeMillis()) + .setIdentifier("unique:" + System.currentTimeMillis()) .putExtra(Intent.EXTRA_PACKAGE_NAME, appInfo.packageName) .putExtra( Intent.EXTRA_VERSION_CODE, From 720f8e1ffbf47d1b11d15735faf65c08fdf420df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Budnik?= Date: Tue, 30 Aug 2022 12:44:12 +0000 Subject: [PATCH 45/45] Revert "Enforce ComponentName belongs to caller app" This reverts commit 7319e40b37aba598e081b56095b7ed4e0a04396c. Reason for revert: b/241798893. Note: this fix is not the root cause of the breakage. It just exposes a previously unknown bug. See linked bug. Change-Id: I2ec5fd036af1d35c6d3fe000ee41f3347f9aea41 Merged-In: I01bda0f5bf343d73c480ad64b562dd0a2ee46e30 (cherry picked from commit 8914ae87def2171b1fabfc69b36e8b56114866e6) Merged-In: I2ec5fd036af1d35c6d3fe000ee41f3347f9aea41 --- .../media/MediaButtonReceiverHolder.java | 7 ------- .../server/media/MediaSessionRecord.java | 19 ------------------- 2 files changed, 26 deletions(-) diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java index 6759d79eedcae..9a190316f4eb6 100644 --- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java +++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java @@ -32,7 +32,6 @@ import android.os.Handler; import android.os.PowerWhitelistManager; import android.os.UserHandle; import android.text.TextUtils; -import android.util.EventLog; import android.util.Log; import android.view.KeyEvent; @@ -118,12 +117,6 @@ final class MediaButtonReceiverHolder { int componentType = getComponentType(pendingIntent); ComponentName componentName = getComponentName(pendingIntent, componentType); if (componentName != null) { - if (!TextUtils.equals(componentName.getPackageName(), sessionPackageName)) { - EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging - throw new IllegalArgumentException("ComponentName does not belong to " - + "sessionPackageName. sessionPackageName = " + sessionPackageName - + ", ComponentName pkg = " + componentName.getPackageName()); - } return new MediaButtonReceiverHolder(userId, pendingIntent, componentName, componentType); } diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index b8131a8ee5b54..604e8f3949f4e 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -52,8 +52,6 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; -import android.text.TextUtils; -import android.util.EventLog; import android.util.Log; import android.view.KeyEvent; @@ -940,14 +938,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR @Override public void setMediaButtonReceiver(PendingIntent pi, String sessionPackageName) throws RemoteException { - //mPackageName has been verified in MediaSessionService.enforcePackageName(). - if (!TextUtils.equals(sessionPackageName, mPackageName)) { - EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging - throw new IllegalArgumentException("sessionPackageName name does not match " - + "package name provided to MediaSessionRecord. sessionPackageName = " - + sessionPackageName + ", pkg = " - + mPackageName); - } final long token = Binder.clearCallingIdentity(); try { if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER) @@ -966,15 +956,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR public void setMediaButtonBroadcastReceiver(ComponentName receiver) throws RemoteException { final long token = Binder.clearCallingIdentity(); try { - //mPackageName has been verified in MediaSessionService.enforcePackageName(). - if (receiver != null && !TextUtils.equals( - mPackageName, receiver.getPackageName())) { - EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging - throw new IllegalArgumentException("receiver does not belong to " - + "package name provided to MediaSessionRecord. Pkg = " + mPackageName - + ", Receiver Pkg = " + receiver.getPackageName()); - } - if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER) != 0) { return;