OSDN Git Service

4d0e5d34761b68c8a47876b52877d4901a2b663b
[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 static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
20 import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
21
22 import android.app.ActivityManager;
23 import android.app.ActivityManagerNative;
24 import android.app.ActivityOptions;
25 import android.app.admin.DevicePolicyManager;
26 import android.content.BroadcastReceiver;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.content.ServiceConnection;
32 import android.content.pm.ActivityInfo;
33 import android.content.pm.PackageManager;
34 import android.content.pm.ResolveInfo;
35 import android.content.res.Configuration;
36 import android.os.AsyncTask;
37 import android.os.Bundle;
38 import android.os.IBinder;
39 import android.os.Message;
40 import android.os.Messenger;
41 import android.os.RemoteException;
42 import android.os.UserHandle;
43 import android.provider.MediaStore;
44 import android.service.media.CameraPrewarmService;
45 import android.telecom.TelecomManager;
46 import android.util.AttributeSet;
47 import android.util.Log;
48 import android.util.TypedValue;
49 import android.view.View;
50 import android.view.ViewGroup;
51 import android.view.WindowManager;
52 import android.view.accessibility.AccessibilityNodeInfo;
53 import android.widget.FrameLayout;
54 import android.widget.TextView;
55
56 import com.android.internal.widget.LockPatternUtils;
57 import com.android.keyguard.KeyguardUpdateMonitor;
58 import com.android.keyguard.KeyguardUpdateMonitorCallback;
59 import com.android.systemui.EventLogConstants;
60 import com.android.systemui.EventLogTags;
61 import com.android.systemui.Interpolators;
62 import com.android.systemui.R;
63 import com.android.systemui.assist.AssistManager;
64 import com.android.systemui.statusbar.CommandQueue;
65 import com.android.systemui.statusbar.KeyguardAffordanceView;
66 import com.android.systemui.statusbar.KeyguardIndicationController;
67 import com.android.systemui.statusbar.policy.AccessibilityController;
68 import com.android.systemui.statusbar.policy.FlashlightController;
69 import com.android.systemui.statusbar.policy.PreviewInflater;
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 KeyguardAffordanceView mCameraImageView;
98     private KeyguardAffordanceView mLeftAffordanceView;
99     private LockIcon mLockIcon;
100     private TextView mIndicationText;
101     private ViewGroup mPreviewContainer;
102
103     private View mLeftPreview;
104     private View mCameraPreview;
105
106     private ActivityStarter mActivityStarter;
107     private UnlockMethodCache mUnlockMethodCache;
108     private LockPatternUtils mLockPatternUtils;
109     private FlashlightController mFlashlightController;
110     private PreviewInflater mPreviewInflater;
111     private KeyguardIndicationController mIndicationController;
112     private AccessibilityController mAccessibilityController;
113     private PhoneStatusBar mPhoneStatusBar;
114     private KeyguardAffordanceHelper mAffordanceHelper;
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         mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
196         mLeftAffordanceView = (KeyguardAffordanceView) findViewById(R.id.left_button);
197         mLockIcon = (LockIcon) findViewById(R.id.lock_icon);
198         mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
199         watchForCameraPolicyChanges();
200         updateCameraVisibility();
201         mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
202         mUnlockMethodCache.addListener(this);
203         mLockIcon.update();
204         setClipChildren(false);
205         setClipToPadding(false);
206         mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
207         inflateCameraPreview();
208         mLockIcon.setOnClickListener(this);
209         mLockIcon.setOnLongClickListener(this);
210         mCameraImageView.setOnClickListener(this);
211         mLeftAffordanceView.setOnClickListener(this);
212         initAccessibility();
213     }
214
215     private void initAccessibility() {
216         mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
217         mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
218         mCameraImageView.setAccessibilityDelegate(mAccessibilityDelegate);
219     }
220
221     @Override
222     protected void onConfigurationChanged(Configuration newConfig) {
223         super.onConfigurationChanged(newConfig);
224         int indicationBottomMargin = getResources().getDimensionPixelSize(
225                 R.dimen.keyguard_indication_margin_bottom);
226         MarginLayoutParams mlp = (MarginLayoutParams) mIndicationText.getLayoutParams();
227         if (mlp.bottomMargin != indicationBottomMargin) {
228             mlp.bottomMargin = indicationBottomMargin;
229             mIndicationText.setLayoutParams(mlp);
230         }
231
232         // Respect font size setting.
233         mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
234                 getResources().getDimensionPixelSize(
235                         com.android.internal.R.dimen.text_size_small_material));
236
237         ViewGroup.LayoutParams lp = mCameraImageView.getLayoutParams();
238         lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
239         lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
240         mCameraImageView.setLayoutParams(lp);
241         mCameraImageView.setImageDrawable(mContext.getDrawable(R.drawable.ic_camera_alt_24dp));
242
243         lp = mLockIcon.getLayoutParams();
244         lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
245         lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
246         mLockIcon.setLayoutParams(lp);
247         mLockIcon.update(true /* force */);
248
249         lp = mLeftAffordanceView.getLayoutParams();
250         lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
251         lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
252         mLeftAffordanceView.setLayoutParams(lp);
253         updateLeftAffordanceIcon();
254     }
255
256     public void setActivityStarter(ActivityStarter activityStarter) {
257         mActivityStarter = activityStarter;
258     }
259
260     public void setFlashlightController(FlashlightController flashlightController) {
261         mFlashlightController = flashlightController;
262     }
263
264     public void setAccessibilityController(AccessibilityController accessibilityController) {
265         mAccessibilityController = accessibilityController;
266         mLockIcon.setAccessibilityController(accessibilityController);
267         accessibilityController.addStateChangedCallback(this);
268     }
269
270     public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) {
271         mPhoneStatusBar = phoneStatusBar;
272         updateCameraVisibility(); // in case onFinishInflate() was called too early
273     }
274
275     public void setAffordanceHelper(KeyguardAffordanceHelper affordanceHelper) {
276         mAffordanceHelper = affordanceHelper;
277     }
278
279     public void setUserSetupComplete(boolean userSetupComplete) {
280         mUserSetupComplete = userSetupComplete;
281         updateCameraVisibility();
282         updateLeftAffordanceIcon();
283     }
284
285     private Intent getCameraIntent() {
286         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
287         boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer(
288                 KeyguardUpdateMonitor.getCurrentUser());
289         boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
290         return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
291     }
292
293     /**
294      * Resolves the intent to launch the camera application.
295      */
296     public ResolveInfo resolveCameraIntent() {
297         return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
298                 PackageManager.MATCH_DEFAULT_ONLY,
299                 KeyguardUpdateMonitor.getCurrentUser());
300     }
301
302     private void updateCameraVisibility() {
303         if (mCameraImageView == null) {
304             // Things are not set up yet; reply hazy, ask again later
305             return;
306         }
307         ResolveInfo resolved = resolveCameraIntent();
308         boolean visible = !isCameraDisabledByDpm() && resolved != null
309                 && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
310                 && mUserSetupComplete;
311         mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
312     }
313
314     private void updateLeftAffordanceIcon() {
315         mLeftIsVoiceAssist = canLaunchVoiceAssist();
316         int drawableId;
317         int contentDescription;
318         boolean visible = mUserSetupComplete;
319         if (mLeftIsVoiceAssist) {
320             drawableId = R.drawable.ic_mic_26dp;
321             contentDescription = R.string.accessibility_voice_assist_button;
322         } else {
323             visible &= isPhoneVisible();
324             drawableId = R.drawable.ic_phone_24dp;
325             contentDescription = R.string.accessibility_phone_button;
326         }
327         mLeftAffordanceView.setVisibility(visible ? View.VISIBLE : View.GONE);
328         mLeftAffordanceView.setImageDrawable(mContext.getDrawable(drawableId));
329         mLeftAffordanceView.setContentDescription(mContext.getString(contentDescription));
330     }
331
332     public boolean isLeftVoiceAssist() {
333         return mLeftIsVoiceAssist;
334     }
335
336     private boolean isPhoneVisible() {
337         PackageManager pm = mContext.getPackageManager();
338         return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
339                 && pm.resolveActivity(PHONE_INTENT, 0) != null;
340     }
341
342     private boolean isCameraDisabledByDpm() {
343         final DevicePolicyManager dpm =
344                 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
345         if (dpm != null && mPhoneStatusBar != null) {
346             try {
347                 final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
348                 final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
349                 final  boolean disabledBecauseKeyguardSecure =
350                         (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
351                                 && mPhoneStatusBar.isKeyguardSecure();
352                 return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
353             } catch (RemoteException e) {
354                 Log.e(TAG, "Can't get userId", e);
355             }
356         }
357         return false;
358     }
359
360     private void watchForCameraPolicyChanges() {
361         final IntentFilter filter = new IntentFilter();
362         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
363         getContext().registerReceiverAsUser(mDevicePolicyReceiver,
364                 UserHandle.ALL, filter, null, null);
365         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
366     }
367
368     @Override
369     public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
370         mCameraImageView.setClickable(touchExplorationEnabled);
371         mLeftAffordanceView.setClickable(touchExplorationEnabled);
372         mCameraImageView.setFocusable(accessibilityEnabled);
373         mLeftAffordanceView.setFocusable(accessibilityEnabled);
374         mLockIcon.update();
375     }
376
377     @Override
378     public void onClick(View v) {
379         if (v == mCameraImageView) {
380             launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
381         } else if (v == mLeftAffordanceView) {
382             launchLeftAffordance();
383         } if (v == mLockIcon) {
384             if (!mAccessibilityController.isAccessibilityEnabled()) {
385                 handleTrustCircleClick();
386             } else {
387                 mPhoneStatusBar.animateCollapsePanels(
388                         CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
389             }
390         }
391     }
392
393     @Override
394     public boolean onLongClick(View v) {
395         handleTrustCircleClick();
396         return true;
397     }
398
399     private void handleTrustCircleClick() {
400         EventLogTags.writeSysuiLockscreenGesture(
401                 EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK, 0 /* lengthDp - N/A */,
402                 0 /* velocityDp - N/A */);
403         mIndicationController.showTransientIndication(
404                 R.string.keyguard_indication_trust_disabled);
405         mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
406     }
407
408     public void bindCameraPrewarmService() {
409         Intent intent = getCameraIntent();
410         ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent,
411                 KeyguardUpdateMonitor.getCurrentUser(), true /* onlyDirectBootAware */);
412         if (targetInfo != null && targetInfo.metaData != null) {
413             String clazz = targetInfo.metaData.getString(
414                     MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE);
415             if (clazz != null) {
416                 Intent serviceIntent = new Intent();
417                 serviceIntent.setClassName(targetInfo.packageName, clazz);
418                 serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM);
419                 try {
420                     if (getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection,
421                             Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
422                             new UserHandle(UserHandle.USER_CURRENT))) {
423                         mPrewarmBound = true;
424                     }
425                 } catch (SecurityException e) {
426                     Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName
427                             + " class=" + clazz, e);
428                 }
429             }
430         }
431     }
432
433     public void unbindCameraPrewarmService(boolean launched) {
434         if (mPrewarmBound) {
435             if (mPrewarmMessenger != null && launched) {
436                 try {
437                     mPrewarmMessenger.send(Message.obtain(null /* handler */,
438                             CameraPrewarmService.MSG_CAMERA_FIRED));
439                 } catch (RemoteException e) {
440                     Log.w(TAG, "Error sending camera fired message", e);
441                 }
442             }
443             mContext.unbindService(mPrewarmConnection);
444             mPrewarmBound = false;
445         }
446     }
447
448     public void launchCamera(String source) {
449         final Intent intent = getCameraIntent();
450         intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
451         boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
452                 mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
453         if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
454             AsyncTask.execute(new Runnable() {
455                 @Override
456                 public void run() {
457                     int result = ActivityManager.START_CANCELED;
458
459                     // Normally an activity will set it's requested rotation
460                     // animation on its window. However when launching an activity
461                     // causes the orientation to change this is too late. In these cases
462                     // the default animation is used. This doesn't look good for
463                     // the camera (as it rotates the camera contents out of sync
464                     // with physical reality). So, we ask the WindowManager to
465                     // force the crossfade animation if an orientation change
466                     // happens to occur during the launch.
467                     ActivityOptions o = ActivityOptions.makeBasic();
468                     o.setRotationAnimationHint(
469                             WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
470                     try {
471                         result = ActivityManagerNative.getDefault().startActivityAsUser(
472                                 null, getContext().getBasePackageName(),
473                                 intent,
474                                 intent.resolveTypeIfNeeded(getContext().getContentResolver()),
475                                 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, o.toBundle(),
476                                 UserHandle.CURRENT.getIdentifier());
477                     } catch (RemoteException e) {
478                         Log.w(TAG, "Unable to start camera activity", e);
479                     }
480                     mActivityStarter.preventNextAnimation();
481                     final boolean launched = isSuccessfulLaunch(result);
482                     post(new Runnable() {
483                         @Override
484                         public void run() {
485                             unbindCameraPrewarmService(launched);
486                         }
487                     });
488                 }
489             });
490         } else {
491
492             // We need to delay starting the activity because ResolverActivity finishes itself if
493             // launched behind lockscreen.
494             mActivityStarter.startActivity(intent, false /* dismissShade */,
495                     new ActivityStarter.Callback() {
496                         @Override
497                         public void onActivityStarted(int resultCode) {
498                             unbindCameraPrewarmService(isSuccessfulLaunch(resultCode));
499                         }
500                     });
501         }
502     }
503
504     private static boolean isSuccessfulLaunch(int result) {
505         return result == ActivityManager.START_SUCCESS
506                 || result == ActivityManager.START_DELIVERED_TO_TOP
507                 || result == ActivityManager.START_TASK_TO_FRONT;
508     }
509
510     public void launchLeftAffordance() {
511         if (mLeftIsVoiceAssist) {
512             launchVoiceAssist();
513         } else {
514             launchPhone();
515         }
516     }
517
518     private void launchVoiceAssist() {
519         Runnable runnable = new Runnable() {
520             @Override
521             public void run() {
522                 mAssistManager.launchVoiceAssistFromKeyguard();
523                 mActivityStarter.preventNextAnimation();
524             }
525         };
526         if (mPhoneStatusBar.isKeyguardCurrentlySecure()) {
527             AsyncTask.execute(runnable);
528         } else {
529             mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
530                     false /* dismissShade */, false /* afterKeyguardGone */, true /* deferred */);
531         }
532     }
533
534     private boolean canLaunchVoiceAssist() {
535         return mAssistManager.canVoiceAssistBeLaunchedFromKeyguard();
536     }
537
538     private void launchPhone() {
539         final TelecomManager tm = TelecomManager.from(mContext);
540         if (tm.isInCall()) {
541             AsyncTask.execute(new Runnable() {
542                 @Override
543                 public void run() {
544                     tm.showInCallScreen(false /* showDialpad */);
545                 }
546             });
547         } else {
548             mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
549         }
550     }
551
552
553     @Override
554     protected void onVisibilityChanged(View changedView, int visibility) {
555         super.onVisibilityChanged(changedView, visibility);
556         if (changedView == this && visibility == VISIBLE) {
557             mLockIcon.update();
558             updateCameraVisibility();
559         }
560     }
561
562     public KeyguardAffordanceView getLeftView() {
563         return mLeftAffordanceView;
564     }
565
566     public KeyguardAffordanceView getRightView() {
567         return mCameraImageView;
568     }
569
570     public View getLeftPreview() {
571         return mLeftPreview;
572     }
573
574     public View getRightPreview() {
575         return mCameraPreview;
576     }
577
578     public LockIcon getLockIcon() {
579         return mLockIcon;
580     }
581
582     public View getIndicationView() {
583         return mIndicationText;
584     }
585
586     @Override
587     public boolean hasOverlappingRendering() {
588         return false;
589     }
590
591     @Override
592     public void onUnlockMethodStateChanged() {
593         mLockIcon.update();
594         updateCameraVisibility();
595     }
596
597     private void inflateCameraPreview() {
598         View previewBefore = mCameraPreview;
599         boolean visibleBefore = false;
600         if (previewBefore != null) {
601             mPreviewContainer.removeView(previewBefore);
602             visibleBefore = previewBefore.getVisibility() == View.VISIBLE;
603         }
604         mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
605         if (mCameraPreview != null) {
606             mPreviewContainer.addView(mCameraPreview);
607             mCameraPreview.setVisibility(visibleBefore ? View.VISIBLE : View.INVISIBLE);
608         }
609         if (mAffordanceHelper != null) {
610             mAffordanceHelper.updatePreviews();
611         }
612     }
613
614     private void updateLeftPreview() {
615         View previewBefore = mLeftPreview;
616         if (previewBefore != null) {
617             mPreviewContainer.removeView(previewBefore);
618         }
619         if (mLeftIsVoiceAssist) {
620             mLeftPreview = mPreviewInflater.inflatePreviewFromService(
621                     mAssistManager.getVoiceInteractorComponentName());
622         } else {
623             mLeftPreview = mPreviewInflater.inflatePreview(PHONE_INTENT);
624         }
625         if (mLeftPreview != null) {
626             mPreviewContainer.addView(mLeftPreview);
627             mLeftPreview.setVisibility(View.INVISIBLE);
628         }
629         if (mAffordanceHelper != null) {
630             mAffordanceHelper.updatePreviews();
631         }
632     }
633
634     public void startFinishDozeAnimation() {
635         long delay = 0;
636         if (mLeftAffordanceView.getVisibility() == View.VISIBLE) {
637             startFinishDozeAnimationElement(mLeftAffordanceView, delay);
638             delay += DOZE_ANIMATION_STAGGER_DELAY;
639         }
640         startFinishDozeAnimationElement(mLockIcon, delay);
641         delay += DOZE_ANIMATION_STAGGER_DELAY;
642         if (mCameraImageView.getVisibility() == View.VISIBLE) {
643             startFinishDozeAnimationElement(mCameraImageView, delay);
644         }
645         mIndicationText.setAlpha(0f);
646         mIndicationText.animate()
647                 .alpha(1f)
648                 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
649                 .setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
650     }
651
652     private void startFinishDozeAnimationElement(View element, long delay) {
653         element.setAlpha(0f);
654         element.setTranslationY(element.getHeight() / 2);
655         element.animate()
656                 .alpha(1f)
657                 .translationY(0f)
658                 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
659                 .setStartDelay(delay)
660                 .setDuration(DOZE_ANIMATION_ELEMENT_DURATION);
661     }
662
663     private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
664         @Override
665         public void onReceive(Context context, Intent intent) {
666             post(new Runnable() {
667                 @Override
668                 public void run() {
669                     updateCameraVisibility();
670                 }
671             });
672         }
673     };
674
675     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
676             new KeyguardUpdateMonitorCallback() {
677         @Override
678         public void onUserSwitchComplete(int userId) {
679             updateCameraVisibility();
680         }
681
682         @Override
683         public void onStartedWakingUp() {
684             mLockIcon.setDeviceInteractive(true);
685         }
686
687         @Override
688         public void onFinishedGoingToSleep(int why) {
689             mLockIcon.setDeviceInteractive(false);
690         }
691
692         @Override
693         public void onScreenTurnedOn() {
694             mLockIcon.setScreenOn(true);
695         }
696
697         @Override
698         public void onScreenTurnedOff() {
699             mLockIcon.setScreenOn(false);
700         }
701
702         @Override
703         public void onKeyguardVisibilityChanged(boolean showing) {
704             mLockIcon.update();
705         }
706
707         @Override
708         public void onFingerprintRunningStateChanged(boolean running) {
709             mLockIcon.update();
710         }
711
712         @Override
713         public void onStrongAuthStateChanged(int userId) {
714             mLockIcon.update();
715         }
716
717         @Override
718         public void onUserUnlocked() {
719             inflateCameraPreview();
720             updateCameraVisibility();
721             updateLeftAffordance();
722         }
723     };
724
725     public void setKeyguardIndicationController(
726             KeyguardIndicationController keyguardIndicationController) {
727         mIndicationController = keyguardIndicationController;
728     }
729
730     public void setAssistManager(AssistManager assistManager) {
731         mAssistManager = assistManager;
732         updateLeftAffordance();
733     }
734
735     public void updateLeftAffordance() {
736         updateLeftAffordanceIcon();
737         updateLeftPreview();
738     }
739
740     public void onKeyguardShowingChanged() {
741         updateLeftAffordance();
742         inflateCameraPreview();
743     }
744 }