OSDN Git Service

Merge \\\\"DO NOT MERGE Disable app pinning when emergency call button pressed\\...
[android-x86/frameworks-base.git] / packages / SystemUI / src / com / android / systemui / statusbar / phone / KeyguardBottomAreaView.java
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
17 package com.android.systemui.statusbar.phone;
18
19 import android.app.ActivityManager;
20 import android.app.ActivityManagerNative;
21 import android.app.admin.DevicePolicyManager;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.ServiceConnection;
28 import android.content.pm.ActivityInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.ResolveInfo;
31 import android.content.res.Configuration;
32 import android.os.AsyncTask;
33 import android.os.Bundle;
34 import android.os.IBinder;
35 import android.os.Message;
36 import android.os.Messenger;
37 import android.os.RemoteException;
38 import android.os.UserHandle;
39 import android.provider.MediaStore;
40 import android.service.media.CameraPrewarmService;
41 import android.telecom.TelecomManager;
42 import android.util.AttributeSet;
43 import android.util.Log;
44 import android.util.TypedValue;
45 import android.view.View;
46 import android.view.ViewGroup;
47 import android.view.accessibility.AccessibilityNodeInfo;
48 import android.widget.FrameLayout;
49 import android.widget.TextView;
50
51 import com.android.internal.widget.LockPatternUtils;
52 import com.android.keyguard.KeyguardUpdateMonitor;
53 import com.android.keyguard.KeyguardUpdateMonitorCallback;
54 import com.android.systemui.EventLogConstants;
55 import com.android.systemui.EventLogTags;
56 import com.android.systemui.Interpolators;
57 import com.android.systemui.R;
58 import com.android.systemui.assist.AssistManager;
59 import com.android.systemui.statusbar.CommandQueue;
60 import com.android.systemui.statusbar.KeyguardAffordanceView;
61 import com.android.systemui.statusbar.KeyguardIndicationController;
62 import com.android.systemui.statusbar.policy.AccessibilityController;
63 import com.android.systemui.statusbar.policy.FlashlightController;
64 import com.android.systemui.statusbar.policy.PreviewInflater;
65
66 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
67 import 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  */
73 public 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 }