1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.systemui.statusbar.phone; 18 19import android.app.ActivityManager; 20import android.app.ActivityManagerNative; 21import android.app.admin.DevicePolicyManager; 22import android.content.BroadcastReceiver; 23import android.content.ComponentName; 24import android.content.Context; 25import android.content.Intent; 26import android.content.IntentFilter; 27import android.content.ServiceConnection; 28import android.content.pm.ActivityInfo; 29import android.content.pm.PackageManager; 30import android.content.pm.ResolveInfo; 31import android.content.res.Configuration; 32import android.os.AsyncTask; 33import android.os.Bundle; 34import android.os.IBinder; 35import android.os.Message; 36import android.os.Messenger; 37import android.os.RemoteException; 38import android.os.UserHandle; 39import android.provider.MediaStore; 40import android.service.media.CameraPrewarmService; 41import android.telecom.TelecomManager; 42import android.util.AttributeSet; 43import android.util.Log; 44import android.util.TypedValue; 45import android.view.View; 46import android.view.ViewGroup; 47import android.view.accessibility.AccessibilityNodeInfo; 48import android.widget.FrameLayout; 49import android.widget.TextView; 50 51import com.android.internal.widget.LockPatternUtils; 52import com.android.keyguard.KeyguardUpdateMonitor; 53import com.android.keyguard.KeyguardUpdateMonitorCallback; 54import com.android.systemui.EventLogConstants; 55import com.android.systemui.EventLogTags; 56import com.android.systemui.Interpolators; 57import com.android.systemui.R; 58import com.android.systemui.assist.AssistManager; 59import com.android.systemui.statusbar.CommandQueue; 60import com.android.systemui.statusbar.KeyguardAffordanceView; 61import com.android.systemui.statusbar.KeyguardIndicationController; 62import com.android.systemui.statusbar.policy.AccessibilityController; 63import com.android.systemui.statusbar.policy.FlashlightController; 64import com.android.systemui.statusbar.policy.PreviewInflater; 65 66import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; 67import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; 68 69/** 70 * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status 71 * text. 72 */ 73public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener, 74 UnlockMethodCache.OnUnlockMethodChangedListener, 75 AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener { 76 77 final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView"; 78 79 public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance"; 80 public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture"; 81 public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap"; 82 83 public static final String EXTRA_CAMERA_LAUNCH_SOURCE 84 = "com.android.systemui.camera_launch_source"; 85 86 private static final Intent SECURE_CAMERA_INTENT = 87 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE) 88 .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 89 public static final Intent INSECURE_CAMERA_INTENT = 90 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 91 private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL); 92 private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; 93 private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; 94 95 private KeyguardAffordanceView mCameraImageView; 96 private KeyguardAffordanceView mLeftAffordanceView; 97 private LockIcon mLockIcon; 98 private TextView mIndicationText; 99 private ViewGroup mPreviewContainer; 100 101 private View mLeftPreview; 102 private View mCameraPreview; 103 104 private ActivityStarter mActivityStarter; 105 private UnlockMethodCache mUnlockMethodCache; 106 private LockPatternUtils mLockPatternUtils; 107 private FlashlightController mFlashlightController; 108 private PreviewInflater mPreviewInflater; 109 private KeyguardIndicationController mIndicationController; 110 private AccessibilityController mAccessibilityController; 111 private PhoneStatusBar mPhoneStatusBar; 112 113 private boolean mUserSetupComplete; 114 private boolean mPrewarmBound; 115 private Messenger mPrewarmMessenger; 116 private final ServiceConnection mPrewarmConnection = new ServiceConnection() { 117 118 @Override 119 public void onServiceConnected(ComponentName name, IBinder service) { 120 mPrewarmMessenger = new Messenger(service); 121 } 122 123 @Override 124 public void onServiceDisconnected(ComponentName name) { 125 mPrewarmMessenger = null; 126 } 127 }; 128 129 private boolean mLeftIsVoiceAssist; 130 private AssistManager mAssistManager; 131 132 public KeyguardBottomAreaView(Context context) { 133 this(context, null); 134 } 135 136 public KeyguardBottomAreaView(Context context, AttributeSet attrs) { 137 this(context, attrs, 0); 138 } 139 140 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) { 141 this(context, attrs, defStyleAttr, 0); 142 } 143 144 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr, 145 int defStyleRes) { 146 super(context, attrs, defStyleAttr, defStyleRes); 147 } 148 149 private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() { 150 @Override 151 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { 152 super.onInitializeAccessibilityNodeInfo(host, info); 153 String label = null; 154 if (host == mLockIcon) { 155 label = getResources().getString(R.string.unlock_label); 156 } else if (host == mCameraImageView) { 157 label = getResources().getString(R.string.camera_label); 158 } else if (host == mLeftAffordanceView) { 159 if (mLeftIsVoiceAssist) { 160 label = getResources().getString(R.string.voice_assist_label); 161 } else { 162 label = getResources().getString(R.string.phone_label); 163 } 164 } 165 info.addAction(new AccessibilityAction(ACTION_CLICK, label)); 166 } 167 168 @Override 169 public boolean performAccessibilityAction(View host, int action, Bundle args) { 170 if (action == ACTION_CLICK) { 171 if (host == mLockIcon) { 172 mPhoneStatusBar.animateCollapsePanels( 173 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); 174 return true; 175 } else if (host == mCameraImageView) { 176 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE); 177 return true; 178 } else if (host == mLeftAffordanceView) { 179 launchLeftAffordance(); 180 return true; 181 } 182 } 183 return super.performAccessibilityAction(host, action, args); 184 } 185 }; 186 187 @Override 188 protected void onFinishInflate() { 189 super.onFinishInflate(); 190 mLockPatternUtils = new LockPatternUtils(mContext); 191 mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container); 192 mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button); 193 mLeftAffordanceView = (KeyguardAffordanceView) findViewById(R.id.left_button); 194 mLockIcon = (LockIcon) findViewById(R.id.lock_icon); 195 mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text); 196 watchForCameraPolicyChanges(); 197 updateCameraVisibility(); 198 mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); 199 mUnlockMethodCache.addListener(this); 200 mLockIcon.update(); 201 setClipChildren(false); 202 setClipToPadding(false); 203 mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext)); 204 inflateCameraPreview(); 205 mLockIcon.setOnClickListener(this); 206 mLockIcon.setOnLongClickListener(this); 207 mCameraImageView.setOnClickListener(this); 208 mLeftAffordanceView.setOnClickListener(this); 209 initAccessibility(); 210 } 211 212 private void initAccessibility() { 213 mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate); 214 mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate); 215 mCameraImageView.setAccessibilityDelegate(mAccessibilityDelegate); 216 } 217 218 @Override 219 protected void onConfigurationChanged(Configuration newConfig) { 220 super.onConfigurationChanged(newConfig); 221 int indicationBottomMargin = getResources().getDimensionPixelSize( 222 R.dimen.keyguard_indication_margin_bottom); 223 MarginLayoutParams mlp = (MarginLayoutParams) mIndicationText.getLayoutParams(); 224 if (mlp.bottomMargin != indicationBottomMargin) { 225 mlp.bottomMargin = indicationBottomMargin; 226 mIndicationText.setLayoutParams(mlp); 227 } 228 229 // Respect font size setting. 230 mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX, 231 getResources().getDimensionPixelSize( 232 com.android.internal.R.dimen.text_size_small_material)); 233 234 ViewGroup.LayoutParams lp = mCameraImageView.getLayoutParams(); 235 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width); 236 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height); 237 mCameraImageView.setLayoutParams(lp); 238 mCameraImageView.setImageDrawable(mContext.getDrawable(R.drawable.ic_camera_alt_24dp)); 239 240 lp = mLockIcon.getLayoutParams(); 241 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width); 242 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height); 243 mLockIcon.setLayoutParams(lp); 244 mLockIcon.update(true /* force */); 245 246 lp = mLeftAffordanceView.getLayoutParams(); 247 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width); 248 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height); 249 mLeftAffordanceView.setLayoutParams(lp); 250 updateLeftAffordanceIcon(); 251 } 252 253 public void setActivityStarter(ActivityStarter activityStarter) { 254 mActivityStarter = activityStarter; 255 } 256 257 public void setFlashlightController(FlashlightController flashlightController) { 258 mFlashlightController = flashlightController; 259 } 260 261 public void setAccessibilityController(AccessibilityController accessibilityController) { 262 mAccessibilityController = accessibilityController; 263 mLockIcon.setAccessibilityController(accessibilityController); 264 accessibilityController.addStateChangedCallback(this); 265 } 266 267 public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) { 268 mPhoneStatusBar = phoneStatusBar; 269 updateCameraVisibility(); // in case onFinishInflate() was called too early 270 } 271 272 public void setUserSetupComplete(boolean userSetupComplete) { 273 mUserSetupComplete = userSetupComplete; 274 updateCameraVisibility(); 275 updateLeftAffordanceIcon(); 276 } 277 278 private Intent getCameraIntent() { 279 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); 280 boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer( 281 KeyguardUpdateMonitor.getCurrentUser()); 282 boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()); 283 return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT; 284 } 285 286 /** 287 * Resolves the intent to launch the camera application. 288 */ 289 public ResolveInfo resolveCameraIntent() { 290 return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(), 291 PackageManager.MATCH_DEFAULT_ONLY, 292 KeyguardUpdateMonitor.getCurrentUser()); 293 } 294 295 private void updateCameraVisibility() { 296 if (mCameraImageView == null) { 297 // Things are not set up yet; reply hazy, ask again later 298 return; 299 } 300 ResolveInfo resolved = resolveCameraIntent(); 301 boolean visible = !isCameraDisabledByDpm() && resolved != null 302 && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance) 303 && mUserSetupComplete; 304 mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE); 305 } 306 307 private void updateLeftAffordanceIcon() { 308 mLeftIsVoiceAssist = canLaunchVoiceAssist(); 309 int drawableId; 310 int contentDescription; 311 boolean visible = mUserSetupComplete; 312 if (mLeftIsVoiceAssist) { 313 drawableId = R.drawable.ic_mic_26dp; 314 contentDescription = R.string.accessibility_voice_assist_button; 315 } else { 316 visible &= isPhoneVisible(); 317 drawableId = R.drawable.ic_phone_24dp; 318 contentDescription = R.string.accessibility_phone_button; 319 } 320 mLeftAffordanceView.setVisibility(visible ? View.VISIBLE : View.GONE); 321 mLeftAffordanceView.setImageDrawable(mContext.getDrawable(drawableId)); 322 mLeftAffordanceView.setContentDescription(mContext.getString(contentDescription)); 323 } 324 325 public boolean isLeftVoiceAssist() { 326 return mLeftIsVoiceAssist; 327 } 328 329 private boolean isPhoneVisible() { 330 PackageManager pm = mContext.getPackageManager(); 331 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) 332 && pm.resolveActivity(PHONE_INTENT, 0) != null; 333 } 334 335 private boolean isCameraDisabledByDpm() { 336 final DevicePolicyManager dpm = 337 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE); 338 if (dpm != null && mPhoneStatusBar != null) { 339 try { 340 final int userId = ActivityManagerNative.getDefault().getCurrentUser().id; 341 final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId); 342 final boolean disabledBecauseKeyguardSecure = 343 (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0 344 && mPhoneStatusBar.isKeyguardSecure(); 345 return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure; 346 } catch (RemoteException e) { 347 Log.e(TAG, "Can't get userId", e); 348 } 349 } 350 return false; 351 } 352 353 private void watchForCameraPolicyChanges() { 354 final IntentFilter filter = new IntentFilter(); 355 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 356 getContext().registerReceiverAsUser(mDevicePolicyReceiver, 357 UserHandle.ALL, filter, null, null); 358 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback); 359 } 360 361 @Override 362 public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) { 363 mCameraImageView.setClickable(touchExplorationEnabled); 364 mLeftAffordanceView.setClickable(touchExplorationEnabled); 365 mCameraImageView.setFocusable(accessibilityEnabled); 366 mLeftAffordanceView.setFocusable(accessibilityEnabled); 367 mLockIcon.update(); 368 } 369 370 @Override 371 public void onClick(View v) { 372 if (v == mCameraImageView) { 373 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE); 374 } else if (v == mLeftAffordanceView) { 375 launchLeftAffordance(); 376 } if (v == mLockIcon) { 377 if (!mAccessibilityController.isAccessibilityEnabled()) { 378 handleTrustCircleClick(); 379 } else { 380 mPhoneStatusBar.animateCollapsePanels( 381 CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); 382 } 383 } 384 } 385 386 @Override 387 public boolean onLongClick(View v) { 388 handleTrustCircleClick(); 389 return true; 390 } 391 392 private void handleTrustCircleClick() { 393 EventLogTags.writeSysuiLockscreenGesture( 394 EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK, 0 /* lengthDp - N/A */, 395 0 /* velocityDp - N/A */); 396 mIndicationController.showTransientIndication( 397 R.string.keyguard_indication_trust_disabled); 398 mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser()); 399 } 400 401 public void bindCameraPrewarmService() { 402 Intent intent = getCameraIntent(); 403 ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent, 404 KeyguardUpdateMonitor.getCurrentUser()); 405 if (targetInfo != null && targetInfo.metaData != null) { 406 String clazz = targetInfo.metaData.getString( 407 MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE); 408 if (clazz != null) { 409 Intent serviceIntent = new Intent(); 410 serviceIntent.setClassName(targetInfo.packageName, clazz); 411 serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM); 412 try { 413 if (getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection, 414 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, 415 new UserHandle(UserHandle.USER_CURRENT))) { 416 mPrewarmBound = true; 417 } 418 } catch (SecurityException e) { 419 Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName 420 + " class=" + clazz, e); 421 } 422 } 423 } 424 } 425 426 public void unbindCameraPrewarmService(boolean launched) { 427 if (mPrewarmBound) { 428 if (mPrewarmMessenger != null && launched) { 429 try { 430 mPrewarmMessenger.send(Message.obtain(null /* handler */, 431 CameraPrewarmService.MSG_CAMERA_FIRED)); 432 } catch (RemoteException e) { 433 Log.w(TAG, "Error sending camera fired message", e); 434 } 435 } 436 mContext.unbindService(mPrewarmConnection); 437 mPrewarmBound = false; 438 } 439 } 440 441 public void launchCamera(String source) { 442 final Intent intent = getCameraIntent(); 443 intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source); 444 boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity( 445 mContext, intent, KeyguardUpdateMonitor.getCurrentUser()); 446 if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) { 447 AsyncTask.execute(new Runnable() { 448 @Override 449 public void run() { 450 int result = ActivityManager.START_CANCELED; 451 try { 452 result = ActivityManagerNative.getDefault().startActivityAsUser( 453 null, getContext().getBasePackageName(), 454 intent, 455 intent.resolveTypeIfNeeded(getContext().getContentResolver()), 456 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, 457 UserHandle.CURRENT.getIdentifier()); 458 } catch (RemoteException e) { 459 Log.w(TAG, "Unable to start camera activity", e); 460 } 461 mActivityStarter.preventNextAnimation(); 462 final boolean launched = isSuccessfulLaunch(result); 463 post(new Runnable() { 464 @Override 465 public void run() { 466 unbindCameraPrewarmService(launched); 467 } 468 }); 469 } 470 }); 471 } else { 472 473 // We need to delay starting the activity because ResolverActivity finishes itself if 474 // launched behind lockscreen. 475 mActivityStarter.startActivity(intent, false /* dismissShade */, 476 new ActivityStarter.Callback() { 477 @Override 478 public void onActivityStarted(int resultCode) { 479 unbindCameraPrewarmService(isSuccessfulLaunch(resultCode)); 480 } 481 }); 482 } 483 } 484 485 private static boolean isSuccessfulLaunch(int result) { 486 return result == ActivityManager.START_SUCCESS 487 || result == ActivityManager.START_DELIVERED_TO_TOP 488 || result == ActivityManager.START_TASK_TO_FRONT; 489 } 490 491 public void launchLeftAffordance() { 492 if (mLeftIsVoiceAssist) { 493 launchVoiceAssist(); 494 } else { 495 launchPhone(); 496 } 497 } 498 499 private void launchVoiceAssist() { 500 Runnable runnable = new Runnable() { 501 @Override 502 public void run() { 503 mAssistManager.launchVoiceAssistFromKeyguard(); 504 mActivityStarter.preventNextAnimation(); 505 } 506 }; 507 if (mPhoneStatusBar.isKeyguardCurrentlySecure()) { 508 AsyncTask.execute(runnable); 509 } else { 510 mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */, 511 false /* dismissShade */, false /* afterKeyguardGone */, true /* deferred */); 512 } 513 } 514 515 private boolean canLaunchVoiceAssist() { 516 return mAssistManager.canVoiceAssistBeLaunchedFromKeyguard(); 517 } 518 519 private void launchPhone() { 520 final TelecomManager tm = TelecomManager.from(mContext); 521 if (tm.isInCall()) { 522 AsyncTask.execute(new Runnable() { 523 @Override 524 public void run() { 525 tm.showInCallScreen(false /* showDialpad */); 526 } 527 }); 528 } else { 529 mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */); 530 } 531 } 532 533 534 @Override 535 protected void onVisibilityChanged(View changedView, int visibility) { 536 super.onVisibilityChanged(changedView, visibility); 537 if (changedView == this && visibility == VISIBLE) { 538 mLockIcon.update(); 539 updateCameraVisibility(); 540 } 541 } 542 543 public KeyguardAffordanceView getLeftView() { 544 return mLeftAffordanceView; 545 } 546 547 public KeyguardAffordanceView getRightView() { 548 return mCameraImageView; 549 } 550 551 public View getLeftPreview() { 552 return mLeftPreview; 553 } 554 555 public View getRightPreview() { 556 return mCameraPreview; 557 } 558 559 public LockIcon getLockIcon() { 560 return mLockIcon; 561 } 562 563 public View getIndicationView() { 564 return mIndicationText; 565 } 566 567 @Override 568 public boolean hasOverlappingRendering() { 569 return false; 570 } 571 572 @Override 573 public void onUnlockMethodStateChanged() { 574 mLockIcon.update(); 575 updateCameraVisibility(); 576 } 577 578 private void inflateCameraPreview() { 579 mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent()); 580 if (mCameraPreview != null) { 581 mPreviewContainer.addView(mCameraPreview); 582 mCameraPreview.setVisibility(View.INVISIBLE); 583 } 584 } 585 586 private void updateLeftPreview() { 587 View previewBefore = mLeftPreview; 588 if (previewBefore != null) { 589 mPreviewContainer.removeView(previewBefore); 590 } 591 if (mLeftIsVoiceAssist) { 592 mLeftPreview = mPreviewInflater.inflatePreviewFromService( 593 mAssistManager.getVoiceInteractorComponentName()); 594 } else { 595 mLeftPreview = mPreviewInflater.inflatePreview(PHONE_INTENT); 596 } 597 if (mLeftPreview != null) { 598 mPreviewContainer.addView(mLeftPreview); 599 mLeftPreview.setVisibility(View.INVISIBLE); 600 } 601 } 602 603 public void startFinishDozeAnimation() { 604 long delay = 0; 605 if (mLeftAffordanceView.getVisibility() == View.VISIBLE) { 606 startFinishDozeAnimationElement(mLeftAffordanceView, delay); 607 delay += DOZE_ANIMATION_STAGGER_DELAY; 608 } 609 startFinishDozeAnimationElement(mLockIcon, delay); 610 delay += DOZE_ANIMATION_STAGGER_DELAY; 611 if (mCameraImageView.getVisibility() == View.VISIBLE) { 612 startFinishDozeAnimationElement(mCameraImageView, delay); 613 } 614 mIndicationText.setAlpha(0f); 615 mIndicationText.animate() 616 .alpha(1f) 617 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) 618 .setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION); 619 } 620 621 private void startFinishDozeAnimationElement(View element, long delay) { 622 element.setAlpha(0f); 623 element.setTranslationY(element.getHeight() / 2); 624 element.animate() 625 .alpha(1f) 626 .translationY(0f) 627 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) 628 .setStartDelay(delay) 629 .setDuration(DOZE_ANIMATION_ELEMENT_DURATION); 630 } 631 632 private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { 633 @Override 634 public void onReceive(Context context, Intent intent) { 635 post(new Runnable() { 636 @Override 637 public void run() { 638 updateCameraVisibility(); 639 } 640 }); 641 } 642 }; 643 644 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = 645 new KeyguardUpdateMonitorCallback() { 646 @Override 647 public void onUserSwitchComplete(int userId) { 648 updateCameraVisibility(); 649 } 650 651 @Override 652 public void onStartedWakingUp() { 653 mLockIcon.setDeviceInteractive(true); 654 } 655 656 @Override 657 public void onFinishedGoingToSleep(int why) { 658 mLockIcon.setDeviceInteractive(false); 659 } 660 661 @Override 662 public void onScreenTurnedOn() { 663 mLockIcon.setScreenOn(true); 664 } 665 666 @Override 667 public void onScreenTurnedOff() { 668 mLockIcon.setScreenOn(false); 669 } 670 671 @Override 672 public void onKeyguardVisibilityChanged(boolean showing) { 673 mLockIcon.update(); 674 } 675 676 @Override 677 public void onFingerprintRunningStateChanged(boolean running) { 678 mLockIcon.update(); 679 } 680 681 @Override 682 public void onStrongAuthStateChanged(int userId) { 683 mLockIcon.update(); 684 } 685 }; 686 687 public void setKeyguardIndicationController( 688 KeyguardIndicationController keyguardIndicationController) { 689 mIndicationController = keyguardIndicationController; 690 } 691 692 public void setAssistManager(AssistManager assistManager) { 693 mAssistManager = assistManager; 694 updateLeftAffordance(); 695 } 696 697 public void updateLeftAffordance() { 698 updateLeftAffordanceIcon(); 699 updateLeftPreview(); 700 } 701} 702