blob: d95d2b7db4c9c6f9385e50e4229cfa44ea154d01 [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
Lucas Dupin07ed3df2019-03-26 21:23:59 -070022import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
Jason Monk1d9632d2017-02-09 13:20:04 -080023import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
Jason Monkd6fa02f2017-01-25 18:26:50 -050024import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
Jason Monk1d9632d2017-02-09 13:20:04 -080025import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON;
Jason Monkd6fa02f2017-01-25 18:26:50 -050026import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK;
Selim Cinek5f145022016-08-02 16:00:12 -070027
Jorim Jaggid9449862015-05-29 14:49:08 -070028import android.app.ActivityManager;
Robert Carrfd10cd12016-06-29 16:41:50 -070029import android.app.ActivityOptions;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070030import android.app.ActivityTaskManager;
Jorim Jaggia6310292014-04-16 14:11:52 +020031import android.app.admin.DevicePolicyManager;
32import android.content.BroadcastReceiver;
Jorim Jaggid9449862015-05-29 14:49:08 -070033import android.content.ComponentName;
Jorim Jaggia6310292014-04-16 14:11:52 +020034import android.content.Context;
35import android.content.Intent;
36import android.content.IntentFilter;
Jorim Jaggid9449862015-05-29 14:49:08 -070037import android.content.ServiceConnection;
38import android.content.pm.ActivityInfo;
Jorim Jaggi97b63c42014-05-02 23:03:34 +020039import android.content.pm.PackageManager;
Adrian Roosa06905b2014-05-28 12:13:48 +020040import android.content.pm.ResolveInfo;
Jorim Jaggie210cc82014-08-12 23:44:59 +020041import android.content.res.Configuration;
Evan Roskyd388c752016-11-15 13:59:06 -080042import android.graphics.drawable.Drawable;
Yorke Lee583a20242014-08-12 18:47:08 -070043import android.os.AsyncTask;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020044import android.os.Bundle;
Jorim Jaggid9449862015-05-29 14:49:08 -070045import android.os.IBinder;
46import android.os.Message;
47import android.os.Messenger;
Jorim Jaggia6310292014-04-16 14:11:52 +020048import android.os.RemoteException;
49import android.os.UserHandle;
50import android.provider.MediaStore;
Jorim Jaggid9449862015-05-29 14:49:08 -070051import android.service.media.CameraPrewarmService;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070052import android.telecom.TelecomManager;
Jason Monkd6fa02f2017-01-25 18:26:50 -050053import android.text.TextUtils;
Jorim Jaggia6310292014-04-16 14:11:52 +020054import android.util.AttributeSet;
55import android.util.Log;
Jorim Jaggie210cc82014-08-12 23:44:59 +020056import android.util.TypedValue;
Jorim Jaggia6310292014-04-16 14:11:52 +020057import android.view.View;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020058import android.view.ViewGroup;
Adrian Roos7e58a082018-03-09 16:40:56 +010059import android.view.WindowInsets;
Robert Carrfd10cd12016-06-29 16:41:50 -070060import android.view.WindowManager;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020061import android.view.accessibility.AccessibilityNodeInfo;
Jorim Jaggia6310292014-04-16 14:11:52 +020062import android.widget.FrameLayout;
Jorim Jaggie210cc82014-08-12 23:44:59 +020063import android.widget.TextView;
Adrian Roosa06905b2014-05-28 12:13:48 +020064
Lucas Dupincea7dee2018-10-16 12:43:37 -070065import com.android.internal.annotations.VisibleForTesting;
Adrian Roosa06905b2014-05-28 12:13:48 +020066import com.android.internal.widget.LockPatternUtils;
67import com.android.keyguard.KeyguardUpdateMonitor;
68import com.android.keyguard.KeyguardUpdateMonitorCallback;
Mark Renouf6b2331c2019-03-21 13:40:08 -040069import com.android.systemui.ActivityIntentHelper;
Jason Monk9c7844c2017-01-18 15:21:53 -050070import com.android.systemui.Dependency;
Winsonc0d70582016-01-29 10:24:39 -080071import com.android.systemui.Interpolators;
Jorim Jaggia6310292014-04-16 14:11:52 +020072import com.android.systemui.R;
Selim Cineke70d6532015-04-24 16:46:13 -070073import com.android.systemui.assist.AssistManager;
Lucas Dupin117365d2018-10-03 15:49:46 -070074import com.android.systemui.plugins.ActivityStarter;
Jason Monkb59f46f2016-09-27 12:29:18 -040075import com.android.systemui.plugins.IntentButtonProvider;
76import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
77import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState;
Selim Cinekbaa23272014-07-08 18:01:07 +020078import com.android.systemui.statusbar.KeyguardAffordanceView;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020079import com.android.systemui.statusbar.policy.AccessibilityController;
Jason Monk1d9632d2017-02-09 13:20:04 -080080import com.android.systemui.statusbar.policy.ExtensionController;
81import com.android.systemui.statusbar.policy.ExtensionController.Extension;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020082import com.android.systemui.statusbar.policy.FlashlightController;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040083import com.android.systemui.statusbar.policy.KeyguardStateController;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020084import com.android.systemui.statusbar.policy.PreviewInflater;
Jason Monk1d9632d2017-02-09 13:20:04 -080085import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory;
Jason Monkd6fa02f2017-01-25 18:26:50 -050086import com.android.systemui.tuner.TunerService;
Jorim Jaggia6310292014-04-16 14:11:52 +020087
88/**
89 * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
90 * text.
91 */
Selim Cinek4c6969a2014-05-26 19:22:17 +020092public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
Lucas Dupinc8f16e82019-09-17 18:24:50 -040093 KeyguardStateController.Callback,
Lucas Dupin2e838ac2019-04-17 16:50:58 -070094 AccessibilityController.AccessibilityStateChangedCallback {
Jorim Jaggia6310292014-04-16 14:11:52 +020095
Jason Monk2a6ea9c2017-01-26 11:14:51 -050096 final static String TAG = "StatusBar/KeyguardBottomAreaView";
Jorim Jaggia6310292014-04-16 14:11:52 +020097
Jorim Jaggi40aa8812015-09-23 12:59:22 -070098 public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance";
99 public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture";
100 public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap";
Jonathan Solnita4138162017-05-10 21:06:04 -0700101 public static final String CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = "lift_to_launch_ml";
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700102
103 public static final String EXTRA_CAMERA_LAUNCH_SOURCE
104 = "com.android.systemui.camera_launch_source";
105
Jason Monkb59f46f2016-09-27 12:29:18 -0400106 private static final String LEFT_BUTTON_PLUGIN
107 = "com.android.systemui.action.PLUGIN_LOCKSCREEN_LEFT_BUTTON";
108 private static final String RIGHT_BUTTON_PLUGIN
109 = "com.android.systemui.action.PLUGIN_LOCKSCREEN_RIGHT_BUTTON";
110
Adrian Roosa06905b2014-05-28 12:13:48 +0200111 private static final Intent SECURE_CAMERA_INTENT =
112 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
113 .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Selim Cinek372d1bd2015-08-14 13:19:37 -0700114 public static final Intent INSECURE_CAMERA_INTENT =
Adrian Roosa06905b2014-05-28 12:13:48 +0200115 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200116 private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100117 private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
118 private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200119
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700120 private final boolean mShowLeftAffordance;
121 private final boolean mShowCameraAffordance;
122
Jason Monkb59f46f2016-09-27 12:29:18 -0400123 private KeyguardAffordanceView mRightAffordanceView;
Selim Cineke70d6532015-04-24 16:46:13 -0700124 private KeyguardAffordanceView mLeftAffordanceView;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100125 private ViewGroup mIndicationArea;
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;
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400134 private KeyguardStateController mKeyguardStateController;
Adrian Roos1e1d6ac2014-07-22 17:18:55 +0200135 private FlashlightController mFlashlightController;
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200136 private PreviewInflater mPreviewInflater;
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200137 private AccessibilityController mAccessibilityController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500138 private StatusBar mStatusBar;
Jorim Jaggidadafd42016-09-30 07:20:25 -0700139 private KeyguardAffordanceHelper mAffordanceHelper;
Adrian Roos2fe592d2014-05-17 03:11:59 +0200140
Adrian Roosa4eba9f2015-07-22 18:13:04 -0700141 private boolean mUserSetupComplete;
Jorim Jaggid9449862015-05-29 14:49:08 -0700142 private boolean mPrewarmBound;
143 private Messenger mPrewarmMessenger;
144 private final ServiceConnection mPrewarmConnection = new ServiceConnection() {
145
146 @Override
147 public void onServiceConnected(ComponentName name, IBinder service) {
148 mPrewarmMessenger = new Messenger(service);
Jorim Jaggid9449862015-05-29 14:49:08 -0700149 }
150
151 @Override
152 public void onServiceDisconnected(ComponentName name) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700153 mPrewarmMessenger = null;
154 }
155 };
156
Selim Cineke70d6532015-04-24 16:46:13 -0700157 private boolean mLeftIsVoiceAssist;
158 private AssistManager mAssistManager;
Evan Roskyd388c752016-11-15 13:59:06 -0800159 private Drawable mLeftAssistIcon;
Adrian Roos72cc3702014-09-18 17:25:09 +0200160
Jason Monkb59f46f2016-09-27 12:29:18 -0400161 private IntentButton mRightButton = new DefaultRightButton();
Jason Monk1d9632d2017-02-09 13:20:04 -0800162 private Extension<IntentButton> mRightExtension;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500163 private String mRightButtonStr;
Jason Monkb59f46f2016-09-27 12:29:18 -0400164 private IntentButton mLeftButton = new DefaultLeftButton();
Jason Monk1d9632d2017-02-09 13:20:04 -0800165 private Extension<IntentButton> mLeftExtension;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500166 private String mLeftButtonStr;
Adrian Roos91ba3072017-02-14 16:50:46 +0100167 private boolean mDozing;
Lucas Dupin4272f442018-01-13 22:00:35 -0800168 private int mIndicationBottomMargin;
Lucas Dupin4272f442018-01-13 22:00:35 -0800169 private float mDarkAmount;
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700170 private int mBurnInXOffset;
171 private int mBurnInYOffset;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400172 private ActivityIntentHelper mActivityIntentHelper;
Jason Monkb59f46f2016-09-27 12:29:18 -0400173
Jorim Jaggia6310292014-04-16 14:11:52 +0200174 public KeyguardBottomAreaView(Context context) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200175 this(context, null);
Jorim Jaggia6310292014-04-16 14:11:52 +0200176 }
177
178 public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200179 this(context, attrs, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200180 }
181
182 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200183 this(context, attrs, defStyleAttr, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200184 }
185
186 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
187 int defStyleRes) {
188 super(context, attrs, defStyleAttr, defStyleRes);
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700189 mShowLeftAffordance = getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance);
190 mShowCameraAffordance = getResources()
191 .getBoolean(R.bool.config_keyguardShowCameraAffordance);
Jorim Jaggia6310292014-04-16 14:11:52 +0200192 }
193
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200194 private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
195 @Override
196 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
197 super.onInitializeAccessibilityNodeInfo(host, info);
198 String label = null;
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700199 if (host == mRightAffordanceView) {
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200200 label = getResources().getString(R.string.camera_label);
Selim Cineke70d6532015-04-24 16:46:13 -0700201 } else if (host == mLeftAffordanceView) {
202 if (mLeftIsVoiceAssist) {
203 label = getResources().getString(R.string.voice_assist_label);
204 } else {
205 label = getResources().getString(R.string.phone_label);
206 }
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200207 }
208 info.addAction(new AccessibilityAction(ACTION_CLICK, label));
209 }
210
211 @Override
212 public boolean performAccessibilityAction(View host, int action, Bundle args) {
213 if (action == ACTION_CLICK) {
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700214 if (host == mRightAffordanceView) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700215 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200216 return true;
Selim Cineke70d6532015-04-24 16:46:13 -0700217 } else if (host == mLeftAffordanceView) {
218 launchLeftAffordance();
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200219 return true;
220 }
221 }
222 return super.performAccessibilityAction(host, action, args);
223 }
224 };
225
Lucas Dupincea7dee2018-10-16 12:43:37 -0700226 public void initFrom(KeyguardBottomAreaView oldBottomArea) {
Lucas Dupincea7dee2018-10-16 12:43:37 -0700227 setStatusBar(oldBottomArea.mStatusBar);
228 }
229
Jorim Jaggia6310292014-04-16 14:11:52 +0200230 @Override
231 protected void onFinishInflate() {
232 super.onFinishInflate();
Mark Renouf6b2331c2019-03-21 13:40:08 -0400233 mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext),
234 new ActivityIntentHelper(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);
Alan Viverette51efddb2017-04-05 10:00:01 -0400239 mIndicationArea = findViewById(R.id.keyguard_indication_area);
Alan Viverette51efddb2017-04-05 10:00:01 -0400240 mIndicationText = findViewById(R.id.keyguard_indication_text);
Lucas Dupin4272f442018-01-13 22:00:35 -0800241 mIndicationBottomMargin = getResources().getDimensionPixelSize(
242 R.dimen.keyguard_indication_margin_bottom);
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700243 mBurnInYOffset = getResources().getDimensionPixelSize(
244 R.dimen.default_burn_in_prevention_offset);
Jorim Jaggia6310292014-04-16 14:11:52 +0200245 updateCameraVisibility();
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400246 mKeyguardStateController = Dependency.get(KeyguardStateController.class);
247 mKeyguardStateController.addCallback(this);
Selim Cinekbaa23272014-07-08 18:01:07 +0200248 setClipChildren(false);
249 setClipToPadding(false);
Selim Cineke70d6532015-04-24 16:46:13 -0700250 inflateCameraPreview();
Jason Monkb59f46f2016-09-27 12:29:18 -0400251 mRightAffordanceView.setOnClickListener(this);
Selim Cineke70d6532015-04-24 16:46:13 -0700252 mLeftAffordanceView.setOnClickListener(this);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200253 initAccessibility();
Jason Monk9c7844c2017-01-18 15:21:53 -0500254 mActivityStarter = Dependency.get(ActivityStarter.class);
255 mFlashlightController = Dependency.get(FlashlightController.class);
256 mAccessibilityController = Dependency.get(AccessibilityController.class);
257 mAssistManager = Dependency.get(AssistManager.class);
Mark Renouf6b2331c2019-03-21 13:40:08 -0400258 mActivityIntentHelper = new ActivityIntentHelper(getContext());
Jason Monk9c7844c2017-01-18 15:21:53 -0500259 updateLeftAffordance();
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200260 }
261
Jason Monkb59f46f2016-09-27 12:29:18 -0400262 @Override
263 protected void onAttachedToWindow() {
264 super.onAttachedToWindow();
Jason Monk9ef73072017-01-27 13:32:51 -0500265 mAccessibilityController.addStateChangedCallback(this);
Jason Monk1d9632d2017-02-09 13:20:04 -0800266 mRightExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
267 .withPlugin(IntentButtonProvider.class, RIGHT_BUTTON_PLUGIN,
268 p -> p.getIntentButton())
269 .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_RIGHT_BUTTON))
270 .withDefault(() -> new DefaultRightButton())
271 .withCallback(button -> setRightButton(button))
272 .build();
273 mLeftExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
274 .withPlugin(IntentButtonProvider.class, LEFT_BUTTON_PLUGIN,
275 p -> p.getIntentButton())
276 .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_LEFT_BUTTON))
277 .withDefault(() -> new DefaultLeftButton())
278 .withCallback(button -> setLeftButton(button))
279 .build();
Selim Cinek9a105312017-07-21 17:16:05 -0700280 final IntentFilter filter = new IntentFilter();
281 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
282 getContext().registerReceiverAsUser(mDevicePolicyReceiver,
283 UserHandle.ALL, filter, null, null);
Dave Mankoffe2294692019-08-14 11:53:13 -0400284 Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mUpdateMonitorCallback);
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400285 mKeyguardStateController.addCallback(this);
Jason Monkb59f46f2016-09-27 12:29:18 -0400286 }
287
288 @Override
289 protected void onDetachedFromWindow() {
290 super.onDetachedFromWindow();
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400291 mKeyguardStateController.removeCallback(this);
Jason Monk9ef73072017-01-27 13:32:51 -0500292 mAccessibilityController.removeStateChangedCallback(this);
Jason Monk1d9632d2017-02-09 13:20:04 -0800293 mRightExtension.destroy();
294 mLeftExtension.destroy();
Selim Cinek9a105312017-07-21 17:16:05 -0700295 getContext().unregisterReceiver(mDevicePolicyReceiver);
Dave Mankoffe2294692019-08-14 11:53:13 -0400296 Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mUpdateMonitorCallback);
Jason Monkb59f46f2016-09-27 12:29:18 -0400297 }
298
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200299 private void initAccessibility() {
Selim Cineke70d6532015-04-24 16:46:13 -0700300 mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
Jason Monkb59f46f2016-09-27 12:29:18 -0400301 mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
Jorim Jaggia6310292014-04-16 14:11:52 +0200302 }
303
Jorim Jaggie210cc82014-08-12 23:44:59 +0200304 @Override
305 protected void onConfigurationChanged(Configuration newConfig) {
306 super.onConfigurationChanged(newConfig);
Lucas Dupin4272f442018-01-13 22:00:35 -0800307 mIndicationBottomMargin = getResources().getDimensionPixelSize(
Jorim Jaggie210cc82014-08-12 23:44:59 +0200308 R.dimen.keyguard_indication_margin_bottom);
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700309 mBurnInYOffset = getResources().getDimensionPixelSize(
310 R.dimen.default_burn_in_prevention_offset);
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100311 MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams();
Lucas Dupin4272f442018-01-13 22:00:35 -0800312 if (mlp.bottomMargin != mIndicationBottomMargin) {
313 mlp.bottomMargin = mIndicationBottomMargin;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100314 mIndicationArea.setLayoutParams(mlp);
Jorim Jaggie210cc82014-08-12 23:44:59 +0200315 }
316
317 // Respect font size setting.
318 mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
319 getResources().getDimensionPixelSize(
320 com.android.internal.R.dimen.text_size_small_material));
Selim Cinek6ebba592016-05-31 15:28:28 -0700321
Jason Monkb59f46f2016-09-27 12:29:18 -0400322 ViewGroup.LayoutParams lp = mRightAffordanceView.getLayoutParams();
Selim Cinek6ebba592016-05-31 15:28:28 -0700323 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
324 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
Jason Monkb59f46f2016-09-27 12:29:18 -0400325 mRightAffordanceView.setLayoutParams(lp);
326 updateRightAffordanceIcon();
Selim Cinek6ebba592016-05-31 15:28:28 -0700327
Selim Cinek6ebba592016-05-31 15:28:28 -0700328 lp = mLeftAffordanceView.getLayoutParams();
329 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
330 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
331 mLeftAffordanceView.setLayoutParams(lp);
332 updateLeftAffordanceIcon();
Jorim Jaggie210cc82014-08-12 23:44:59 +0200333 }
334
Jason Monkb59f46f2016-09-27 12:29:18 -0400335 private void updateRightAffordanceIcon() {
336 IconState state = mRightButton.getIcon();
Adrian Roos674b8ea2017-05-25 12:33:17 -0700337 mRightAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE);
Lucas Dupin3704d532019-04-18 19:23:06 -0700338 if (state.drawable != mRightAffordanceView.getDrawable()
339 || state.tint != mRightAffordanceView.shouldTint()) {
340 mRightAffordanceView.setImageDrawable(state.drawable, state.tint);
341 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400342 mRightAffordanceView.setContentDescription(state.contentDescription);
343 }
344
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500345 public void setStatusBar(StatusBar statusBar) {
346 mStatusBar = statusBar;
Dan Sandlere163a642015-03-01 22:58:32 -0500347 updateCameraVisibility(); // in case onFinishInflate() was called too early
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200348 }
349
Jorim Jaggidadafd42016-09-30 07:20:25 -0700350 public void setAffordanceHelper(KeyguardAffordanceHelper affordanceHelper) {
351 mAffordanceHelper = affordanceHelper;
352 }
353
Adrian Roosa4eba9f2015-07-22 18:13:04 -0700354 public void setUserSetupComplete(boolean userSetupComplete) {
355 mUserSetupComplete = userSetupComplete;
356 updateCameraVisibility();
357 updateLeftAffordanceIcon();
358 }
359
Adrian Roosa06905b2014-05-28 12:13:48 +0200360 private Intent getCameraIntent() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400361 return mRightButton.getIntent();
Adrian Roosa06905b2014-05-28 12:13:48 +0200362 }
363
Zhentao Sun04f97402015-08-26 17:37:30 -0700364 /**
365 * Resolves the intent to launch the camera application.
366 */
367 public ResolveInfo resolveCameraIntent() {
Lucas Dupinc8add512019-08-28 12:08:58 -0700368 return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
369 PackageManager.MATCH_DEFAULT_ONLY,
370 KeyguardUpdateMonitor.getCurrentUser());
Zhentao Sun04f97402015-08-26 17:37:30 -0700371 }
372
Jorim Jaggia6310292014-04-16 14:11:52 +0200373 private void updateCameraVisibility() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400374 if (mRightAffordanceView == null) {
Dan Sandlere163a642015-03-01 22:58:32 -0500375 // Things are not set up yet; reply hazy, ask again later
376 return;
377 }
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700378 mRightAffordanceView.setVisibility(!mDozing && mShowCameraAffordance
379 && mRightButton.getIcon().isVisible ? View.VISIBLE : View.GONE);
Jorim Jaggia6310292014-04-16 14:11:52 +0200380 }
381
Evan Roskyd388c752016-11-15 13:59:06 -0800382 /**
383 * Set an alternate icon for the left assist affordance (replace the mic icon)
384 */
385 public void setLeftAssistIcon(Drawable drawable) {
386 mLeftAssistIcon = drawable;
387 updateLeftAffordanceIcon();
388 }
389
Selim Cineke70d6532015-04-24 16:46:13 -0700390 private void updateLeftAffordanceIcon() {
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700391 if (!mShowLeftAffordance || mDozing) {
392 mLeftAffordanceView.setVisibility(GONE);
393 return;
394 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400395 IconState state = mLeftButton.getIcon();
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700396 mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE);
Lucas Dupin3704d532019-04-18 19:23:06 -0700397 if (state.drawable != mLeftAffordanceView.getDrawable()
398 || state.tint != mLeftAffordanceView.shouldTint()) {
399 mLeftAffordanceView.setImageDrawable(state.drawable, state.tint);
400 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400401 mLeftAffordanceView.setContentDescription(state.contentDescription);
Selim Cineke70d6532015-04-24 16:46:13 -0700402 }
403
404 public boolean isLeftVoiceAssist() {
405 return mLeftIsVoiceAssist;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200406 }
407
408 private boolean isPhoneVisible() {
409 PackageManager pm = mContext.getPackageManager();
410 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
411 && pm.resolveActivity(PHONE_INTENT, 0) != null;
412 }
413
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200414 @Override
415 public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
Jason Monkb59f46f2016-09-27 12:29:18 -0400416 mRightAffordanceView.setClickable(touchExplorationEnabled);
Selim Cineke70d6532015-04-24 16:46:13 -0700417 mLeftAffordanceView.setClickable(touchExplorationEnabled);
Jason Monkb59f46f2016-09-27 12:29:18 -0400418 mRightAffordanceView.setFocusable(accessibilityEnabled);
Selim Cineke70d6532015-04-24 16:46:13 -0700419 mLeftAffordanceView.setFocusable(accessibilityEnabled);
Jorim Jaggia6310292014-04-16 14:11:52 +0200420 }
421
Selim Cinek4c6969a2014-05-26 19:22:17 +0200422 @Override
423 public void onClick(View v) {
Jason Monkb59f46f2016-09-27 12:29:18 -0400424 if (v == mRightAffordanceView) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700425 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
Selim Cineke70d6532015-04-24 16:46:13 -0700426 } else if (v == mLeftAffordanceView) {
427 launchLeftAffordance();
Selim Cinek4c6969a2014-05-26 19:22:17 +0200428 }
429 }
430
Jorim Jaggid9449862015-05-29 14:49:08 -0700431 public void bindCameraPrewarmService() {
Adrian Roosa06905b2014-05-28 12:13:48 +0200432 Intent intent = getCameraIntent();
Mark Renouf6b2331c2019-03-21 13:40:08 -0400433 ActivityInfo targetInfo = mActivityIntentHelper.getTargetActivityInfo(intent,
Selim Cinek5f145022016-08-02 16:00:12 -0700434 KeyguardUpdateMonitor.getCurrentUser(), true /* onlyDirectBootAware */);
Jorim Jaggi8b8fa3e2015-08-18 18:33:49 -0700435 if (targetInfo != null && targetInfo.metaData != null) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700436 String clazz = targetInfo.metaData.getString(
437 MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE);
438 if (clazz != null) {
439 Intent serviceIntent = new Intent();
440 serviceIntent.setClassName(targetInfo.packageName, clazz);
441 serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM);
442 try {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700443 if (getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection,
Selim Cinekedf47482015-09-01 18:05:08 -0700444 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
445 new UserHandle(UserHandle.USER_CURRENT))) {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700446 mPrewarmBound = true;
447 }
Jorim Jaggid9449862015-05-29 14:49:08 -0700448 } catch (SecurityException e) {
449 Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName
450 + " class=" + clazz, e);
451 }
452 }
Jorim Jaggia86790b2015-04-02 16:32:29 -0700453 }
454 }
455
Jorim Jaggid9449862015-05-29 14:49:08 -0700456 public void unbindCameraPrewarmService(boolean launched) {
457 if (mPrewarmBound) {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700458 if (mPrewarmMessenger != null && launched) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700459 try {
460 mPrewarmMessenger.send(Message.obtain(null /* handler */,
461 CameraPrewarmService.MSG_CAMERA_FIRED));
462 } catch (RemoteException e) {
463 Log.w(TAG, "Error sending camera fired message", e);
464 }
465 }
466 mContext.unbindService(mPrewarmConnection);
467 mPrewarmBound = false;
Jorim Jaggia86790b2015-04-02 16:32:29 -0700468 }
469 }
470
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700471 public void launchCamera(String source) {
Jorim Jaggia86790b2015-04-02 16:32:29 -0700472 final Intent intent = getCameraIntent();
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700473 intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
Mark Renouf6b2331c2019-03-21 13:40:08 -0400474 boolean wouldLaunchResolverActivity = mActivityIntentHelper.wouldLaunchResolverActivity(
475 intent, KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200476 if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
Jorim Jaggia86790b2015-04-02 16:32:29 -0700477 AsyncTask.execute(new Runnable() {
478 @Override
479 public void run() {
Jorim Jaggid9449862015-05-29 14:49:08 -0700480 int result = ActivityManager.START_CANCELED;
Robert Carrfd10cd12016-06-29 16:41:50 -0700481
482 // Normally an activity will set it's requested rotation
483 // animation on its window. However when launching an activity
484 // causes the orientation to change this is too late. In these cases
485 // the default animation is used. This doesn't look good for
486 // the camera (as it rotates the camera contents out of sync
487 // with physical reality). So, we ask the WindowManager to
488 // force the crossfade animation if an orientation change
489 // happens to occur during the launch.
490 ActivityOptions o = ActivityOptions.makeBasic();
Winson Chungf7e03e12017-08-22 11:32:16 -0700491 o.setDisallowEnterPictureInPictureWhileLaunching(true);
Robert Carrfd10cd12016-06-29 16:41:50 -0700492 o.setRotationAnimationHint(
Robert Carr57d9fbd2016-08-15 12:00:35 -0700493 WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
Jorim Jaggid9449862015-05-29 14:49:08 -0700494 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700495 result = ActivityTaskManager.getService().startActivityAsUser(
Jorim Jaggid9449862015-05-29 14:49:08 -0700496 null, getContext().getBasePackageName(),
497 intent,
498 intent.resolveTypeIfNeeded(getContext().getContentResolver()),
Robert Carrfd10cd12016-06-29 16:41:50 -0700499 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, o.toBundle(),
Jorim Jaggid9449862015-05-29 14:49:08 -0700500 UserHandle.CURRENT.getIdentifier());
501 } catch (RemoteException e) {
502 Log.w(TAG, "Unable to start camera activity", e);
503 }
Jorim Jaggid9449862015-05-29 14:49:08 -0700504 final boolean launched = isSuccessfulLaunch(result);
505 post(new Runnable() {
506 @Override
507 public void run() {
508 unbindCameraPrewarmService(launched);
509 }
510 });
Jorim Jaggia86790b2015-04-02 16:32:29 -0700511 }
512 });
Adrian Roosa06905b2014-05-28 12:13:48 +0200513 } else {
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200514
515 // We need to delay starting the activity because ResolverActivity finishes itself if
516 // launched behind lockscreen.
Jorim Jaggid9449862015-05-29 14:49:08 -0700517 mActivityStarter.startActivity(intent, false /* dismissShade */,
518 new ActivityStarter.Callback() {
519 @Override
520 public void onActivityStarted(int resultCode) {
521 unbindCameraPrewarmService(isSuccessfulLaunch(resultCode));
522 }
523 });
Adrian Roosa06905b2014-05-28 12:13:48 +0200524 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200525 }
526
Lucas Dupin4272f442018-01-13 22:00:35 -0800527 public void setDarkAmount(float darkAmount) {
528 if (darkAmount == mDarkAmount) {
529 return;
530 }
531 mDarkAmount = darkAmount;
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700532 dozeTimeTick();
Lucas Dupinf22194f2018-12-26 11:43:57 -0800533 }
534
Jorim Jaggid9449862015-05-29 14:49:08 -0700535 private static boolean isSuccessfulLaunch(int result) {
536 return result == ActivityManager.START_SUCCESS
537 || result == ActivityManager.START_DELIVERED_TO_TOP
538 || result == ActivityManager.START_TASK_TO_FRONT;
539 }
540
Selim Cineke70d6532015-04-24 16:46:13 -0700541 public void launchLeftAffordance() {
542 if (mLeftIsVoiceAssist) {
543 launchVoiceAssist();
544 } else {
545 launchPhone();
546 }
547 }
548
Lucas Dupincea7dee2018-10-16 12:43:37 -0700549 @VisibleForTesting
550 void launchVoiceAssist() {
Selim Cineke70d6532015-04-24 16:46:13 -0700551 Runnable runnable = new Runnable() {
552 @Override
553 public void run() {
554 mAssistManager.launchVoiceAssistFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700555 }
556 };
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400557 if (!mKeyguardStateController.canDismissLockScreen()) {
Selim Cineke70d6532015-04-24 16:46:13 -0700558 AsyncTask.execute(runnable);
559 } else {
Jason Monkd6fa02f2017-01-25 18:26:50 -0500560 boolean dismissShade = !TextUtils.isEmpty(mRightButtonStr)
Jason Monkde850bb2017-02-01 19:26:30 -0500561 && Dependency.get(TunerService.class).getValue(LOCKSCREEN_RIGHT_UNLOCK, 1) != 0;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500562 mStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
Jason Monkd6fa02f2017-01-25 18:26:50 -0500563 dismissShade, false /* afterKeyguardGone */, true /* deferred */);
Selim Cineke70d6532015-04-24 16:46:13 -0700564 }
565 }
566
567 private boolean canLaunchVoiceAssist() {
568 return mAssistManager.canVoiceAssistBeLaunchedFromKeyguard();
569 }
570
571 private void launchPhone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700572 final TelecomManager tm = TelecomManager.from(mContext);
Nancy Chen0eb1e402014-08-21 22:52:29 -0700573 if (tm.isInCall()) {
Yorke Lee583a20242014-08-12 18:47:08 -0700574 AsyncTask.execute(new Runnable() {
575 @Override
576 public void run() {
Nancy Chen0eb1e402014-08-21 22:52:29 -0700577 tm.showInCallScreen(false /* showDialpad */);
Yorke Lee583a20242014-08-12 18:47:08 -0700578 }
579 });
580 } else {
Jason Monkd6fa02f2017-01-25 18:26:50 -0500581 boolean dismissShade = !TextUtils.isEmpty(mLeftButtonStr)
Jason Monkde850bb2017-02-01 19:26:30 -0500582 && Dependency.get(TunerService.class).getValue(LOCKSCREEN_LEFT_UNLOCK, 1) != 0;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500583 mActivityStarter.startActivity(mLeftButton.getIntent(), dismissShade);
Yorke Lee583a20242014-08-12 18:47:08 -0700584 }
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200585 }
586
Adrian Roos2fe592d2014-05-17 03:11:59 +0200587
588 @Override
589 protected void onVisibilityChanged(View changedView, int visibility) {
590 super.onVisibilityChanged(changedView, visibility);
591 if (changedView == this && visibility == VISIBLE) {
Adrian Roosa06905b2014-05-28 12:13:48 +0200592 updateCameraVisibility();
Adrian Roos2fe592d2014-05-17 03:11:59 +0200593 }
594 }
595
Selim Cineke70d6532015-04-24 16:46:13 -0700596 public KeyguardAffordanceView getLeftView() {
597 return mLeftAffordanceView;
Selim Cinek4c6969a2014-05-26 19:22:17 +0200598 }
599
Selim Cineke70d6532015-04-24 16:46:13 -0700600 public KeyguardAffordanceView getRightView() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400601 return mRightAffordanceView;
Selim Cinek4c6969a2014-05-26 19:22:17 +0200602 }
603
Selim Cineke70d6532015-04-24 16:46:13 -0700604 public View getLeftPreview() {
605 return mLeftPreview;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200606 }
607
Selim Cineke70d6532015-04-24 16:46:13 -0700608 public View getRightPreview() {
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200609 return mCameraPreview;
610 }
611
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100612 public View getIndicationArea() {
613 return mIndicationArea;
Selim Cinekf99d0002014-06-13 07:36:01 +0200614 }
615
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200616 @Override
Jorim Jaggi2580a9762014-06-25 03:08:25 +0200617 public boolean hasOverlappingRendering() {
618 return false;
619 }
620
621 @Override
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400622 public void onUnlockedChanged() {
Adrian Roosa06905b2014-05-28 12:13:48 +0200623 updateCameraVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200624 }
Adrian Roosa06905b2014-05-28 12:13:48 +0200625
Selim Cineke70d6532015-04-24 16:46:13 -0700626 private void inflateCameraPreview() {
Selim Cinek5f145022016-08-02 16:00:12 -0700627 View previewBefore = mCameraPreview;
628 boolean visibleBefore = false;
629 if (previewBefore != null) {
630 mPreviewContainer.removeView(previewBefore);
631 visibleBefore = previewBefore.getVisibility() == View.VISIBLE;
632 }
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200633 mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200634 if (mCameraPreview != null) {
635 mPreviewContainer.addView(mCameraPreview);
Selim Cinek5f145022016-08-02 16:00:12 -0700636 mCameraPreview.setVisibility(visibleBefore ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200637 }
Jorim Jaggidadafd42016-09-30 07:20:25 -0700638 if (mAffordanceHelper != null) {
639 mAffordanceHelper.updatePreviews();
640 }
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200641 }
642
Selim Cineke70d6532015-04-24 16:46:13 -0700643 private void updateLeftPreview() {
644 View previewBefore = mLeftPreview;
645 if (previewBefore != null) {
646 mPreviewContainer.removeView(previewBefore);
647 }
648 if (mLeftIsVoiceAssist) {
649 mLeftPreview = mPreviewInflater.inflatePreviewFromService(
650 mAssistManager.getVoiceInteractorComponentName());
651 } else {
Jason Monkb59f46f2016-09-27 12:29:18 -0400652 mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent());
Selim Cineke70d6532015-04-24 16:46:13 -0700653 }
654 if (mLeftPreview != null) {
655 mPreviewContainer.addView(mLeftPreview);
656 mLeftPreview.setVisibility(View.INVISIBLE);
657 }
Jorim Jaggidadafd42016-09-30 07:20:25 -0700658 if (mAffordanceHelper != null) {
659 mAffordanceHelper.updatePreviews();
660 }
Selim Cineke70d6532015-04-24 16:46:13 -0700661 }
662
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100663 public void startFinishDozeAnimation() {
664 long delay = 0;
Selim Cineke70d6532015-04-24 16:46:13 -0700665 if (mLeftAffordanceView.getVisibility() == View.VISIBLE) {
666 startFinishDozeAnimationElement(mLeftAffordanceView, delay);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100667 delay += DOZE_ANIMATION_STAGGER_DELAY;
668 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400669 if (mRightAffordanceView.getVisibility() == View.VISIBLE) {
670 startFinishDozeAnimationElement(mRightAffordanceView, delay);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100671 }
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100672 }
673
674 private void startFinishDozeAnimationElement(View element, long delay) {
675 element.setAlpha(0f);
676 element.setTranslationY(element.getHeight() / 2);
677 element.animate()
678 .alpha(1f)
679 .translationY(0f)
Selim Cinekc18010f2016-01-20 13:41:30 -0800680 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100681 .setStartDelay(delay)
682 .setDuration(DOZE_ANIMATION_ELEMENT_DURATION);
683 }
684
Adrian Roosa06905b2014-05-28 12:13:48 +0200685 private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
Jim Millerb29814c2015-08-05 19:03:01 -0700686 @Override
Adrian Roosa06905b2014-05-28 12:13:48 +0200687 public void onReceive(Context context, Intent intent) {
688 post(new Runnable() {
689 @Override
690 public void run() {
691 updateCameraVisibility();
692 }
693 });
694 }
695 };
696
697 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
698 new KeyguardUpdateMonitorCallback() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400699 @Override
700 public void onUserSwitchComplete(int userId) {
701 updateCameraVisibility();
702 }
Jorim Jaggie7b12522014-08-06 16:41:21 +0200703
Jason Monkb59f46f2016-09-27 12:29:18 -0400704 @Override
Jorim Jaggi90f62792016-10-07 15:11:44 +0200705 public void onUserUnlocked() {
706 inflateCameraPreview();
707 updateCameraVisibility();
708 updateLeftAffordance();
Jason Monkb59f46f2016-09-27 12:29:18 -0400709 }
710 };
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200711
Selim Cineke70d6532015-04-24 16:46:13 -0700712 public void updateLeftAffordance() {
713 updateLeftAffordanceIcon();
714 updateLeftPreview();
715 }
Selim Cinek5f145022016-08-02 16:00:12 -0700716
Jason Monkb59f46f2016-09-27 12:29:18 -0400717 private void setRightButton(IntentButton button) {
Jason Monk1d9632d2017-02-09 13:20:04 -0800718 mRightButton = button;
Jason Monkb59f46f2016-09-27 12:29:18 -0400719 updateRightAffordanceIcon();
720 updateCameraVisibility();
721 inflateCameraPreview();
722 }
723
724 private void setLeftButton(IntentButton button) {
Jason Monk1d9632d2017-02-09 13:20:04 -0800725 mLeftButton = button;
726 if (!(mLeftButton instanceof DefaultLeftButton)) {
727 mLeftIsVoiceAssist = false;
728 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400729 updateLeftAffordance();
730 }
731
Adrian Roos91ba3072017-02-14 16:50:46 +0100732 public void setDozing(boolean dozing, boolean animate) {
733 mDozing = dozing;
734
735 updateCameraVisibility();
736 updateLeftAffordanceIcon();
737
738 if (dozing) {
Philip Quinnb86efa42017-07-08 12:59:24 -0700739 mOverlayContainer.setVisibility(INVISIBLE);
Adrian Roos91ba3072017-02-14 16:50:46 +0100740 } else {
Philip Quinnb86efa42017-07-08 12:59:24 -0700741 mOverlayContainer.setVisibility(VISIBLE);
Adrian Roos91ba3072017-02-14 16:50:46 +0100742 if (animate) {
743 startFinishDozeAnimation();
744 }
745 }
746 }
747
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700748 public void dozeTimeTick() {
749 int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */)
750 - mBurnInYOffset;
751 mIndicationArea.setTranslationY(burnInYOffset * mDarkAmount);
752 }
753
754 public void setAntiBurnInOffsetX(int burnInXOffset) {
755 if (mBurnInXOffset == burnInXOffset) {
756 return;
757 }
758 mBurnInXOffset = burnInXOffset;
759 mIndicationArea.setTranslationX(burnInXOffset);
760 }
761
Lucas Dupin407cc582019-03-11 21:04:31 -0700762 /**
763 * Sets the alpha of the indication areas and affordances, excluding the lock icon.
764 */
765 public void setAffordanceAlpha(float alpha) {
766 mLeftAffordanceView.setAlpha(alpha);
767 mRightAffordanceView.setAlpha(alpha);
768 mIndicationArea.setAlpha(alpha);
769 }
770
Jason Monkb59f46f2016-09-27 12:29:18 -0400771 private class DefaultLeftButton implements IntentButton {
772
773 private IconState mIconState = new IconState();
774
775 @Override
776 public IconState getIcon() {
777 mLeftIsVoiceAssist = canLaunchVoiceAssist();
778 if (mLeftIsVoiceAssist) {
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700779 mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance;
Evan Roskyd388c752016-11-15 13:59:06 -0800780 if (mLeftAssistIcon == null) {
781 mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
782 } else {
783 mIconState.drawable = mLeftAssistIcon;
784 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400785 mIconState.contentDescription = mContext.getString(
786 R.string.accessibility_voice_assist_button);
787 } else {
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700788 mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance
789 && isPhoneVisible();
Amin Shaikhf3a94272019-01-29 18:22:14 -0500790 mIconState.drawable = mContext.getDrawable(
791 com.android.internal.R.drawable.ic_phone);
Jason Monkb59f46f2016-09-27 12:29:18 -0400792 mIconState.contentDescription = mContext.getString(
793 R.string.accessibility_phone_button);
794 }
795 return mIconState;
796 }
797
798 @Override
799 public Intent getIntent() {
800 return PHONE_INTENT;
801 }
802 }
803
804 private class DefaultRightButton implements IntentButton {
805
806 private IconState mIconState = new IconState();
807
808 @Override
809 public IconState getIcon() {
Esteban Talavera40f8b992017-07-14 16:14:07 +0100810 boolean isCameraDisabled = (mStatusBar != null) && !mStatusBar.isCameraAllowedByAdmin();
Lucas Dupinc8add512019-08-28 12:08:58 -0700811 mIconState.isVisible = !isCameraDisabled
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700812 && mShowCameraAffordance
Lucas Dupinc8add512019-08-28 12:08:58 -0700813 && mUserSetupComplete
814 && resolveCameraIntent() != null;
Jason Monkb59f46f2016-09-27 12:29:18 -0400815 mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
816 mIconState.contentDescription =
817 mContext.getString(R.string.accessibility_camera_button);
818 return mIconState;
819 }
820
821 @Override
822 public Intent getIntent() {
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400823 boolean canDismissLs = mKeyguardStateController.canDismissLockScreen();
824 boolean secure = mKeyguardStateController.isMethodSecure();
825 return (secure && !canDismissLs) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
Jason Monkb59f46f2016-09-27 12:29:18 -0400826 }
827 }
Adrian Roos7e58a082018-03-09 16:40:56 +0100828
829 @Override
830 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
831 int bottom = insets.getDisplayCutout() != null
832 ? insets.getDisplayCutout().getSafeInsetBottom() : 0;
833 if (isPaddingRelative()) {
834 setPaddingRelative(getPaddingStart(), getPaddingTop(), getPaddingEnd(), bottom);
835 } else {
836 setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottom);
837 }
838 return insets;
839 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200840}