blob: e5ef6ff0053a6f1851968108104f15c547ab05a3 [file] [log] [blame]
Jorim Jaggia6310292014-04-16 14:11:52 +02001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar.phone;
18
19import android.app.ActivityManagerNative;
20import android.app.admin.DevicePolicyManager;
21import android.content.BroadcastReceiver;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
Jorim Jaggi97b63c42014-05-02 23:03:34 +020025import android.content.pm.PackageManager;
Adrian Roosa06905b2014-05-28 12:13:48 +020026import android.content.pm.ResolveInfo;
Jorim Jaggie210cc82014-08-12 23:44:59 +020027import android.content.res.Configuration;
Jorim Jaggi27c9b742015-04-09 10:34:49 -070028import android.content.res.Resources;
Adrian Roos72cc3702014-09-18 17:25:09 +020029import android.graphics.drawable.Drawable;
30import android.graphics.drawable.InsetDrawable;
Jim Millerfe6439f2015-04-11 18:07:57 -070031import android.hardware.fingerprint.FingerprintManager;
Yorke Lee583a20242014-08-12 18:47:08 -070032import android.os.AsyncTask;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020033import android.os.Bundle;
Jorim Jaggia6310292014-04-16 14:11:52 +020034import android.os.RemoteException;
35import android.os.UserHandle;
Jorim Jaggi27c9b742015-04-09 10:34:49 -070036import android.os.Vibrator;
Jorim Jaggia6310292014-04-16 14:11:52 +020037import android.provider.MediaStore;
Jorim Jaggi27c9b742015-04-09 10:34:49 -070038import android.provider.Settings;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070039import android.telecom.TelecomManager;
Jorim Jaggia6310292014-04-16 14:11:52 +020040import android.util.AttributeSet;
41import android.util.Log;
Jorim Jaggie210cc82014-08-12 23:44:59 +020042import android.util.TypedValue;
Jorim Jaggia6310292014-04-16 14:11:52 +020043import android.view.View;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020044import android.view.ViewGroup;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020045import android.view.accessibility.AccessibilityNodeInfo;
Jorim Jaggi16423aa2014-10-28 11:42:58 +010046import android.view.animation.AnimationUtils;
47import android.view.animation.Interpolator;
Jorim Jaggia6310292014-04-16 14:11:52 +020048import android.widget.FrameLayout;
Jorim Jaggie210cc82014-08-12 23:44:59 +020049import android.widget.TextView;
Adrian Roosa06905b2014-05-28 12:13:48 +020050
51import com.android.internal.widget.LockPatternUtils;
52import com.android.keyguard.KeyguardUpdateMonitor;
53import com.android.keyguard.KeyguardUpdateMonitorCallback;
Christoph Studerb0183992014-12-22 21:02:26 +010054import com.android.systemui.EventLogConstants;
55import com.android.systemui.EventLogTags;
Jorim Jaggia6310292014-04-16 14:11:52 +020056import com.android.systemui.R;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020057import com.android.systemui.statusbar.CommandQueue;
Selim Cinekbaa23272014-07-08 18:01:07 +020058import com.android.systemui.statusbar.KeyguardAffordanceView;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020059import com.android.systemui.statusbar.KeyguardIndicationController;
60import com.android.systemui.statusbar.policy.AccessibilityController;
61import com.android.systemui.statusbar.policy.FlashlightController;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020062import com.android.systemui.statusbar.policy.PreviewInflater;
Jorim Jaggia6310292014-04-16 14:11:52 +020063
Jorim Jaggib2e104f2014-08-15 18:12:36 +020064import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
65import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
66
Jorim Jaggia6310292014-04-16 14:11:52 +020067/**
68 * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
69 * text.
70 */
Selim Cinek4c6969a2014-05-26 19:22:17 +020071public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
Jorim Jaggib2e104f2014-08-15 18:12:36 +020072 UnlockMethodCache.OnUnlockMethodChangedListener,
73 AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
Jorim Jaggia6310292014-04-16 14:11:52 +020074
75 final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
76
Adrian Roosa06905b2014-05-28 12:13:48 +020077 private static final Intent SECURE_CAMERA_INTENT =
78 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
79 .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
80 private static final Intent INSECURE_CAMERA_INTENT =
81 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
Jorim Jaggi97b63c42014-05-02 23:03:34 +020082 private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
Jorim Jaggi16423aa2014-10-28 11:42:58 +010083 private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
84 private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
Jorim Jaggi27c9b742015-04-09 10:34:49 -070085 private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
Jorim Jaggi97b63c42014-05-02 23:03:34 +020086
Selim Cinekbaa23272014-07-08 18:01:07 +020087 private KeyguardAffordanceView mCameraImageView;
88 private KeyguardAffordanceView mPhoneImageView;
89 private KeyguardAffordanceView mLockIcon;
Jorim Jaggie210cc82014-08-12 23:44:59 +020090 private TextView mIndicationText;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020091 private ViewGroup mPreviewContainer;
92
93 private View mPhonePreview;
94 private View mCameraPreview;
Jorim Jaggi97b63c42014-05-02 23:03:34 +020095
Jorim Jaggi97b63c42014-05-02 23:03:34 +020096 private ActivityStarter mActivityStarter;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020097 private UnlockMethodCache mUnlockMethodCache;
Adrian Roosa06905b2014-05-28 12:13:48 +020098 private LockPatternUtils mLockPatternUtils;
Adrian Roos1e1d6ac2014-07-22 17:18:55 +020099 private FlashlightController mFlashlightController;
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200100 private PreviewInflater mPreviewInflater;
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200101 private KeyguardIndicationController mIndicationController;
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200102 private AccessibilityController mAccessibilityController;
103 private PhoneStatusBar mPhoneStatusBar;
Adrian Roos2fe592d2014-05-17 03:11:59 +0200104
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200105 private final TrustDrawable mTrustDrawable;
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100106 private final Interpolator mLinearOutSlowInInterpolator;
Adrian Roos72cc3702014-09-18 17:25:09 +0200107 private int mLastUnlockIconRes = 0;
Jorim Jaggia86790b2015-04-02 16:32:29 -0700108 private boolean mPrewarmSent;
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700109 private boolean mTransientFpError;
Adrian Roos72cc3702014-09-18 17:25:09 +0200110
Jorim Jaggia6310292014-04-16 14:11:52 +0200111 public KeyguardBottomAreaView(Context context) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200112 this(context, null);
Jorim Jaggia6310292014-04-16 14:11:52 +0200113 }
114
115 public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200116 this(context, attrs, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200117 }
118
119 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200120 this(context, attrs, defStyleAttr, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200121 }
122
123 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
124 int defStyleRes) {
125 super(context, attrs, defStyleAttr, defStyleRes);
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200126 mTrustDrawable = new TrustDrawable(mContext);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100127 mLinearOutSlowInInterpolator =
128 AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in);
Jorim Jaggia6310292014-04-16 14:11:52 +0200129 }
130
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200131 private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
132 @Override
133 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
134 super.onInitializeAccessibilityNodeInfo(host, info);
135 String label = null;
136 if (host == mLockIcon) {
137 label = getResources().getString(R.string.unlock_label);
138 } else if (host == mCameraImageView) {
139 label = getResources().getString(R.string.camera_label);
140 } else if (host == mPhoneImageView) {
141 label = getResources().getString(R.string.phone_label);
142 }
143 info.addAction(new AccessibilityAction(ACTION_CLICK, label));
144 }
145
146 @Override
147 public boolean performAccessibilityAction(View host, int action, Bundle args) {
148 if (action == ACTION_CLICK) {
149 if (host == mLockIcon) {
150 mPhoneStatusBar.animateCollapsePanels(
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +0100151 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200152 return true;
153 } else if (host == mCameraImageView) {
154 launchCamera();
155 return true;
156 } else if (host == mPhoneImageView) {
157 launchPhone();
158 return true;
159 }
160 }
161 return super.performAccessibilityAction(host, action, args);
162 }
163 };
164
Jorim Jaggia6310292014-04-16 14:11:52 +0200165 @Override
166 protected void onFinishInflate() {
167 super.onFinishInflate();
Adrian Roosa06905b2014-05-28 12:13:48 +0200168 mLockPatternUtils = new LockPatternUtils(mContext);
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200169 mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container);
Selim Cinekbaa23272014-07-08 18:01:07 +0200170 mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
171 mPhoneImageView = (KeyguardAffordanceView) findViewById(R.id.phone_button);
172 mLockIcon = (KeyguardAffordanceView) findViewById(R.id.lock_icon);
Jorim Jaggie210cc82014-08-12 23:44:59 +0200173 mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
Adrian Roosa06905b2014-05-28 12:13:48 +0200174 watchForCameraPolicyChanges();
Jorim Jaggia6310292014-04-16 14:11:52 +0200175 updateCameraVisibility();
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200176 updatePhoneVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200177 mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
178 mUnlockMethodCache.addListener(this);
Jorim Jaggie7b12522014-08-06 16:41:21 +0200179 updateLockIcon();
Selim Cinekbaa23272014-07-08 18:01:07 +0200180 setClipChildren(false);
181 setClipToPadding(false);
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200182 mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200183 inflatePreviews();
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200184 mLockIcon.setOnClickListener(this);
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200185 mLockIcon.setBackground(mTrustDrawable);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200186 mLockIcon.setOnLongClickListener(this);
187 mCameraImageView.setOnClickListener(this);
188 mPhoneImageView.setOnClickListener(this);
189 initAccessibility();
190 }
191
192 private void initAccessibility() {
193 mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
194 mPhoneImageView.setAccessibilityDelegate(mAccessibilityDelegate);
195 mCameraImageView.setAccessibilityDelegate(mAccessibilityDelegate);
Jorim Jaggia6310292014-04-16 14:11:52 +0200196 }
197
Jorim Jaggie210cc82014-08-12 23:44:59 +0200198 @Override
199 protected void onConfigurationChanged(Configuration newConfig) {
200 super.onConfigurationChanged(newConfig);
201 int indicationBottomMargin = getResources().getDimensionPixelSize(
202 R.dimen.keyguard_indication_margin_bottom);
203 MarginLayoutParams mlp = (MarginLayoutParams) mIndicationText.getLayoutParams();
204 if (mlp.bottomMargin != indicationBottomMargin) {
205 mlp.bottomMargin = indicationBottomMargin;
206 mIndicationText.setLayoutParams(mlp);
207 }
208
209 // Respect font size setting.
210 mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
211 getResources().getDimensionPixelSize(
212 com.android.internal.R.dimen.text_size_small_material));
213 }
214
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200215 public void setActivityStarter(ActivityStarter activityStarter) {
216 mActivityStarter = activityStarter;
217 }
218
Adrian Roos1e1d6ac2014-07-22 17:18:55 +0200219 public void setFlashlightController(FlashlightController flashlightController) {
220 mFlashlightController = flashlightController;
221 }
222
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200223 public void setAccessibilityController(AccessibilityController accessibilityController) {
224 mAccessibilityController = accessibilityController;
225 accessibilityController.addStateChangedCallback(this);
226 }
227
228 public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) {
229 mPhoneStatusBar = phoneStatusBar;
Dan Sandlere163a642015-03-01 22:58:32 -0500230 updateCameraVisibility(); // in case onFinishInflate() was called too early
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200231 }
232
Adrian Roosa06905b2014-05-28 12:13:48 +0200233 private Intent getCameraIntent() {
234 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
235 boolean currentUserHasTrust = updateMonitor.getUserHasTrust(
236 mLockPatternUtils.getCurrentUser());
237 return mLockPatternUtils.isSecure() && !currentUserHasTrust
238 ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
239 }
240
Jorim Jaggia6310292014-04-16 14:11:52 +0200241 private void updateCameraVisibility() {
Dan Sandlere163a642015-03-01 22:58:32 -0500242 if (mCameraImageView == null) {
243 // Things are not set up yet; reply hazy, ask again later
244 return;
245 }
Adrian Roosa06905b2014-05-28 12:13:48 +0200246 ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
247 PackageManager.MATCH_DEFAULT_ONLY,
248 mLockPatternUtils.getCurrentUser());
Jorim Jaggi15dac5f2014-08-27 19:08:26 +0200249 boolean visible = !isCameraDisabledByDpm() && resolved != null
250 && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance);
Selim Cinek4c6969a2014-05-26 19:22:17 +0200251 mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
Jorim Jaggia6310292014-04-16 14:11:52 +0200252 }
253
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200254 private void updatePhoneVisibility() {
255 boolean visible = isPhoneVisible();
Selim Cinek4c6969a2014-05-26 19:22:17 +0200256 mPhoneImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200257 }
258
259 private boolean isPhoneVisible() {
260 PackageManager pm = mContext.getPackageManager();
261 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
262 && pm.resolveActivity(PHONE_INTENT, 0) != null;
263 }
264
Jorim Jaggia6310292014-04-16 14:11:52 +0200265 private boolean isCameraDisabledByDpm() {
266 final DevicePolicyManager dpm =
267 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
Dan Sandlere163a642015-03-01 22:58:32 -0500268 if (dpm != null && mPhoneStatusBar != null) {
Jorim Jaggia6310292014-04-16 14:11:52 +0200269 try {
270 final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
271 final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
272 final boolean disabledBecauseKeyguardSecure =
273 (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
Jim Millerab954542014-10-10 18:21:49 -0700274 && mPhoneStatusBar.isKeyguardSecure();
Jorim Jaggia6310292014-04-16 14:11:52 +0200275 return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
276 } catch (RemoteException e) {
277 Log.e(TAG, "Can't get userId", e);
278 }
279 }
280 return false;
281 }
282
Adrian Roosa06905b2014-05-28 12:13:48 +0200283 private void watchForCameraPolicyChanges() {
Jorim Jaggia6310292014-04-16 14:11:52 +0200284 final IntentFilter filter = new IntentFilter();
285 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
Adrian Roosa06905b2014-05-28 12:13:48 +0200286 getContext().registerReceiverAsUser(mDevicePolicyReceiver,
287 UserHandle.ALL, filter, null, null);
288 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
Jorim Jaggia6310292014-04-16 14:11:52 +0200289 }
290
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200291 @Override
292 public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
293 mCameraImageView.setClickable(touchExplorationEnabled);
294 mPhoneImageView.setClickable(touchExplorationEnabled);
295 mCameraImageView.setFocusable(accessibilityEnabled);
296 mPhoneImageView.setFocusable(accessibilityEnabled);
297 updateLockIconClickability();
Jorim Jaggia6310292014-04-16 14:11:52 +0200298 }
299
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200300 private void updateLockIconClickability() {
301 if (mAccessibilityController == null) {
302 return;
303 }
Adrian Roos38fc76062014-09-22 17:34:56 +0200304 boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled();
305 boolean clickToForceLock = mUnlockMethodCache.isTrustManaged()
306 && !mAccessibilityController.isAccessibilityEnabled();
307 boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged()
308 && !clickToForceLock;
309 mLockIcon.setClickable(clickToForceLock || clickToUnlock);
310 mLockIcon.setLongClickable(longClickToForceLock);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200311 mLockIcon.setFocusable(mAccessibilityController.isAccessibilityEnabled());
Jorim Jaggia6310292014-04-16 14:11:52 +0200312 }
313
Selim Cinek4c6969a2014-05-26 19:22:17 +0200314 @Override
315 public void onClick(View v) {
316 if (v == mCameraImageView) {
317 launchCamera();
318 } else if (v == mPhoneImageView) {
319 launchPhone();
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200320 } if (v == mLockIcon) {
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200321 if (!mAccessibilityController.isAccessibilityEnabled()) {
322 handleTrustCircleClick();
323 } else {
324 mPhoneStatusBar.animateCollapsePanels(
325 CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
326 }
Selim Cinek4c6969a2014-05-26 19:22:17 +0200327 }
328 }
329
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200330 @Override
331 public boolean onLongClick(View v) {
332 handleTrustCircleClick();
333 return true;
334 }
335
336 private void handleTrustCircleClick() {
Christoph Studerb0183992014-12-22 21:02:26 +0100337 EventLogTags.writeSysuiLockscreenGesture(
338 EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK, 0 /* lengthDp - N/A */,
339 0 /* velocityDp - N/A */);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200340 mIndicationController.showTransientIndication(
341 R.string.keyguard_indication_trust_disabled);
342 mLockPatternUtils.requireCredentialEntry(mLockPatternUtils.getCurrentUser());
343 }
344
Jorim Jaggia86790b2015-04-02 16:32:29 -0700345 public void prewarmCamera() {
Adrian Roosa06905b2014-05-28 12:13:48 +0200346 Intent intent = getCameraIntent();
Jorim Jaggia86790b2015-04-02 16:32:29 -0700347 String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
348 mLockPatternUtils.getCurrentUser());
349 if (targetPackage != null) {
350 Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM);
351 prewarm.setPackage(targetPackage);
352 mPrewarmSent = true;
353 mContext.sendBroadcast(prewarm);
354 }
355 }
356
357 public void maybeCooldownCamera() {
358 if (!mPrewarmSent) {
359 return;
360 }
361 mPrewarmSent = false;
362 Intent intent = getCameraIntent();
363 String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
364 mLockPatternUtils.getCurrentUser());
365 if (targetPackage != null) {
366 Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN);
367 prewarm.setPackage(targetPackage);
368 mContext.sendBroadcast(prewarm);
369 }
370 }
371
372 public void launchCamera() {
373
374 // Reset prewarm state.
375 mPrewarmSent = false;
376 final Intent intent = getCameraIntent();
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200377 boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
378 mContext, intent, mLockPatternUtils.getCurrentUser());
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200379 if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
Jorim Jaggia86790b2015-04-02 16:32:29 -0700380 AsyncTask.execute(new Runnable() {
381 @Override
382 public void run() {
383 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
384 }
385 });
Adrian Roosa06905b2014-05-28 12:13:48 +0200386 } else {
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200387
388 // We need to delay starting the activity because ResolverActivity finishes itself if
389 // launched behind lockscreen.
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200390 mActivityStarter.startActivity(intent, false /* dismissShade */);
Adrian Roosa06905b2014-05-28 12:13:48 +0200391 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200392 }
393
Selim Cinek4c6969a2014-05-26 19:22:17 +0200394 public void launchPhone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700395 final TelecomManager tm = TelecomManager.from(mContext);
Nancy Chen0eb1e402014-08-21 22:52:29 -0700396 if (tm.isInCall()) {
Yorke Lee583a20242014-08-12 18:47:08 -0700397 AsyncTask.execute(new Runnable() {
398 @Override
399 public void run() {
Nancy Chen0eb1e402014-08-21 22:52:29 -0700400 tm.showInCallScreen(false /* showDialpad */);
Yorke Lee583a20242014-08-12 18:47:08 -0700401 }
402 });
403 } else {
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200404 mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
Yorke Lee583a20242014-08-12 18:47:08 -0700405 }
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200406 }
407
Adrian Roos2fe592d2014-05-17 03:11:59 +0200408
409 @Override
410 protected void onVisibilityChanged(View changedView, int visibility) {
411 super.onVisibilityChanged(changedView, visibility);
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200412 if (isShown()) {
413 mTrustDrawable.start();
414 } else {
415 mTrustDrawable.stop();
416 }
Adrian Roos2fe592d2014-05-17 03:11:59 +0200417 if (changedView == this && visibility == VISIBLE) {
Jorim Jaggie7b12522014-08-06 16:41:21 +0200418 updateLockIcon();
Adrian Roosa06905b2014-05-28 12:13:48 +0200419 updateCameraVisibility();
Adrian Roos2fe592d2014-05-17 03:11:59 +0200420 }
421 }
422
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200423 @Override
424 protected void onDetachedFromWindow() {
425 super.onDetachedFromWindow();
426 mTrustDrawable.stop();
427 }
428
Jorim Jaggie7b12522014-08-06 16:41:21 +0200429 private void updateLockIcon() {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200430 boolean visible = isShown() && KeyguardUpdateMonitor.getInstance(mContext).isScreenOn();
431 if (visible) {
432 mTrustDrawable.start();
433 } else {
434 mTrustDrawable.stop();
435 }
436 if (!visible) {
Adrian Roos2fe592d2014-05-17 03:11:59 +0200437 return;
438 }
Jorim Jaggie7b12522014-08-06 16:41:21 +0200439 // TODO: Real icon for facelock.
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700440 boolean isFingerprintIcon =
441 KeyguardUpdateMonitor.getInstance(mContext).isFingerprintDetectionRunning();
442 boolean anyFingerprintIcon = isFingerprintIcon || mTransientFpError;
443 int iconRes = mTransientFpError ? R.drawable.ic_fingerprint_error
444 : isFingerprintIcon ? R.drawable.ic_fingerprint
445 : mUnlockMethodCache.isFaceUnlockRunning()
446 ? com.android.internal.R.drawable.ic_account_circle
Christoph Studer2231c6e2014-12-19 12:40:13 +0100447 : mUnlockMethodCache.isCurrentlyInsecure() ? R.drawable.ic_lock_open_24dp
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200448 : R.drawable.ic_lock_24dp;
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700449
Adrian Roos72cc3702014-09-18 17:25:09 +0200450 if (mLastUnlockIconRes != iconRes) {
451 Drawable icon = mContext.getDrawable(iconRes);
452 int iconHeight = getResources().getDimensionPixelSize(
453 R.dimen.keyguard_affordance_icon_height);
454 int iconWidth = getResources().getDimensionPixelSize(
455 R.dimen.keyguard_affordance_icon_width);
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700456 if (!anyFingerprintIcon && (icon.getIntrinsicHeight() != iconHeight
457 || icon.getIntrinsicWidth() != iconWidth)) {
Adrian Roos72cc3702014-09-18 17:25:09 +0200458 icon = new IntrinsicSizeDrawable(icon, iconWidth, iconHeight);
459 }
460 mLockIcon.setImageDrawable(icon);
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700461 mLockIcon.setPaddingRelative(0, 0, 0, anyFingerprintIcon
462 ? getResources().getDimensionPixelSize(
463 R.dimen.fingerprint_icon_additional_padding)
464 : 0);
465 mLockIcon.setRestingAlpha(
466 anyFingerprintIcon ? 1f : KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT);
Adrian Roos72cc3702014-09-18 17:25:09 +0200467 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700468
469 // Hide trust circle when fingerprint is running.
470 boolean trustManaged = mUnlockMethodCache.isTrustManaged() && !anyFingerprintIcon;
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200471 mTrustDrawable.setTrustManaged(trustManaged);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200472 updateLockIconClickability();
Adrian Roos2fe592d2014-05-17 03:11:59 +0200473 }
474
Selim Cinekbaa23272014-07-08 18:01:07 +0200475 public KeyguardAffordanceView getPhoneView() {
Selim Cinek4c6969a2014-05-26 19:22:17 +0200476 return mPhoneImageView;
477 }
478
Selim Cinekbaa23272014-07-08 18:01:07 +0200479 public KeyguardAffordanceView getCameraView() {
Selim Cinek4c6969a2014-05-26 19:22:17 +0200480 return mCameraImageView;
481 }
482
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200483 public View getPhonePreview() {
484 return mPhonePreview;
485 }
486
487 public View getCameraPreview() {
488 return mCameraPreview;
489 }
490
Selim Cinekbaa23272014-07-08 18:01:07 +0200491 public KeyguardAffordanceView getLockIcon() {
Selim Cinek4c6969a2014-05-26 19:22:17 +0200492 return mLockIcon;
493 }
494
Selim Cinekf99d0002014-06-13 07:36:01 +0200495 public View getIndicationView() {
496 return mIndicationText;
497 }
498
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200499 @Override
Jorim Jaggi2580a9762014-06-25 03:08:25 +0200500 public boolean hasOverlappingRendering() {
501 return false;
502 }
503
504 @Override
Christoph Studer2231c6e2014-12-19 12:40:13 +0100505 public void onUnlockMethodStateChanged() {
Jorim Jaggie7b12522014-08-06 16:41:21 +0200506 updateLockIcon();
Adrian Roosa06905b2014-05-28 12:13:48 +0200507 updateCameraVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200508 }
Adrian Roosa06905b2014-05-28 12:13:48 +0200509
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200510 private void inflatePreviews() {
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200511 mPhonePreview = mPreviewInflater.inflatePreview(PHONE_INTENT);
512 mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200513 if (mPhonePreview != null) {
514 mPreviewContainer.addView(mPhonePreview);
515 mPhonePreview.setVisibility(View.INVISIBLE);
516 }
517 if (mCameraPreview != null) {
518 mPreviewContainer.addView(mCameraPreview);
519 mCameraPreview.setVisibility(View.INVISIBLE);
520 }
521 }
522
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100523 public void startFinishDozeAnimation() {
524 long delay = 0;
525 if (mPhoneImageView.getVisibility() == View.VISIBLE) {
526 startFinishDozeAnimationElement(mPhoneImageView, delay);
527 delay += DOZE_ANIMATION_STAGGER_DELAY;
528 }
529 startFinishDozeAnimationElement(mLockIcon, delay);
530 delay += DOZE_ANIMATION_STAGGER_DELAY;
531 if (mCameraImageView.getVisibility() == View.VISIBLE) {
532 startFinishDozeAnimationElement(mCameraImageView, delay);
533 }
534 mIndicationText.setAlpha(0f);
535 mIndicationText.animate()
536 .alpha(1f)
537 .setInterpolator(mLinearOutSlowInInterpolator)
538 .setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
539 }
540
541 private void startFinishDozeAnimationElement(View element, long delay) {
542 element.setAlpha(0f);
543 element.setTranslationY(element.getHeight() / 2);
544 element.animate()
545 .alpha(1f)
546 .translationY(0f)
547 .setInterpolator(mLinearOutSlowInInterpolator)
548 .setStartDelay(delay)
549 .setDuration(DOZE_ANIMATION_ELEMENT_DURATION);
550 }
551
Adrian Roosa06905b2014-05-28 12:13:48 +0200552 private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
553 public void onReceive(Context context, Intent intent) {
554 post(new Runnable() {
555 @Override
556 public void run() {
557 updateCameraVisibility();
558 }
559 });
560 }
561 };
562
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700563 private final Runnable mTransientFpErrorClearRunnable = new Runnable() {
564 @Override
565 public void run() {
566 mTransientFpError = false;
567 mIndicationController.hideTransientIndication();
568 updateLockIcon();
569 }
570 };
571
Adrian Roosa06905b2014-05-28 12:13:48 +0200572 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
573 new KeyguardUpdateMonitorCallback() {
574 @Override
575 public void onUserSwitchComplete(int userId) {
576 updateCameraVisibility();
577 }
Jorim Jaggie7b12522014-08-06 16:41:21 +0200578
579 @Override
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200580 public void onScreenTurnedOn() {
581 updateLockIcon();
582 }
583
584 @Override
585 public void onScreenTurnedOff(int why) {
586 updateLockIcon();
587 }
Adrian Roosb9ae0902014-10-27 14:20:30 +0100588
589 @Override
590 public void onKeyguardVisibilityChanged(boolean showing) {
591 updateLockIcon();
592 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700593
594 @Override
595 public void onFingerprintAuthenticated(int userId) {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700596 }
597
598 @Override
599 public void onFingerprintRunningStateChanged(boolean running) {
600 updateLockIcon();
601 }
602
603 @Override
604 public void onFingerprintHelp(int msgId, String helpString) {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700605 mTransientFpError = true;
606 mIndicationController.showTransientIndication(helpString,
607 getResources().getColor(R.color.system_warning_color, null));
608 removeCallbacks(mTransientFpErrorClearRunnable);
609 postDelayed(mTransientFpErrorClearRunnable, TRANSIENT_FP_ERROR_TIMEOUT);
610 updateLockIcon();
611 }
612
613 @Override
614 public void onFingerprintError(int msgId, String errString) {
615 // TODO: Go to bouncer if this is "too many attempts" (lockout) error.
616 Log.i(TAG, "FP Error: " + errString);
Jim Millerfe6439f2015-04-11 18:07:57 -0700617 updateLockIcon();
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700618 }
Adrian Roosa06905b2014-05-28 12:13:48 +0200619 };
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200620
621 public void setKeyguardIndicationController(
622 KeyguardIndicationController keyguardIndicationController) {
623 mIndicationController = keyguardIndicationController;
624 }
Adrian Roos72cc3702014-09-18 17:25:09 +0200625
Adrian Roos72cc3702014-09-18 17:25:09 +0200626 /**
627 * A wrapper around another Drawable that overrides the intrinsic size.
628 */
629 private static class IntrinsicSizeDrawable extends InsetDrawable {
630
631 private final int mIntrinsicWidth;
632 private final int mIntrinsicHeight;
633
634 public IntrinsicSizeDrawable(Drawable drawable, int intrinsicWidth, int intrinsicHeight) {
635 super(drawable, 0);
636 mIntrinsicWidth = intrinsicWidth;
637 mIntrinsicHeight = intrinsicHeight;
638 }
639
640 @Override
641 public int getIntrinsicWidth() {
642 return mIntrinsicWidth;
643 }
644
645 @Override
646 public int getIntrinsicHeight() {
647 return mIntrinsicHeight;
648 }
649 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200650}