blob: 0716b37ff8d9adb0625804a1bb7a0ab9c47e30e5 [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
Selim Cinek5f145022016-08-02 16:00:12 -070019import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
20import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
Jason Monk2a6ea9c2017-01-26 11:14:51 -050021
Jason Monk1d9632d2017-02-09 13:20:04 -080022import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
Jason Monkd6fa02f2017-01-25 18:26:50 -050023import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
Jason Monk1d9632d2017-02-09 13:20:04 -080024import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON;
Jason Monkd6fa02f2017-01-25 18:26:50 -050025import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK;
Selim Cinek5f145022016-08-02 16:00:12 -070026
Jorim Jaggid9449862015-05-29 14:49:08 -070027import android.app.ActivityManager;
Robert Carrfd10cd12016-06-29 16:41:50 -070028import android.app.ActivityOptions;
Jorim Jaggia6310292014-04-16 14:11:52 +020029import android.app.admin.DevicePolicyManager;
30import android.content.BroadcastReceiver;
Jorim Jaggid9449862015-05-29 14:49:08 -070031import android.content.ComponentName;
Jorim Jaggia6310292014-04-16 14:11:52 +020032import android.content.Context;
33import android.content.Intent;
34import android.content.IntentFilter;
Jorim Jaggid9449862015-05-29 14:49:08 -070035import android.content.ServiceConnection;
36import android.content.pm.ActivityInfo;
Jorim Jaggi97b63c42014-05-02 23:03:34 +020037import android.content.pm.PackageManager;
Adrian Roosa06905b2014-05-28 12:13:48 +020038import android.content.pm.ResolveInfo;
Jorim Jaggie210cc82014-08-12 23:44:59 +020039import android.content.res.Configuration;
Evan Roskyd388c752016-11-15 13:59:06 -080040import android.graphics.drawable.Drawable;
Yorke Lee583a20242014-08-12 18:47:08 -070041import android.os.AsyncTask;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020042import android.os.Bundle;
Jorim Jaggid9449862015-05-29 14:49:08 -070043import android.os.IBinder;
44import android.os.Message;
45import android.os.Messenger;
Jorim Jaggia6310292014-04-16 14:11:52 +020046import android.os.RemoteException;
47import android.os.UserHandle;
48import android.provider.MediaStore;
Jorim Jaggid9449862015-05-29 14:49:08 -070049import android.service.media.CameraPrewarmService;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070050import android.telecom.TelecomManager;
Jason Monkd6fa02f2017-01-25 18:26:50 -050051import android.text.TextUtils;
Jorim Jaggia6310292014-04-16 14:11:52 +020052import android.util.AttributeSet;
53import android.util.Log;
Lucas Dupin4272f442018-01-13 22:00:35 -080054import android.util.MathUtils;
Jorim Jaggie210cc82014-08-12 23:44:59 +020055import android.util.TypedValue;
Jorim Jaggia6310292014-04-16 14:11:52 +020056import android.view.View;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020057import android.view.ViewGroup;
Adrian Roos7e58a082018-03-09 16:40:56 +010058import android.view.WindowInsets;
Robert Carrfd10cd12016-06-29 16:41:50 -070059import android.view.WindowManager;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020060import android.view.accessibility.AccessibilityNodeInfo;
Jorim Jaggia6310292014-04-16 14:11:52 +020061import android.widget.FrameLayout;
Jorim Jaggie210cc82014-08-12 23:44:59 +020062import android.widget.TextView;
Adrian Roosa06905b2014-05-28 12:13:48 +020063
Chris Wren27a52fa2017-02-01 14:21:43 -050064import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Adrian Roosa06905b2014-05-28 12:13:48 +020065import com.android.internal.widget.LockPatternUtils;
66import com.android.keyguard.KeyguardUpdateMonitor;
67import com.android.keyguard.KeyguardUpdateMonitorCallback;
Christoph Studerb0183992014-12-22 21:02:26 +010068import com.android.systemui.EventLogTags;
Jason Monk9c7844c2017-01-18 15:21:53 -050069import com.android.systemui.Dependency;
Winsonc0d70582016-01-29 10:24:39 -080070import com.android.systemui.Interpolators;
Jorim Jaggia6310292014-04-16 14:11:52 +020071import com.android.systemui.R;
Selim Cineke70d6532015-04-24 16:46:13 -070072import com.android.systemui.assist.AssistManager;
Jason Monkb59f46f2016-09-27 12:29:18 -040073import com.android.systemui.plugins.IntentButtonProvider;
74import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
75import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState;
76import com.android.systemui.plugins.PluginListener;
Jason Monkec34da82017-02-24 15:57:05 -050077import com.android.systemui.plugins.ActivityStarter;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020078import com.android.systemui.statusbar.CommandQueue;
Selim Cinekbaa23272014-07-08 18:01:07 +020079import com.android.systemui.statusbar.KeyguardAffordanceView;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020080import com.android.systemui.statusbar.KeyguardIndicationController;
81import com.android.systemui.statusbar.policy.AccessibilityController;
Jason Monk1d9632d2017-02-09 13:20:04 -080082import com.android.systemui.statusbar.policy.ExtensionController;
83import com.android.systemui.statusbar.policy.ExtensionController.Extension;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020084import com.android.systemui.statusbar.policy.FlashlightController;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020085import com.android.systemui.statusbar.policy.PreviewInflater;
Jason Monk1d9632d2017-02-09 13:20:04 -080086import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory;
Jason Monkd6fa02f2017-01-25 18:26:50 -050087import com.android.systemui.tuner.TunerService;
Jorim Jaggia6310292014-04-16 14:11:52 +020088
89/**
90 * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
91 * text.
92 */
Selim Cinek4c6969a2014-05-26 19:22:17 +020093public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
Jorim Jaggib2e104f2014-08-15 18:12:36 +020094 UnlockMethodCache.OnUnlockMethodChangedListener,
Jason Monk1d9632d2017-02-09 13:20:04 -080095 AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
Jorim Jaggia6310292014-04-16 14:11:52 +020096
Jason Monk2a6ea9c2017-01-26 11:14:51 -050097 final static String TAG = "StatusBar/KeyguardBottomAreaView";
Jorim Jaggia6310292014-04-16 14:11:52 +020098
Jorim Jaggi40aa8812015-09-23 12:59:22 -070099 public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance";
100 public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture";
101 public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap";
Jonathan Solnita4138162017-05-10 21:06:04 -0700102 public static final String CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = "lift_to_launch_ml";
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700103
104 public static final String EXTRA_CAMERA_LAUNCH_SOURCE
105 = "com.android.systemui.camera_launch_source";
106
Jason Monkb59f46f2016-09-27 12:29:18 -0400107 private static final String LEFT_BUTTON_PLUGIN
108 = "com.android.systemui.action.PLUGIN_LOCKSCREEN_LEFT_BUTTON";
109 private static final String RIGHT_BUTTON_PLUGIN
110 = "com.android.systemui.action.PLUGIN_LOCKSCREEN_RIGHT_BUTTON";
111
Adrian Roosa06905b2014-05-28 12:13:48 +0200112 private static final Intent SECURE_CAMERA_INTENT =
113 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
114 .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Selim Cinek372d1bd2015-08-14 13:19:37 -0700115 public static final Intent INSECURE_CAMERA_INTENT =
Adrian Roosa06905b2014-05-28 12:13:48 +0200116 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200117 private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100118 private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
119 private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200120
Jason Monkb59f46f2016-09-27 12:29:18 -0400121 private KeyguardAffordanceView mRightAffordanceView;
Selim Cineke70d6532015-04-24 16:46:13 -0700122 private KeyguardAffordanceView mLeftAffordanceView;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700123 private LockIcon mLockIcon;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100124 private ViewGroup mIndicationArea;
125 private TextView mEnterpriseDisclosure;
Jorim Jaggie210cc82014-08-12 23:44:59 +0200126 private TextView mIndicationText;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200127 private ViewGroup mPreviewContainer;
Philip Quinnb86efa42017-07-08 12:59:24 -0700128 private ViewGroup mOverlayContainer;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200129
Selim Cineke70d6532015-04-24 16:46:13 -0700130 private View mLeftPreview;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200131 private View mCameraPreview;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200132
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200133 private ActivityStarter mActivityStarter;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200134 private UnlockMethodCache mUnlockMethodCache;
Adrian Roosa06905b2014-05-28 12:13:48 +0200135 private LockPatternUtils mLockPatternUtils;
Adrian Roos1e1d6ac2014-07-22 17:18:55 +0200136 private FlashlightController mFlashlightController;
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200137 private PreviewInflater mPreviewInflater;
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200138 private KeyguardIndicationController mIndicationController;
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200139 private AccessibilityController mAccessibilityController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500140 private StatusBar mStatusBar;
Jorim Jaggidadafd42016-09-30 07:20:25 -0700141 private KeyguardAffordanceHelper mAffordanceHelper;
Adrian Roos2fe592d2014-05-17 03:11:59 +0200142
Adrian Roosa4eba9f2015-07-22 18:13:04 -0700143 private boolean mUserSetupComplete;
Jorim Jaggid9449862015-05-29 14:49:08 -0700144 private boolean mPrewarmBound;
145 private Messenger mPrewarmMessenger;
146 private final ServiceConnection mPrewarmConnection = new ServiceConnection() {
147
148 @Override
149 public void onServiceConnected(ComponentName name, IBinder service) {
150 mPrewarmMessenger = new Messenger(service);
Jorim Jaggid9449862015-05-29 14:49:08 -0700151 }
152
153 @Override
154 public void onServiceDisconnected(ComponentName name) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700155 mPrewarmMessenger = null;
156 }
157 };
158
Selim Cineke70d6532015-04-24 16:46:13 -0700159 private boolean mLeftIsVoiceAssist;
160 private AssistManager mAssistManager;
Evan Roskyd388c752016-11-15 13:59:06 -0800161 private Drawable mLeftAssistIcon;
Adrian Roos72cc3702014-09-18 17:25:09 +0200162
Jason Monkb59f46f2016-09-27 12:29:18 -0400163 private IntentButton mRightButton = new DefaultRightButton();
Jason Monk1d9632d2017-02-09 13:20:04 -0800164 private Extension<IntentButton> mRightExtension;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500165 private String mRightButtonStr;
Jason Monkb59f46f2016-09-27 12:29:18 -0400166 private IntentButton mLeftButton = new DefaultLeftButton();
Jason Monk1d9632d2017-02-09 13:20:04 -0800167 private Extension<IntentButton> mLeftExtension;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500168 private String mLeftButtonStr;
Chris Wren27a52fa2017-02-01 14:21:43 -0500169 private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
Adrian Roos91ba3072017-02-14 16:50:46 +0100170 private boolean mDozing;
Lucas Dupin4272f442018-01-13 22:00:35 -0800171 private int mIndicationBottomMargin;
172 private int mIndicationBottomMarginAmbient;
173 private float mDarkAmount;
174 private int mBurnInXOffset;
Jason Monkb59f46f2016-09-27 12:29:18 -0400175
Jorim Jaggia6310292014-04-16 14:11:52 +0200176 public KeyguardBottomAreaView(Context context) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200177 this(context, null);
Jorim Jaggia6310292014-04-16 14:11:52 +0200178 }
179
180 public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200181 this(context, attrs, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200182 }
183
184 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200185 this(context, attrs, defStyleAttr, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200186 }
187
188 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
189 int defStyleRes) {
190 super(context, attrs, defStyleAttr, defStyleRes);
191 }
192
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200193 private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
194 @Override
195 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
196 super.onInitializeAccessibilityNodeInfo(host, info);
197 String label = null;
198 if (host == mLockIcon) {
199 label = getResources().getString(R.string.unlock_label);
Jason Monkb59f46f2016-09-27 12:29:18 -0400200 } else if (host == mRightAffordanceView) {
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200201 label = getResources().getString(R.string.camera_label);
Selim Cineke70d6532015-04-24 16:46:13 -0700202 } else if (host == mLeftAffordanceView) {
203 if (mLeftIsVoiceAssist) {
204 label = getResources().getString(R.string.voice_assist_label);
205 } else {
206 label = getResources().getString(R.string.phone_label);
207 }
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200208 }
209 info.addAction(new AccessibilityAction(ACTION_CLICK, label));
210 }
211
212 @Override
213 public boolean performAccessibilityAction(View host, int action, Bundle args) {
214 if (action == ACTION_CLICK) {
215 if (host == mLockIcon) {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500216 mStatusBar.animateCollapsePanels(
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +0100217 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200218 return true;
Jason Monkb59f46f2016-09-27 12:29:18 -0400219 } else if (host == mRightAffordanceView) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700220 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200221 return true;
Selim Cineke70d6532015-04-24 16:46:13 -0700222 } else if (host == mLeftAffordanceView) {
223 launchLeftAffordance();
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200224 return true;
225 }
226 }
227 return super.performAccessibilityAction(host, action, args);
228 }
229 };
230
Jorim Jaggia6310292014-04-16 14:11:52 +0200231 @Override
232 protected void onFinishInflate() {
233 super.onFinishInflate();
Adrian Roosa06905b2014-05-28 12:13:48 +0200234 mLockPatternUtils = new LockPatternUtils(mContext);
Alan Viverette51efddb2017-04-05 10:00:01 -0400235 mPreviewContainer = findViewById(R.id.preview_container);
Philip Quinnb86efa42017-07-08 12:59:24 -0700236 mOverlayContainer = findViewById(R.id.overlay_container);
Alan Viverette51efddb2017-04-05 10:00:01 -0400237 mRightAffordanceView = findViewById(R.id.camera_button);
238 mLeftAffordanceView = findViewById(R.id.left_button);
239 mLockIcon = findViewById(R.id.lock_icon);
240 mIndicationArea = findViewById(R.id.keyguard_indication_area);
241 mEnterpriseDisclosure = findViewById(
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100242 R.id.keyguard_indication_enterprise_disclosure);
Alan Viverette51efddb2017-04-05 10:00:01 -0400243 mIndicationText = findViewById(R.id.keyguard_indication_text);
Lucas Dupin4272f442018-01-13 22:00:35 -0800244 mIndicationBottomMargin = getResources().getDimensionPixelSize(
245 R.dimen.keyguard_indication_margin_bottom);
246 mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
247 R.dimen.keyguard_indication_margin_bottom_ambient);
Jorim Jaggia6310292014-04-16 14:11:52 +0200248 updateCameraVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200249 mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
250 mUnlockMethodCache.addListener(this);
Selim Cinek9a105312017-07-21 17:16:05 -0700251 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
252 mLockIcon.setScreenOn(updateMonitor.isScreenOn());
253 mLockIcon.setDeviceInteractive(updateMonitor.isDeviceInteractive());
Jorim Jaggi27267d62015-04-28 13:27:12 -0700254 mLockIcon.update();
Selim Cinekbaa23272014-07-08 18:01:07 +0200255 setClipChildren(false);
256 setClipToPadding(false);
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200257 mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
Selim Cineke70d6532015-04-24 16:46:13 -0700258 inflateCameraPreview();
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200259 mLockIcon.setOnClickListener(this);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200260 mLockIcon.setOnLongClickListener(this);
Jason Monkb59f46f2016-09-27 12:29:18 -0400261 mRightAffordanceView.setOnClickListener(this);
Selim Cineke70d6532015-04-24 16:46:13 -0700262 mLeftAffordanceView.setOnClickListener(this);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200263 initAccessibility();
Jason Monk9c7844c2017-01-18 15:21:53 -0500264 mActivityStarter = Dependency.get(ActivityStarter.class);
265 mFlashlightController = Dependency.get(FlashlightController.class);
266 mAccessibilityController = Dependency.get(AccessibilityController.class);
267 mAssistManager = Dependency.get(AssistManager.class);
Adrian Roos83c60c02017-07-06 15:36:32 +0200268 mLockIcon.setAccessibilityController(mAccessibilityController);
Jason Monk9c7844c2017-01-18 15:21:53 -0500269 updateLeftAffordance();
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200270 }
271
Jason Monkb59f46f2016-09-27 12:29:18 -0400272 @Override
273 protected void onAttachedToWindow() {
274 super.onAttachedToWindow();
Jason Monk9ef73072017-01-27 13:32:51 -0500275 mAccessibilityController.addStateChangedCallback(this);
Jason Monk1d9632d2017-02-09 13:20:04 -0800276 mRightExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
277 .withPlugin(IntentButtonProvider.class, RIGHT_BUTTON_PLUGIN,
278 p -> p.getIntentButton())
279 .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_RIGHT_BUTTON))
280 .withDefault(() -> new DefaultRightButton())
281 .withCallback(button -> setRightButton(button))
282 .build();
283 mLeftExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
284 .withPlugin(IntentButtonProvider.class, LEFT_BUTTON_PLUGIN,
285 p -> p.getIntentButton())
286 .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_LEFT_BUTTON))
287 .withDefault(() -> new DefaultLeftButton())
288 .withCallback(button -> setLeftButton(button))
289 .build();
Selim Cinek9a105312017-07-21 17:16:05 -0700290 final IntentFilter filter = new IntentFilter();
291 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
292 getContext().registerReceiverAsUser(mDevicePolicyReceiver,
293 UserHandle.ALL, filter, null, null);
294 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
Jason Monkb59f46f2016-09-27 12:29:18 -0400295 }
296
297 @Override
298 protected void onDetachedFromWindow() {
299 super.onDetachedFromWindow();
Jason Monk9ef73072017-01-27 13:32:51 -0500300 mAccessibilityController.removeStateChangedCallback(this);
Jason Monk1d9632d2017-02-09 13:20:04 -0800301 mRightExtension.destroy();
302 mLeftExtension.destroy();
Selim Cinek9a105312017-07-21 17:16:05 -0700303 getContext().unregisterReceiver(mDevicePolicyReceiver);
304 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallback);
Jason Monkb59f46f2016-09-27 12:29:18 -0400305 }
306
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200307 private void initAccessibility() {
308 mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
Selim Cineke70d6532015-04-24 16:46:13 -0700309 mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
Jason Monkb59f46f2016-09-27 12:29:18 -0400310 mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
Jorim Jaggia6310292014-04-16 14:11:52 +0200311 }
312
Jorim Jaggie210cc82014-08-12 23:44:59 +0200313 @Override
314 protected void onConfigurationChanged(Configuration newConfig) {
315 super.onConfigurationChanged(newConfig);
Lucas Dupin4272f442018-01-13 22:00:35 -0800316 mIndicationBottomMargin = getResources().getDimensionPixelSize(
Jorim Jaggie210cc82014-08-12 23:44:59 +0200317 R.dimen.keyguard_indication_margin_bottom);
Lucas Dupin4272f442018-01-13 22:00:35 -0800318 mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
319 R.dimen.keyguard_indication_margin_bottom_ambient);
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100320 MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams();
Lucas Dupin4272f442018-01-13 22:00:35 -0800321 if (mlp.bottomMargin != mIndicationBottomMargin) {
322 mlp.bottomMargin = mIndicationBottomMargin;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100323 mIndicationArea.setLayoutParams(mlp);
Jorim Jaggie210cc82014-08-12 23:44:59 +0200324 }
325
326 // Respect font size setting.
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100327 mEnterpriseDisclosure.setTextSize(TypedValue.COMPLEX_UNIT_PX,
328 getResources().getDimensionPixelSize(
329 com.android.internal.R.dimen.text_size_small_material));
Jorim Jaggie210cc82014-08-12 23:44:59 +0200330 mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
331 getResources().getDimensionPixelSize(
332 com.android.internal.R.dimen.text_size_small_material));
Selim Cinek6ebba592016-05-31 15:28:28 -0700333
Jason Monkb59f46f2016-09-27 12:29:18 -0400334 ViewGroup.LayoutParams lp = mRightAffordanceView.getLayoutParams();
Selim Cinek6ebba592016-05-31 15:28:28 -0700335 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
336 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
Jason Monkb59f46f2016-09-27 12:29:18 -0400337 mRightAffordanceView.setLayoutParams(lp);
338 updateRightAffordanceIcon();
Selim Cinek6ebba592016-05-31 15:28:28 -0700339
340 lp = mLockIcon.getLayoutParams();
341 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
342 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
343 mLockIcon.setLayoutParams(lp);
Adrian Rooseffff9c2017-08-09 15:50:00 +0200344 mLockIcon.setContentDescription(getContext().getText(R.string.accessibility_unlock_button));
Selim Cinek6ebba592016-05-31 15:28:28 -0700345 mLockIcon.update(true /* force */);
346
347 lp = mLeftAffordanceView.getLayoutParams();
348 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
349 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
350 mLeftAffordanceView.setLayoutParams(lp);
351 updateLeftAffordanceIcon();
Jorim Jaggie210cc82014-08-12 23:44:59 +0200352 }
353
Jason Monkb59f46f2016-09-27 12:29:18 -0400354 private void updateRightAffordanceIcon() {
355 IconState state = mRightButton.getIcon();
Adrian Roos674b8ea2017-05-25 12:33:17 -0700356 mRightAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE);
Jason Monkca215682017-02-09 14:32:54 -0800357 mRightAffordanceView.setImageDrawable(state.drawable, state.tint);
Jason Monkb59f46f2016-09-27 12:29:18 -0400358 mRightAffordanceView.setContentDescription(state.contentDescription);
359 }
360
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500361 public void setStatusBar(StatusBar statusBar) {
362 mStatusBar = statusBar;
Dan Sandlere163a642015-03-01 22:58:32 -0500363 updateCameraVisibility(); // in case onFinishInflate() was called too early
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200364 }
365
Jorim Jaggidadafd42016-09-30 07:20:25 -0700366 public void setAffordanceHelper(KeyguardAffordanceHelper affordanceHelper) {
367 mAffordanceHelper = affordanceHelper;
368 }
369
Adrian Roosa4eba9f2015-07-22 18:13:04 -0700370 public void setUserSetupComplete(boolean userSetupComplete) {
371 mUserSetupComplete = userSetupComplete;
372 updateCameraVisibility();
373 updateLeftAffordanceIcon();
374 }
375
Adrian Roosa06905b2014-05-28 12:13:48 +0200376 private Intent getCameraIntent() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400377 return mRightButton.getIntent();
Adrian Roosa06905b2014-05-28 12:13:48 +0200378 }
379
Zhentao Sun04f97402015-08-26 17:37:30 -0700380 /**
381 * Resolves the intent to launch the camera application.
382 */
383 public ResolveInfo resolveCameraIntent() {
384 return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
385 PackageManager.MATCH_DEFAULT_ONLY,
386 KeyguardUpdateMonitor.getCurrentUser());
387 }
388
Jorim Jaggia6310292014-04-16 14:11:52 +0200389 private void updateCameraVisibility() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400390 if (mRightAffordanceView == null) {
Dan Sandlere163a642015-03-01 22:58:32 -0500391 // Things are not set up yet; reply hazy, ask again later
392 return;
393 }
Adrian Roos91ba3072017-02-14 16:50:46 +0100394 mRightAffordanceView.setVisibility(!mDozing && mRightButton.getIcon().isVisible
Jason Monkb59f46f2016-09-27 12:29:18 -0400395 ? View.VISIBLE : View.GONE);
Jorim Jaggia6310292014-04-16 14:11:52 +0200396 }
397
Evan Roskyd388c752016-11-15 13:59:06 -0800398 /**
399 * Set an alternate icon for the left assist affordance (replace the mic icon)
400 */
401 public void setLeftAssistIcon(Drawable drawable) {
402 mLeftAssistIcon = drawable;
403 updateLeftAffordanceIcon();
404 }
405
Selim Cineke70d6532015-04-24 16:46:13 -0700406 private void updateLeftAffordanceIcon() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400407 IconState state = mLeftButton.getIcon();
Adrian Roos91ba3072017-02-14 16:50:46 +0100408 mLeftAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE);
Jason Monkca215682017-02-09 14:32:54 -0800409 mLeftAffordanceView.setImageDrawable(state.drawable, state.tint);
Jason Monkb59f46f2016-09-27 12:29:18 -0400410 mLeftAffordanceView.setContentDescription(state.contentDescription);
Selim Cineke70d6532015-04-24 16:46:13 -0700411 }
412
413 public boolean isLeftVoiceAssist() {
414 return mLeftIsVoiceAssist;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200415 }
416
417 private boolean isPhoneVisible() {
418 PackageManager pm = mContext.getPackageManager();
419 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
420 && pm.resolveActivity(PHONE_INTENT, 0) != null;
421 }
422
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200423 @Override
424 public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
Jason Monkb59f46f2016-09-27 12:29:18 -0400425 mRightAffordanceView.setClickable(touchExplorationEnabled);
Selim Cineke70d6532015-04-24 16:46:13 -0700426 mLeftAffordanceView.setClickable(touchExplorationEnabled);
Jason Monkb59f46f2016-09-27 12:29:18 -0400427 mRightAffordanceView.setFocusable(accessibilityEnabled);
Selim Cineke70d6532015-04-24 16:46:13 -0700428 mLeftAffordanceView.setFocusable(accessibilityEnabled);
Jorim Jaggi27267d62015-04-28 13:27:12 -0700429 mLockIcon.update();
Jorim Jaggia6310292014-04-16 14:11:52 +0200430 }
431
Selim Cinek4c6969a2014-05-26 19:22:17 +0200432 @Override
433 public void onClick(View v) {
Jason Monkb59f46f2016-09-27 12:29:18 -0400434 if (v == mRightAffordanceView) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700435 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
Selim Cineke70d6532015-04-24 16:46:13 -0700436 } else if (v == mLeftAffordanceView) {
437 launchLeftAffordance();
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200438 } if (v == mLockIcon) {
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200439 if (!mAccessibilityController.isAccessibilityEnabled()) {
440 handleTrustCircleClick();
441 } else {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500442 mStatusBar.animateCollapsePanels(
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200443 CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
444 }
Selim Cinek4c6969a2014-05-26 19:22:17 +0200445 }
446 }
447
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200448 @Override
449 public boolean onLongClick(View v) {
450 handleTrustCircleClick();
451 return true;
452 }
453
454 private void handleTrustCircleClick() {
Chris Wren27a52fa2017-02-01 14:21:43 -0500455 mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_LOCK, 0 /* lengthDp - N/A */,
Christoph Studerb0183992014-12-22 21:02:26 +0100456 0 /* velocityDp - N/A */);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200457 mIndicationController.showTransientIndication(
458 R.string.keyguard_indication_trust_disabled);
Adrian Roosd6aa6cb2015-04-16 19:31:29 -0700459 mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200460 }
461
Jorim Jaggid9449862015-05-29 14:49:08 -0700462 public void bindCameraPrewarmService() {
Adrian Roosa06905b2014-05-28 12:13:48 +0200463 Intent intent = getCameraIntent();
Jorim Jaggid9449862015-05-29 14:49:08 -0700464 ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent,
Selim Cinek5f145022016-08-02 16:00:12 -0700465 KeyguardUpdateMonitor.getCurrentUser(), true /* onlyDirectBootAware */);
Jorim Jaggi8b8fa3e2015-08-18 18:33:49 -0700466 if (targetInfo != null && targetInfo.metaData != null) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700467 String clazz = targetInfo.metaData.getString(
468 MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE);
469 if (clazz != null) {
470 Intent serviceIntent = new Intent();
471 serviceIntent.setClassName(targetInfo.packageName, clazz);
472 serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM);
473 try {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700474 if (getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection,
Selim Cinekedf47482015-09-01 18:05:08 -0700475 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
476 new UserHandle(UserHandle.USER_CURRENT))) {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700477 mPrewarmBound = true;
478 }
Jorim Jaggid9449862015-05-29 14:49:08 -0700479 } catch (SecurityException e) {
480 Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName
481 + " class=" + clazz, e);
482 }
483 }
Jorim Jaggia86790b2015-04-02 16:32:29 -0700484 }
485 }
486
Jorim Jaggid9449862015-05-29 14:49:08 -0700487 public void unbindCameraPrewarmService(boolean launched) {
488 if (mPrewarmBound) {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700489 if (mPrewarmMessenger != null && launched) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700490 try {
491 mPrewarmMessenger.send(Message.obtain(null /* handler */,
492 CameraPrewarmService.MSG_CAMERA_FIRED));
493 } catch (RemoteException e) {
494 Log.w(TAG, "Error sending camera fired message", e);
495 }
496 }
497 mContext.unbindService(mPrewarmConnection);
498 mPrewarmBound = false;
Jorim Jaggia86790b2015-04-02 16:32:29 -0700499 }
500 }
501
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700502 public void launchCamera(String source) {
Jorim Jaggia86790b2015-04-02 16:32:29 -0700503 final Intent intent = getCameraIntent();
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700504 intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200505 boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
Adrian Roosd6aa6cb2015-04-16 19:31:29 -0700506 mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200507 if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
Jorim Jaggia86790b2015-04-02 16:32:29 -0700508 AsyncTask.execute(new Runnable() {
509 @Override
510 public void run() {
Jorim Jaggid9449862015-05-29 14:49:08 -0700511 int result = ActivityManager.START_CANCELED;
Robert Carrfd10cd12016-06-29 16:41:50 -0700512
513 // Normally an activity will set it's requested rotation
514 // animation on its window. However when launching an activity
515 // causes the orientation to change this is too late. In these cases
516 // the default animation is used. This doesn't look good for
517 // the camera (as it rotates the camera contents out of sync
518 // with physical reality). So, we ask the WindowManager to
519 // force the crossfade animation if an orientation change
520 // happens to occur during the launch.
521 ActivityOptions o = ActivityOptions.makeBasic();
Winson Chungf7e03e12017-08-22 11:32:16 -0700522 o.setDisallowEnterPictureInPictureWhileLaunching(true);
Robert Carrfd10cd12016-06-29 16:41:50 -0700523 o.setRotationAnimationHint(
Robert Carr57d9fbd2016-08-15 12:00:35 -0700524 WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
Jorim Jaggid9449862015-05-29 14:49:08 -0700525 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800526 result = ActivityManager.getService().startActivityAsUser(
Jorim Jaggid9449862015-05-29 14:49:08 -0700527 null, getContext().getBasePackageName(),
528 intent,
529 intent.resolveTypeIfNeeded(getContext().getContentResolver()),
Robert Carrfd10cd12016-06-29 16:41:50 -0700530 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, o.toBundle(),
Jorim Jaggid9449862015-05-29 14:49:08 -0700531 UserHandle.CURRENT.getIdentifier());
532 } catch (RemoteException e) {
533 Log.w(TAG, "Unable to start camera activity", e);
534 }
Jorim Jaggid9449862015-05-29 14:49:08 -0700535 final boolean launched = isSuccessfulLaunch(result);
536 post(new Runnable() {
537 @Override
538 public void run() {
539 unbindCameraPrewarmService(launched);
540 }
541 });
Jorim Jaggia86790b2015-04-02 16:32:29 -0700542 }
543 });
Adrian Roosa06905b2014-05-28 12:13:48 +0200544 } else {
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200545
546 // We need to delay starting the activity because ResolverActivity finishes itself if
547 // launched behind lockscreen.
Jorim Jaggid9449862015-05-29 14:49:08 -0700548 mActivityStarter.startActivity(intent, false /* dismissShade */,
549 new ActivityStarter.Callback() {
550 @Override
551 public void onActivityStarted(int resultCode) {
552 unbindCameraPrewarmService(isSuccessfulLaunch(resultCode));
553 }
554 });
Adrian Roosa06905b2014-05-28 12:13:48 +0200555 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200556 }
557
Lucas Dupin4272f442018-01-13 22:00:35 -0800558 public void setDarkAmount(float darkAmount) {
559 if (darkAmount == mDarkAmount) {
560 return;
561 }
562 mDarkAmount = darkAmount;
563 // Let's randomize the bottom margin every time we wake up to avoid burn-in.
564 if (darkAmount == 0) {
565 mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
566 R.dimen.keyguard_indication_margin_bottom_ambient)
567 + (int) (Math.random() * mIndicationText.getTextSize());
568 }
569 mIndicationArea.setAlpha(MathUtils.lerp(1f, 0.7f, darkAmount));
570 mIndicationArea.setTranslationY(MathUtils.lerp(0,
571 mIndicationBottomMargin - mIndicationBottomMarginAmbient, darkAmount));
572 }
573
Jorim Jaggid9449862015-05-29 14:49:08 -0700574 private static boolean isSuccessfulLaunch(int result) {
575 return result == ActivityManager.START_SUCCESS
576 || result == ActivityManager.START_DELIVERED_TO_TOP
577 || result == ActivityManager.START_TASK_TO_FRONT;
578 }
579
Selim Cineke70d6532015-04-24 16:46:13 -0700580 public void launchLeftAffordance() {
581 if (mLeftIsVoiceAssist) {
582 launchVoiceAssist();
583 } else {
584 launchPhone();
585 }
586 }
587
588 private void launchVoiceAssist() {
589 Runnable runnable = new Runnable() {
590 @Override
591 public void run() {
592 mAssistManager.launchVoiceAssistFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700593 }
594 };
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500595 if (mStatusBar.isKeyguardCurrentlySecure()) {
Selim Cineke70d6532015-04-24 16:46:13 -0700596 AsyncTask.execute(runnable);
597 } else {
Jason Monkd6fa02f2017-01-25 18:26:50 -0500598 boolean dismissShade = !TextUtils.isEmpty(mRightButtonStr)
Jason Monkde850bb2017-02-01 19:26:30 -0500599 && Dependency.get(TunerService.class).getValue(LOCKSCREEN_RIGHT_UNLOCK, 1) != 0;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500600 mStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
Jason Monkd6fa02f2017-01-25 18:26:50 -0500601 dismissShade, false /* afterKeyguardGone */, true /* deferred */);
Selim Cineke70d6532015-04-24 16:46:13 -0700602 }
603 }
604
605 private boolean canLaunchVoiceAssist() {
606 return mAssistManager.canVoiceAssistBeLaunchedFromKeyguard();
607 }
608
609 private void launchPhone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700610 final TelecomManager tm = TelecomManager.from(mContext);
Nancy Chen0eb1e402014-08-21 22:52:29 -0700611 if (tm.isInCall()) {
Yorke Lee583a20242014-08-12 18:47:08 -0700612 AsyncTask.execute(new Runnable() {
613 @Override
614 public void run() {
Nancy Chen0eb1e402014-08-21 22:52:29 -0700615 tm.showInCallScreen(false /* showDialpad */);
Yorke Lee583a20242014-08-12 18:47:08 -0700616 }
617 });
618 } else {
Jason Monkd6fa02f2017-01-25 18:26:50 -0500619 boolean dismissShade = !TextUtils.isEmpty(mLeftButtonStr)
Jason Monkde850bb2017-02-01 19:26:30 -0500620 && Dependency.get(TunerService.class).getValue(LOCKSCREEN_LEFT_UNLOCK, 1) != 0;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500621 mActivityStarter.startActivity(mLeftButton.getIntent(), dismissShade);
Yorke Lee583a20242014-08-12 18:47:08 -0700622 }
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200623 }
624
Adrian Roos2fe592d2014-05-17 03:11:59 +0200625
626 @Override
627 protected void onVisibilityChanged(View changedView, int visibility) {
628 super.onVisibilityChanged(changedView, visibility);
629 if (changedView == this && visibility == VISIBLE) {
Jorim Jaggi27267d62015-04-28 13:27:12 -0700630 mLockIcon.update();
Adrian Roosa06905b2014-05-28 12:13:48 +0200631 updateCameraVisibility();
Adrian Roos2fe592d2014-05-17 03:11:59 +0200632 }
633 }
634
Selim Cineke70d6532015-04-24 16:46:13 -0700635 public KeyguardAffordanceView getLeftView() {
636 return mLeftAffordanceView;
Selim Cinek4c6969a2014-05-26 19:22:17 +0200637 }
638
Selim Cineke70d6532015-04-24 16:46:13 -0700639 public KeyguardAffordanceView getRightView() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400640 return mRightAffordanceView;
Selim Cinek4c6969a2014-05-26 19:22:17 +0200641 }
642
Selim Cineke70d6532015-04-24 16:46:13 -0700643 public View getLeftPreview() {
644 return mLeftPreview;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200645 }
646
Selim Cineke70d6532015-04-24 16:46:13 -0700647 public View getRightPreview() {
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200648 return mCameraPreview;
649 }
650
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700651 public LockIcon getLockIcon() {
Selim Cinek4c6969a2014-05-26 19:22:17 +0200652 return mLockIcon;
653 }
654
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100655 public View getIndicationArea() {
656 return mIndicationArea;
Selim Cinekf99d0002014-06-13 07:36:01 +0200657 }
658
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200659 @Override
Jorim Jaggi2580a9762014-06-25 03:08:25 +0200660 public boolean hasOverlappingRendering() {
661 return false;
662 }
663
664 @Override
Christoph Studer2231c6e2014-12-19 12:40:13 +0100665 public void onUnlockMethodStateChanged() {
Jorim Jaggi27267d62015-04-28 13:27:12 -0700666 mLockIcon.update();
Adrian Roosa06905b2014-05-28 12:13:48 +0200667 updateCameraVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200668 }
Adrian Roosa06905b2014-05-28 12:13:48 +0200669
Selim Cineke70d6532015-04-24 16:46:13 -0700670 private void inflateCameraPreview() {
Selim Cinek5f145022016-08-02 16:00:12 -0700671 View previewBefore = mCameraPreview;
672 boolean visibleBefore = false;
673 if (previewBefore != null) {
674 mPreviewContainer.removeView(previewBefore);
675 visibleBefore = previewBefore.getVisibility() == View.VISIBLE;
676 }
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200677 mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200678 if (mCameraPreview != null) {
679 mPreviewContainer.addView(mCameraPreview);
Selim Cinek5f145022016-08-02 16:00:12 -0700680 mCameraPreview.setVisibility(visibleBefore ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200681 }
Jorim Jaggidadafd42016-09-30 07:20:25 -0700682 if (mAffordanceHelper != null) {
683 mAffordanceHelper.updatePreviews();
684 }
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200685 }
686
Selim Cineke70d6532015-04-24 16:46:13 -0700687 private void updateLeftPreview() {
688 View previewBefore = mLeftPreview;
689 if (previewBefore != null) {
690 mPreviewContainer.removeView(previewBefore);
691 }
692 if (mLeftIsVoiceAssist) {
693 mLeftPreview = mPreviewInflater.inflatePreviewFromService(
694 mAssistManager.getVoiceInteractorComponentName());
695 } else {
Jason Monkb59f46f2016-09-27 12:29:18 -0400696 mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent());
Selim Cineke70d6532015-04-24 16:46:13 -0700697 }
698 if (mLeftPreview != null) {
699 mPreviewContainer.addView(mLeftPreview);
700 mLeftPreview.setVisibility(View.INVISIBLE);
701 }
Jorim Jaggidadafd42016-09-30 07:20:25 -0700702 if (mAffordanceHelper != null) {
703 mAffordanceHelper.updatePreviews();
704 }
Selim Cineke70d6532015-04-24 16:46:13 -0700705 }
706
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100707 public void startFinishDozeAnimation() {
708 long delay = 0;
Selim Cineke70d6532015-04-24 16:46:13 -0700709 if (mLeftAffordanceView.getVisibility() == View.VISIBLE) {
710 startFinishDozeAnimationElement(mLeftAffordanceView, delay);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100711 delay += DOZE_ANIMATION_STAGGER_DELAY;
712 }
713 startFinishDozeAnimationElement(mLockIcon, delay);
714 delay += DOZE_ANIMATION_STAGGER_DELAY;
Jason Monkb59f46f2016-09-27 12:29:18 -0400715 if (mRightAffordanceView.getVisibility() == View.VISIBLE) {
716 startFinishDozeAnimationElement(mRightAffordanceView, delay);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100717 }
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100718 }
719
720 private void startFinishDozeAnimationElement(View element, long delay) {
721 element.setAlpha(0f);
722 element.setTranslationY(element.getHeight() / 2);
723 element.animate()
724 .alpha(1f)
725 .translationY(0f)
Selim Cinekc18010f2016-01-20 13:41:30 -0800726 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100727 .setStartDelay(delay)
728 .setDuration(DOZE_ANIMATION_ELEMENT_DURATION);
729 }
730
Adrian Roosa06905b2014-05-28 12:13:48 +0200731 private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
Jim Millerb29814c2015-08-05 19:03:01 -0700732 @Override
Adrian Roosa06905b2014-05-28 12:13:48 +0200733 public void onReceive(Context context, Intent intent) {
734 post(new Runnable() {
735 @Override
736 public void run() {
737 updateCameraVisibility();
738 }
739 });
740 }
741 };
742
743 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
744 new KeyguardUpdateMonitorCallback() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400745 @Override
746 public void onUserSwitchComplete(int userId) {
747 updateCameraVisibility();
748 }
Jorim Jaggie7b12522014-08-06 16:41:21 +0200749
Jason Monkb59f46f2016-09-27 12:29:18 -0400750 @Override
751 public void onStartedWakingUp() {
752 mLockIcon.setDeviceInteractive(true);
753 }
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200754
Jason Monkb59f46f2016-09-27 12:29:18 -0400755 @Override
756 public void onFinishedGoingToSleep(int why) {
757 mLockIcon.setDeviceInteractive(false);
758 }
Adrian Roosb9ae0902014-10-27 14:20:30 +0100759
Jason Monkb59f46f2016-09-27 12:29:18 -0400760 @Override
761 public void onScreenTurnedOn() {
762 mLockIcon.setScreenOn(true);
763 }
Jorim Jaggif1518da2015-07-30 11:56:36 -0700764
Jason Monkb59f46f2016-09-27 12:29:18 -0400765 @Override
766 public void onScreenTurnedOff() {
767 mLockIcon.setScreenOn(false);
768 }
Jorim Jaggif1518da2015-07-30 11:56:36 -0700769
Jason Monkb59f46f2016-09-27 12:29:18 -0400770 @Override
771 public void onKeyguardVisibilityChanged(boolean showing) {
772 mLockIcon.update();
773 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700774
Jason Monkb59f46f2016-09-27 12:29:18 -0400775 @Override
776 public void onFingerprintRunningStateChanged(boolean running) {
777 mLockIcon.update();
778 }
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700779
Jason Monkb59f46f2016-09-27 12:29:18 -0400780 @Override
781 public void onStrongAuthStateChanged(int userId) {
782 mLockIcon.update();
Adrian Roosa06905b2014-05-28 12:13:48 +0200783 }
784
Jorim Jaggi90f62792016-10-07 15:11:44 +0200785 @Override
786 public void onUserUnlocked() {
787 inflateCameraPreview();
788 updateCameraVisibility();
789 updateLeftAffordance();
Jason Monkb59f46f2016-09-27 12:29:18 -0400790 }
791 };
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200792
793 public void setKeyguardIndicationController(
794 KeyguardIndicationController keyguardIndicationController) {
795 mIndicationController = keyguardIndicationController;
796 }
Selim Cineke70d6532015-04-24 16:46:13 -0700797
Selim Cineke70d6532015-04-24 16:46:13 -0700798 public void updateLeftAffordance() {
799 updateLeftAffordanceIcon();
800 updateLeftPreview();
801 }
Selim Cinek5f145022016-08-02 16:00:12 -0700802
803 public void onKeyguardShowingChanged() {
804 updateLeftAffordance();
805 inflateCameraPreview();
806 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400807
808 private void setRightButton(IntentButton button) {
Jason Monk1d9632d2017-02-09 13:20:04 -0800809 mRightButton = button;
Jason Monkb59f46f2016-09-27 12:29:18 -0400810 updateRightAffordanceIcon();
811 updateCameraVisibility();
812 inflateCameraPreview();
813 }
814
815 private void setLeftButton(IntentButton button) {
Jason Monk1d9632d2017-02-09 13:20:04 -0800816 mLeftButton = button;
817 if (!(mLeftButton instanceof DefaultLeftButton)) {
818 mLeftIsVoiceAssist = false;
819 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400820 updateLeftAffordance();
821 }
822
Adrian Roos91ba3072017-02-14 16:50:46 +0100823 public void setDozing(boolean dozing, boolean animate) {
824 mDozing = dozing;
825
826 updateCameraVisibility();
827 updateLeftAffordanceIcon();
828
829 if (dozing) {
830 mLockIcon.setVisibility(INVISIBLE);
Philip Quinnb86efa42017-07-08 12:59:24 -0700831 mOverlayContainer.setVisibility(INVISIBLE);
Adrian Roos91ba3072017-02-14 16:50:46 +0100832 } else {
833 mLockIcon.setVisibility(VISIBLE);
Philip Quinnb86efa42017-07-08 12:59:24 -0700834 mOverlayContainer.setVisibility(VISIBLE);
Adrian Roos91ba3072017-02-14 16:50:46 +0100835 if (animate) {
836 startFinishDozeAnimation();
837 }
838 }
839 }
840
Lucas Dupin4272f442018-01-13 22:00:35 -0800841 public void dozeTimeTick() {
842 if (mDarkAmount == 1) {
843 // Move indication every minute to avoid burn-in
844 final int dozeTranslation = mIndicationBottomMargin - mIndicationBottomMarginAmbient;
845 mIndicationArea.setTranslationY(dozeTranslation + (float) Math.random() * 5);
846 }
847 }
848
849 public void setBurnInXOffset(int burnInXOffset) {
850 if (mBurnInXOffset == burnInXOffset) {
851 return;
852 }
853 mBurnInXOffset = burnInXOffset;
854 mIndicationArea.setTranslationX(burnInXOffset);
855 }
856
Jason Monkb59f46f2016-09-27 12:29:18 -0400857 private class DefaultLeftButton implements IntentButton {
858
859 private IconState mIconState = new IconState();
860
861 @Override
862 public IconState getIcon() {
863 mLeftIsVoiceAssist = canLaunchVoiceAssist();
Lucas Dupinf78c5402018-01-05 12:57:27 -0800864 final boolean showAffordance =
865 getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance);
Jason Monkb59f46f2016-09-27 12:29:18 -0400866 if (mLeftIsVoiceAssist) {
Lucas Dupinf78c5402018-01-05 12:57:27 -0800867 mIconState.isVisible = mUserSetupComplete && showAffordance;
Evan Roskyd388c752016-11-15 13:59:06 -0800868 if (mLeftAssistIcon == null) {
869 mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
870 } else {
871 mIconState.drawable = mLeftAssistIcon;
872 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400873 mIconState.contentDescription = mContext.getString(
874 R.string.accessibility_voice_assist_button);
875 } else {
Lucas Dupinf78c5402018-01-05 12:57:27 -0800876 mIconState.isVisible = mUserSetupComplete && showAffordance && isPhoneVisible();
Jason Monkb59f46f2016-09-27 12:29:18 -0400877 mIconState.drawable = mContext.getDrawable(R.drawable.ic_phone_24dp);
878 mIconState.contentDescription = mContext.getString(
879 R.string.accessibility_phone_button);
880 }
881 return mIconState;
882 }
883
884 @Override
885 public Intent getIntent() {
886 return PHONE_INTENT;
887 }
888 }
889
890 private class DefaultRightButton implements IntentButton {
891
892 private IconState mIconState = new IconState();
893
894 @Override
895 public IconState getIcon() {
896 ResolveInfo resolved = resolveCameraIntent();
Esteban Talavera40f8b992017-07-14 16:14:07 +0100897 boolean isCameraDisabled = (mStatusBar != null) && !mStatusBar.isCameraAllowedByAdmin();
898 mIconState.isVisible = !isCameraDisabled && resolved != null
Jason Monkb59f46f2016-09-27 12:29:18 -0400899 && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
900 && mUserSetupComplete;
901 mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
902 mIconState.contentDescription =
903 mContext.getString(R.string.accessibility_camera_button);
904 return mIconState;
905 }
906
907 @Override
908 public Intent getIntent() {
909 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
910 boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer(
911 KeyguardUpdateMonitor.getCurrentUser());
912 boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
913 return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
914 }
915 }
Adrian Roos7e58a082018-03-09 16:40:56 +0100916
917 @Override
918 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
919 int bottom = insets.getDisplayCutout() != null
920 ? insets.getDisplayCutout().getSafeInsetBottom() : 0;
921 if (isPaddingRelative()) {
922 setPaddingRelative(getPaddingStart(), getPaddingTop(), getPaddingEnd(), bottom);
923 } else {
924 setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottom);
925 }
926 return insets;
927 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200928}