OSDN Git Service

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