Merge "Removes old/unused left/right button logic from bottom area." into tm-qpr-dev am: 4c5423146c am: b1a7e1b6ba

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19119857

Change-Id: I5e2e26350696891704d4e0e817620c8c0414d23b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-07-02 05:43:05 +00:00
committed by Automerger Merge Worker
17 changed files with 248 additions and 1657 deletions

View File

@@ -59,26 +59,6 @@
</LinearLayout>
<com.android.systemui.statusbar.KeyguardAffordanceView
android:id="@+id/camera_button"
android:layout_height="@dimen/keyguard_affordance_height"
android:layout_width="@dimen/keyguard_affordance_width"
android:layout_gravity="bottom|end"
android:src="@drawable/ic_camera_alt_24dp"
android:scaleType="center"
android:contentDescription="@string/accessibility_camera_button"
android:tint="?attr/wallpaperTextColor" />
<com.android.systemui.statusbar.KeyguardAffordanceView
android:id="@+id/left_button"
android:layout_height="@dimen/keyguard_affordance_height"
android:layout_width="@dimen/keyguard_affordance_width"
android:layout_gravity="bottom|start"
android:src="@*android:drawable/ic_phone"
android:scaleType="center"
android:contentDescription="@string/accessibility_phone_button"
android:tint="?attr/wallpaperTextColor" />
<ImageView
android:id="@+id/wallet_button"
android:layout_height="@dimen/keyguard_affordance_fixed_height"

View File

@@ -37,12 +37,6 @@
<item>400</item>
</integer-array>
<!-- Show mic or phone affordance on Keyguard -->
<bool name="config_keyguardShowLeftAffordance">false</bool>
<!-- Show camera affordance on Keyguard -->
<bool name="config_keyguardShowCameraAffordance">false</bool>
<!-- decay duration (from size_max -> size), in ms -->
<integer name="navigation_bar_deadzone_hold">333</integer>
<integer name="navigation_bar_deadzone_decay">333</integer>

View File

@@ -671,9 +671,6 @@
<!-- The minimum background radius when swiping to a side for the camera / phone affordances. -->
<dimen name="keyguard_affordance_min_background_radius">30dp</dimen>
<!-- The size of the touch targets on the keyguard for the affordances. -->
<dimen name="keyguard_affordance_touch_target_size">120dp</dimen>
<!-- The grow amount for the camera and phone circles when hinting -->
<dimen name="hint_grow_amount_sideways">60dp</dimen>

View File

@@ -313,13 +313,6 @@
<string name="accessibility_scanning_face">Scanning face</string>
<!-- Click action label for accessibility for the smart reply buttons (not shown on-screen).". [CHAR LIMIT=NONE] -->
<string name="accessibility_send_smart_reply">Send</string>
<!-- Content description of the manage notification button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
<string name="phone_label">open phone</string>
<!-- Click action label for accessibility for the voice assist button. This is not shown on-screen and is an accessibility label for the icon which launches the voice assist from the lock screen.[CHAR LIMIT=NONE] -->
<string name="voice_assist_label">open voice assist</string>
<!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
<string name="camera_label">open camera</string>
<!-- Button name for "Cancel". [CHAR LIMIT=NONE] -->
<string name="cancel">Cancel</string>

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2021 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.camera
import android.app.ActivityManager
import android.app.ActivityManager.RunningTaskInfo
import android.app.ActivityOptions
import android.app.ActivityTaskManager
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.os.AsyncTask
import android.os.RemoteException
import android.os.UserHandle
import android.util.Log
import android.view.WindowManager
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.ActivityIntentHelper
import com.android.systemui.camera.CameraIntents.Companion.isSecureCameraIntent
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.PanelViewController
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
/**
* Helps with handling camera-related gestures (for example, double-tap the power button to launch
* the camera).
*/
class CameraGestureHelper @Inject constructor(
private val context: Context,
private val centralSurfaces: CentralSurfaces,
private val keyguardStateController: KeyguardStateController,
private val packageManager: PackageManager,
private val activityManager: ActivityManager,
private val activityStarter: ActivityStarter,
private val activityIntentHelper: ActivityIntentHelper,
private val cameraIntents: CameraIntentsWrapper,
private val contentResolver: ContentResolver,
) {
/**
* Whether the camera application can be launched for the camera launch gesture.
*/
fun canCameraGestureBeLaunched(statusBarState: Int): Boolean {
if (!centralSurfaces.isCameraAllowedByAdmin) {
return false
}
val resolveInfo: ResolveInfo = packageManager.resolveActivityAsUser(
getStartCameraIntent(),
PackageManager.MATCH_DEFAULT_ONLY,
KeyguardUpdateMonitor.getCurrentUser()
)
val resolvedPackage = resolveInfo.activityInfo?.packageName
return (resolvedPackage != null &&
(statusBarState != StatusBarState.SHADE ||
!isForegroundApp(resolvedPackage)))
}
/**
* Launches the camera.
*
* @param source The source of the camera launch, to be passed to the camera app via [Intent]
*/
fun launchCamera(source: Int) {
val intent: Intent = getStartCameraIntent()
intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source)
val wouldLaunchResolverActivity = activityIntentHelper.wouldLaunchResolverActivity(
intent, KeyguardUpdateMonitor.getCurrentUser()
)
if (isSecureCameraIntent(intent) && !wouldLaunchResolverActivity) {
AsyncTask.execute {
// Normally an activity will set its 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).
// Therefore, we ask the WindowManager to force the cross-fade animation if an
// orientation change happens to occur during the launch.
val activityOptions = ActivityOptions.makeBasic()
activityOptions.setDisallowEnterPictureInPictureWhileLaunching(true)
activityOptions.rotationAnimationHint =
WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
try {
ActivityTaskManager.getService().startActivityAsUser(
null,
context.basePackageName,
context.attributionTag,
intent,
intent.resolveTypeIfNeeded(contentResolver),
null,
null,
0,
Intent.FLAG_ACTIVITY_NEW_TASK,
null,
activityOptions.toBundle(),
UserHandle.CURRENT.identifier,
)
} catch (e: RemoteException) {
Log.w(
PanelViewController.TAG,
"Unable to start camera activity",
e
)
}
}
} else {
// We need to delay starting the activity because ResolverActivity finishes itself if
// launched from behind the lock-screen.
activityStarter.startActivity(intent, false /* dismissShade */)
}
}
/**
* Returns an [Intent] that can be used to start the camera app such that it occludes the
* lock-screen, if needed.
*/
private fun getStartCameraIntent(): Intent {
val isLockScreenDismissible = keyguardStateController.canDismissLockScreen()
val isSecure = keyguardStateController.isMethodSecure
return if (isSecure && !isLockScreenDismissible) {
cameraIntents.getSecureCameraIntent()
} else {
cameraIntents.getInsecureCameraIntent()
}
}
/**
* Returns `true` if the application with the given package name is running in the foreground;
* `false` otherwise
*/
private fun isForegroundApp(packageName: String): Boolean {
val tasks: List<RunningTaskInfo> = activityManager.getRunningTasks(1)
return tasks.isNotEmpty() && packageName == tasks[0].topActivity.packageName
}
companion object {
private const val EXTRA_CAMERA_LAUNCH_SOURCE = "com.android.systemui.camera_launch_source"
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2021 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.camera
import android.content.Context
import android.content.Intent
import javax.inject.Inject
/** Injectable wrapper around [CameraIntents]. */
class CameraIntentsWrapper @Inject constructor(
private val context: Context,
) {
/**
* Returns an [Intent] that can be used to start the camera, suitable for when the device is
* already unlocked
*/
fun getSecureCameraIntent(): Intent {
return CameraIntents.getSecureCameraIntent(context)
}
/**
* Returns an [Intent] that can be used to start the camera, suitable for when the device is not
* already unlocked
*/
fun getInsecureCameraIntent(): Intent {
return CameraIntents.getInsecureCameraIntent(context)
}
}

View File

@@ -427,12 +427,6 @@ 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.

View File

@@ -388,8 +388,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.reset(true /* hide */);
}
mNotificationPanelViewController.launchCamera(
mCentralSurfaces.isDeviceInteractive() /* animate */, source);
mNotificationPanelViewController.launchCamera(source);
mCentralSurfaces.updateScrimController();
} else {
// We need to defer the camera launch until the screen comes on, since otherwise

View File

@@ -1268,8 +1268,6 @@ 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) {
@@ -3008,8 +3006,7 @@ public class CentralSurfacesImpl extends CoreStartable implements
@Override
public boolean isInLaunchTransition() {
return mNotificationPanelViewController.isLaunchTransitionRunning()
|| mNotificationPanelViewController.isLaunchTransitionFinished();
return mNotificationPanelViewController.isLaunchTransitionFinished();
}
/**
@@ -3041,11 +3038,7 @@ public class CentralSurfacesImpl extends CoreStartable implements
mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(),
LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
};
if (mNotificationPanelViewController.isLaunchTransitionRunning()) {
mNotificationPanelViewController.setLaunchTransitionEndRunnable(hideRunnable);
} else {
hideRunnable.run();
}
hideRunnable.run();
}
private void cancelAfterLaunchTransitionRunnables() {
@@ -3054,7 +3047,6 @@ public class CentralSurfacesImpl extends CoreStartable implements
}
mLaunchTransitionEndRunnable = null;
mLaunchTransitionCancelRunnable = null;
mNotificationPanelViewController.setLaunchTransitionEndRunnable(null);
}
/**
@@ -3482,24 +3474,6 @@ 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) {
}
@@ -3684,8 +3658,7 @@ public class CentralSurfacesImpl extends CoreStartable implements
mWakeUpCoordinator.setFullyAwake(true);
mWakeUpCoordinator.setWakingUp(false);
if (mLaunchCameraWhenFinishedWaking) {
mNotificationPanelViewController.launchCamera(
false /* animate */, mLastCameraLaunchSource);
mNotificationPanelViewController.launchCamera(mLastCameraLaunchSource);
mLaunchCameraWhenFinishedWaking = false;
}
if (mLaunchEmergencyActionWhenFinishedWaking) {
@@ -4327,9 +4300,6 @@ public class CentralSurfacesImpl extends CoreStartable implements
if (!mUserSetup) {
animateCollapseQuickSettings();
}
if (mNotificationPanelViewController != null) {
mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
}
updateQsExpansionEnabled();
}
}

View File

@@ -1,587 +0,0 @@
/*
* 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();
}
}

View File

@@ -16,47 +16,30 @@
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;
@@ -64,81 +47,35 @@ 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 implements View.OnClickListener,
KeyguardStateController.Callback,
AccessibilityController.AccessibilityStateChangedCallback {
public class KeyguardBottomAreaView extends FrameLayout {
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 String TAG = "CentralSurfaces/KeyguardBottomAreaView";
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 WalletCardRetriever mCardRetriever = new WalletCardRetriever();
private final WalletCardRetriever mCardRetriever = new WalletCardRetriever();
private QuickAccessWalletController mQuickAccessWalletController;
private QRCodeScannerController mQRCodeScannerController;
private ControlsComponent mControlsComponent;
@@ -148,54 +85,42 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
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<IntentButton> mRightExtension;
private String mRightButtonStr;
private IntentButton mLeftButton = new DefaultLeftButton();
private Extension<IntentButton> 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 ControlsListingController.ControlsListingCallback mListingCallback =
new ControlsListingController.ControlsListingCallback() {
public void onServicesUpdated(List<ControlsServiceInfo> serviceInfos) {
post(() -> {
boolean available = !serviceInfos.isEmpty();
private final ControlsListingController.ControlsListingCallback mListingCallback =
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);
@@ -212,43 +137,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
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);
@@ -279,11 +169,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@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);
@@ -295,18 +181,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
R.dimen.keyguard_indication_margin_bottom);
mBurnInYOffset = getResources().getDimensionPixelSize(
R.dimen.default_burn_in_prevention_offset);
updateCameraVisibility();
mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mKeyguardStateController.addCallback(this);
mKeyguardStateController.addCallback(mKeyguardStateCallback);
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);
@@ -315,51 +194,18 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
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);
getContext().registerReceiverAsUser(mDevicePolicyReceiver,
UserHandle.ALL, filter, null, null);
mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
mKeyguardStateController.addCallback(this);
mKeyguardStateController.addCallback(mKeyguardStateCallback);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mKeyguardStateController.removeCallback(this);
mAccessibilityController.removeStateChangedCallback(this);
mRightExtension.destroy();
mLeftExtension.destroy();
getContext().unregisterReceiver(mDevicePolicyReceiver);
mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
mKeyguardStateController.removeCallback(mKeyguardStateCallback);
if (mQuickAccessWalletController != null) {
mQuickAccessWalletController.unregisterWalletChangeObservers(
@@ -378,11 +224,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
}
private void initAccessibility() {
mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -404,19 +245,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
getResources().getDimensionPixelSize(
com.android.internal.R.dimen.text_size_small_material));
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();
ViewGroup.LayoutParams 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);
@@ -439,74 +268,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
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() {
@@ -552,73 +315,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
}
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;
@@ -627,77 +323,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
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;
}
@@ -707,66 +332,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
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) {
@@ -778,13 +343,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
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) {
@@ -798,58 +356,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
.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();
@@ -888,77 +397,12 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
* 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

View File

@@ -50,8 +50,6 @@ 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;
@@ -117,6 +115,7 @@ import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.LaunchAnimator;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.camera.CameraGestureHelper;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.controls.dagger.ControlsComponent;
@@ -145,7 +144,6 @@ 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;
@@ -252,9 +250,6 @@ public class NotificationPanelViewController extends PanelViewController {
private final OnOverscrollTopChangedListener
mOnOverscrollTopChangedListener =
new OnOverscrollTopChangedListener();
private final KeyguardAffordanceHelperCallback
mKeyguardAffordanceHelperCallback =
new KeyguardAffordanceHelperCallback();
private final OnEmptySpaceClickListener
mOnEmptySpaceClickListener =
new OnEmptySpaceClickListener();
@@ -333,8 +328,6 @@ 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;
@@ -434,8 +427,6 @@ public class NotificationPanelViewController extends PanelViewController {
*/
private boolean mQsAnimatorExpand;
private boolean mIsLaunchTransitionFinished;
private boolean mIsLaunchTransitionRunning;
private Runnable mLaunchAnimationEndRunnable;
private boolean mOnlyAffordanceInThisMotion;
private ValueAnimator mQsSizeChangeAnimator;
@@ -452,10 +443,8 @@ 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);
@@ -488,7 +477,6 @@ public class NotificationPanelViewController extends PanelViewController {
private float mLinearDarkAmount;
private boolean mPulsing;
private boolean mUserSetupComplete;
private boolean mHideIconsDuringLaunchAnimation = true;
private int mStackScrollerMeasuringPass;
/**
@@ -704,6 +692,8 @@ public class NotificationPanelViewController extends PanelViewController {
}
};
private final CameraGestureHelper mCameraGestureHelper;
@Inject
public NotificationPanelViewController(NotificationPanelView view,
@Main Resources resources,
@@ -775,7 +765,8 @@ public class NotificationPanelViewController extends PanelViewController {
NotificationStackSizeCalculator notificationStackSizeCalculator,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
ShadeTransitionController shadeTransitionController,
SystemClock systemClock) {
SystemClock systemClock,
CameraGestureHelper cameraGestureHelper) {
super(view,
falsingManager,
dozeLog,
@@ -960,6 +951,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
}
});
mCameraGestureHelper = cameraGestureHelper;
}
@VisibleForTesting
@@ -1007,8 +999,6 @@ 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();
@@ -1032,7 +1022,6 @@ public class NotificationPanelViewController extends PanelViewController {
mView.setRtlChangeListener(layoutDirection -> {
if (layoutDirection != mOldLayoutDirection) {
mAffordanceHelper.onRtlPropertiesChanged();
mOldLayoutDirection = layoutDirection;
}
});
@@ -1258,7 +1247,6 @@ public class NotificationPanelViewController extends PanelViewController {
KeyguardBottomAreaView oldBottomArea = mKeyguardBottomArea;
mKeyguardBottomArea = mKeyguardBottomAreaViewControllerProvider.get().getView();
mKeyguardBottomArea.initFrom(oldBottomArea);
mKeyguardBottomArea.setPreviewContainer(mPreviewContainer);
mView.addView(mKeyguardBottomArea, index);
initBottomArea();
mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
@@ -1295,11 +1283,7 @@ 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);
@@ -1664,10 +1648,6 @@ 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()) {
@@ -2210,11 +2190,6 @@ 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) {
@@ -3377,9 +3352,6 @@ public class NotificationPanelViewController extends PanelViewController {
mQsExpandImmediate = true;
setShowShelfOnly(true);
}
if (mBarState == KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) {
mAffordanceHelper.animateHideLeftRightIcon();
}
mNotificationStackScrollLayoutController.onPanelTrackingStarted();
cancelPendingPanelCollapse();
}
@@ -3393,12 +3365,6 @@ 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.
@@ -3471,10 +3437,6 @@ public class NotificationPanelViewController extends PanelViewController {
return mIsLaunchTransitionFinished;
}
public boolean isLaunchTransitionRunning() {
return mIsLaunchTransitionRunning;
}
@Override
public void setIsLaunchAnimationRunning(boolean running) {
boolean wasRunning = mIsLaunchAnimationRunning;
@@ -3493,10 +3455,6 @@ public class NotificationPanelViewController extends PanelViewController {
}
}
public void setLaunchTransitionEndRunnable(Runnable r) {
mLaunchAnimationEndRunnable = r;
}
private void updateDozingVisibilities(boolean animate) {
mKeyguardBottomArea.setDozing(mDozing, animate);
if (!mDozing && animate) {
@@ -3675,30 +3633,13 @@ public class NotificationPanelViewController extends PanelViewController {
&& mBarState == StatusBarState.SHADE;
}
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.
/** Launches the camera. */
public void launchCamera(int source) {
if (!isFullyCollapsed()) {
setLaunchingAffordance(true);
} else {
animate = false;
}
mAffordanceHasPreview = mKeyguardBottomArea.getRightPreview() != null;
mAffordanceHelper.launchAffordance(
animate, mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
mCameraGestureHelper.launchCamera(source);
}
public void onAffordanceLaunchEnded() {
@@ -3711,9 +3652,6 @@ public class NotificationPanelViewController extends PanelViewController {
*/
private void setLaunchingAffordance(boolean launchingAffordance) {
mLaunchingAffordance = launchingAffordance;
mKeyguardAffordanceHelperCallback.getLeftIcon().setLaunchingAffordance(launchingAffordance);
mKeyguardAffordanceHelperCallback.getRightIcon().setLaunchingAffordance(
launchingAffordance);
mKeyguardBypassController.setLaunchingAffordance(launchingAffordance);
}
@@ -3721,34 +3659,14 @@ 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 && mAffordanceHasPreview;
return mLaunchingAffordance;
}
/**
* Whether the camera application can be launched for the camera launch gesture.
*/
public boolean canCameraGestureBeLaunched() {
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();
}
/**
* Return true if the applications with the package name is running in foreground.
*
* @param pkgName application package name.
*/
private boolean isForegroundApp(String pkgName) {
List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
return mCameraGestureHelper.canCameraGestureBeLaunched(mBarState);
}
public boolean hideStatusBarIconsWhenExpanded() {
@@ -3827,9 +3745,6 @@ 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);
}
@@ -3912,11 +3827,6 @@ 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;
@@ -4271,10 +4181,6 @@ 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;
}
@@ -4517,139 +4423,6 @@ 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
@@ -5104,15 +4877,6 @@ 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

View File

@@ -484,8 +484,6 @@ 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);
@@ -1333,7 +1331,7 @@ public abstract class PanelViewController {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
mGestureWaitForTouchSlop = shouldGestureWaitForTouchSlop();
mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y);
mIgnoreXTouchSlop = true;
}
switch (event.getActionMasked()) {

View File

@@ -1,150 +0,0 @@
/*
* 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<ResolveInfo> 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;
}
}

View File

@@ -848,7 +848,6 @@ 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());
@@ -885,7 +884,6 @@ 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));

View File

@@ -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,6 +51,5 @@ class KeyguardBottomAreaTest : SysuiTestCase() {
null, false) as KeyguardBottomAreaView
other.initFrom(mKeyguardBottomArea)
other.launchVoiceAssist()
}
}
}

View File

@@ -87,6 +87,7 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.camera.CameraGestureHelper;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.controls.dagger.ControlsComponent;
@@ -106,7 +107,6 @@ 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;
@@ -404,8 +404,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
.thenReturn(mHeadsUpCallback);
when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
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))
@@ -549,7 +547,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
mNotificationStackSizeCalculator,
mUnlockedScreenOffAnimationController,
mShadeTransitionController,
mSystemClock);
mSystemClock,
mock(CameraGestureHelper.class));
mNotificationPanelViewController.initDependencies(
mCentralSurfaces,
() -> {},