blob: 72dfa18ca991770091c618acf6f1f68f5924724c [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;
Evan Roskyd388c752016-11-15 13:59:06 -0800158 private Drawable mLeftAssistIcon;
Adrian Roos72cc3702014-09-18 17:25:09 +0200159
Jason Monkb59f46f2016-09-27 12:29:18 -0400160 private IntentButton mRightButton = new DefaultRightButton();
Jason Monk1d9632d2017-02-09 13:20:04 -0800161 private Extension<IntentButton> mRightExtension;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500162 private String mRightButtonStr;
Jason Monkb59f46f2016-09-27 12:29:18 -0400163 private IntentButton mLeftButton = new DefaultLeftButton();
Jason Monk1d9632d2017-02-09 13:20:04 -0800164 private Extension<IntentButton> mLeftExtension;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500165 private String mLeftButtonStr;
Adrian Roos91ba3072017-02-14 16:50:46 +0100166 private boolean mDozing;
Lucas Dupin4272f442018-01-13 22:00:35 -0800167 private int mIndicationBottomMargin;
Lucas Dupin4272f442018-01-13 22:00:35 -0800168 private float mDarkAmount;
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700169 private int mBurnInXOffset;
170 private int mBurnInYOffset;
Mark Renouf6b2331c2019-03-21 13:40:08 -0400171 private ActivityIntentHelper mActivityIntentHelper;
Jason Monkb59f46f2016-09-27 12:29:18 -0400172
Jorim Jaggia6310292014-04-16 14:11:52 +0200173 public KeyguardBottomAreaView(Context context) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200174 this(context, null);
Jorim Jaggia6310292014-04-16 14:11:52 +0200175 }
176
177 public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200178 this(context, attrs, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200179 }
180
181 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200182 this(context, attrs, defStyleAttr, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200183 }
184
185 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
186 int defStyleRes) {
187 super(context, attrs, defStyleAttr, defStyleRes);
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700188 mShowLeftAffordance = getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance);
189 mShowCameraAffordance = getResources()
190 .getBoolean(R.bool.config_keyguardShowCameraAffordance);
Jorim Jaggia6310292014-04-16 14:11:52 +0200191 }
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;
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700198 if (host == mRightAffordanceView) {
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200199 label = getResources().getString(R.string.camera_label);
Selim Cineke70d6532015-04-24 16:46:13 -0700200 } else if (host == mLeftAffordanceView) {
201 if (mLeftIsVoiceAssist) {
202 label = getResources().getString(R.string.voice_assist_label);
203 } else {
204 label = getResources().getString(R.string.phone_label);
205 }
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200206 }
207 info.addAction(new AccessibilityAction(ACTION_CLICK, label));
208 }
209
210 @Override
211 public boolean performAccessibilityAction(View host, int action, Bundle args) {
212 if (action == ACTION_CLICK) {
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700213 if (host == mRightAffordanceView) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700214 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200215 return true;
Selim Cineke70d6532015-04-24 16:46:13 -0700216 } else if (host == mLeftAffordanceView) {
217 launchLeftAffordance();
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200218 return true;
219 }
220 }
221 return super.performAccessibilityAction(host, action, args);
222 }
223 };
224
Lucas Dupincea7dee2018-10-16 12:43:37 -0700225 public void initFrom(KeyguardBottomAreaView oldBottomArea) {
Lucas Dupincea7dee2018-10-16 12:43:37 -0700226 setStatusBar(oldBottomArea.mStatusBar);
227 }
228
Jorim Jaggia6310292014-04-16 14:11:52 +0200229 @Override
230 protected void onFinishInflate() {
231 super.onFinishInflate();
Mark Renouf6b2331c2019-03-21 13:40:08 -0400232 mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext),
233 new ActivityIntentHelper(mContext));
Alan Viverette51efddb2017-04-05 10:00:01 -0400234 mPreviewContainer = findViewById(R.id.preview_container);
Philip Quinnb86efa42017-07-08 12:59:24 -0700235 mOverlayContainer = findViewById(R.id.overlay_container);
Alan Viverette51efddb2017-04-05 10:00:01 -0400236 mRightAffordanceView = findViewById(R.id.camera_button);
237 mLeftAffordanceView = findViewById(R.id.left_button);
Alan Viverette51efddb2017-04-05 10:00:01 -0400238 mIndicationArea = findViewById(R.id.keyguard_indication_area);
Alan Viverette51efddb2017-04-05 10:00:01 -0400239 mIndicationText = findViewById(R.id.keyguard_indication_text);
Lucas Dupin4272f442018-01-13 22:00:35 -0800240 mIndicationBottomMargin = getResources().getDimensionPixelSize(
241 R.dimen.keyguard_indication_margin_bottom);
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700242 mBurnInYOffset = getResources().getDimensionPixelSize(
243 R.dimen.default_burn_in_prevention_offset);
Jorim Jaggia6310292014-04-16 14:11:52 +0200244 updateCameraVisibility();
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400245 mKeyguardStateController = Dependency.get(KeyguardStateController.class);
246 mKeyguardStateController.addCallback(this);
Selim Cinekbaa23272014-07-08 18:01:07 +0200247 setClipChildren(false);
248 setClipToPadding(false);
Selim Cineke70d6532015-04-24 16:46:13 -0700249 inflateCameraPreview();
Jason Monkb59f46f2016-09-27 12:29:18 -0400250 mRightAffordanceView.setOnClickListener(this);
Selim Cineke70d6532015-04-24 16:46:13 -0700251 mLeftAffordanceView.setOnClickListener(this);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200252 initAccessibility();
Jason Monk9c7844c2017-01-18 15:21:53 -0500253 mActivityStarter = Dependency.get(ActivityStarter.class);
254 mFlashlightController = Dependency.get(FlashlightController.class);
255 mAccessibilityController = Dependency.get(AccessibilityController.class);
Mark Renouf6b2331c2019-03-21 13:40:08 -0400256 mActivityIntentHelper = new ActivityIntentHelper(getContext());
Jason Monk9c7844c2017-01-18 15:21:53 -0500257 updateLeftAffordance();
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200258 }
259
Jason Monkb59f46f2016-09-27 12:29:18 -0400260 @Override
261 protected void onAttachedToWindow() {
262 super.onAttachedToWindow();
Jason Monk9ef73072017-01-27 13:32:51 -0500263 mAccessibilityController.addStateChangedCallback(this);
Jason Monk1d9632d2017-02-09 13:20:04 -0800264 mRightExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
265 .withPlugin(IntentButtonProvider.class, RIGHT_BUTTON_PLUGIN,
266 p -> p.getIntentButton())
267 .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_RIGHT_BUTTON))
268 .withDefault(() -> new DefaultRightButton())
269 .withCallback(button -> setRightButton(button))
270 .build();
271 mLeftExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
272 .withPlugin(IntentButtonProvider.class, LEFT_BUTTON_PLUGIN,
273 p -> p.getIntentButton())
274 .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_LEFT_BUTTON))
275 .withDefault(() -> new DefaultLeftButton())
276 .withCallback(button -> setLeftButton(button))
277 .build();
Selim Cinek9a105312017-07-21 17:16:05 -0700278 final IntentFilter filter = new IntentFilter();
279 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
280 getContext().registerReceiverAsUser(mDevicePolicyReceiver,
281 UserHandle.ALL, filter, null, null);
Dave Mankoffe2294692019-08-14 11:53:13 -0400282 Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mUpdateMonitorCallback);
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400283 mKeyguardStateController.addCallback(this);
Jason Monkb59f46f2016-09-27 12:29:18 -0400284 }
285
286 @Override
287 protected void onDetachedFromWindow() {
288 super.onDetachedFromWindow();
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400289 mKeyguardStateController.removeCallback(this);
Jason Monk9ef73072017-01-27 13:32:51 -0500290 mAccessibilityController.removeStateChangedCallback(this);
Jason Monk1d9632d2017-02-09 13:20:04 -0800291 mRightExtension.destroy();
292 mLeftExtension.destroy();
Selim Cinek9a105312017-07-21 17:16:05 -0700293 getContext().unregisterReceiver(mDevicePolicyReceiver);
Dave Mankoffe2294692019-08-14 11:53:13 -0400294 Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mUpdateMonitorCallback);
Jason Monkb59f46f2016-09-27 12:29:18 -0400295 }
296
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200297 private void initAccessibility() {
Selim Cineke70d6532015-04-24 16:46:13 -0700298 mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
Jason Monkb59f46f2016-09-27 12:29:18 -0400299 mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
Jorim Jaggia6310292014-04-16 14:11:52 +0200300 }
301
Jorim Jaggie210cc82014-08-12 23:44:59 +0200302 @Override
303 protected void onConfigurationChanged(Configuration newConfig) {
304 super.onConfigurationChanged(newConfig);
Lucas Dupin4272f442018-01-13 22:00:35 -0800305 mIndicationBottomMargin = getResources().getDimensionPixelSize(
Jorim Jaggie210cc82014-08-12 23:44:59 +0200306 R.dimen.keyguard_indication_margin_bottom);
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700307 mBurnInYOffset = getResources().getDimensionPixelSize(
308 R.dimen.default_burn_in_prevention_offset);
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100309 MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams();
Lucas Dupin4272f442018-01-13 22:00:35 -0800310 if (mlp.bottomMargin != mIndicationBottomMargin) {
311 mlp.bottomMargin = mIndicationBottomMargin;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100312 mIndicationArea.setLayoutParams(mlp);
Jorim Jaggie210cc82014-08-12 23:44:59 +0200313 }
314
315 // Respect font size setting.
316 mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
317 getResources().getDimensionPixelSize(
318 com.android.internal.R.dimen.text_size_small_material));
Selim Cinek6ebba592016-05-31 15:28:28 -0700319
Jason Monkb59f46f2016-09-27 12:29:18 -0400320 ViewGroup.LayoutParams lp = mRightAffordanceView.getLayoutParams();
Selim Cinek6ebba592016-05-31 15:28:28 -0700321 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
322 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
Jason Monkb59f46f2016-09-27 12:29:18 -0400323 mRightAffordanceView.setLayoutParams(lp);
324 updateRightAffordanceIcon();
Selim Cinek6ebba592016-05-31 15:28:28 -0700325
Selim Cinek6ebba592016-05-31 15:28:28 -0700326 lp = mLeftAffordanceView.getLayoutParams();
327 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
328 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
329 mLeftAffordanceView.setLayoutParams(lp);
330 updateLeftAffordanceIcon();
Jorim Jaggie210cc82014-08-12 23:44:59 +0200331 }
332
Jason Monkb59f46f2016-09-27 12:29:18 -0400333 private void updateRightAffordanceIcon() {
334 IconState state = mRightButton.getIcon();
Adrian Roos674b8ea2017-05-25 12:33:17 -0700335 mRightAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE);
Lucas Dupin3704d532019-04-18 19:23:06 -0700336 if (state.drawable != mRightAffordanceView.getDrawable()
337 || state.tint != mRightAffordanceView.shouldTint()) {
338 mRightAffordanceView.setImageDrawable(state.drawable, state.tint);
339 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400340 mRightAffordanceView.setContentDescription(state.contentDescription);
341 }
342
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500343 public void setStatusBar(StatusBar statusBar) {
344 mStatusBar = statusBar;
Dan Sandlere163a642015-03-01 22:58:32 -0500345 updateCameraVisibility(); // in case onFinishInflate() was called too early
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200346 }
347
Jorim Jaggidadafd42016-09-30 07:20:25 -0700348 public void setAffordanceHelper(KeyguardAffordanceHelper affordanceHelper) {
349 mAffordanceHelper = affordanceHelper;
350 }
351
Adrian Roosa4eba9f2015-07-22 18:13:04 -0700352 public void setUserSetupComplete(boolean userSetupComplete) {
353 mUserSetupComplete = userSetupComplete;
354 updateCameraVisibility();
355 updateLeftAffordanceIcon();
356 }
357
Adrian Roosa06905b2014-05-28 12:13:48 +0200358 private Intent getCameraIntent() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400359 return mRightButton.getIntent();
Adrian Roosa06905b2014-05-28 12:13:48 +0200360 }
361
Zhentao Sun04f97402015-08-26 17:37:30 -0700362 /**
363 * Resolves the intent to launch the camera application.
364 */
365 public ResolveInfo resolveCameraIntent() {
Lucas Dupinc8add512019-08-28 12:08:58 -0700366 return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
367 PackageManager.MATCH_DEFAULT_ONLY,
368 KeyguardUpdateMonitor.getCurrentUser());
Zhentao Sun04f97402015-08-26 17:37:30 -0700369 }
370
Jorim Jaggia6310292014-04-16 14:11:52 +0200371 private void updateCameraVisibility() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400372 if (mRightAffordanceView == null) {
Dan Sandlere163a642015-03-01 22:58:32 -0500373 // Things are not set up yet; reply hazy, ask again later
374 return;
375 }
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700376 mRightAffordanceView.setVisibility(!mDozing && mShowCameraAffordance
377 && mRightButton.getIcon().isVisible ? View.VISIBLE : View.GONE);
Jorim Jaggia6310292014-04-16 14:11:52 +0200378 }
379
Evan Roskyd388c752016-11-15 13:59:06 -0800380 /**
381 * Set an alternate icon for the left assist affordance (replace the mic icon)
382 */
383 public void setLeftAssistIcon(Drawable drawable) {
384 mLeftAssistIcon = drawable;
385 updateLeftAffordanceIcon();
386 }
387
Selim Cineke70d6532015-04-24 16:46:13 -0700388 private void updateLeftAffordanceIcon() {
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700389 if (!mShowLeftAffordance || mDozing) {
390 mLeftAffordanceView.setVisibility(GONE);
391 return;
392 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400393 IconState state = mLeftButton.getIcon();
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700394 mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE);
Lucas Dupin3704d532019-04-18 19:23:06 -0700395 if (state.drawable != mLeftAffordanceView.getDrawable()
396 || state.tint != mLeftAffordanceView.shouldTint()) {
397 mLeftAffordanceView.setImageDrawable(state.drawable, state.tint);
398 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400399 mLeftAffordanceView.setContentDescription(state.contentDescription);
Selim Cineke70d6532015-04-24 16:46:13 -0700400 }
401
402 public boolean isLeftVoiceAssist() {
403 return mLeftIsVoiceAssist;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200404 }
405
406 private boolean isPhoneVisible() {
407 PackageManager pm = mContext.getPackageManager();
408 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
409 && pm.resolveActivity(PHONE_INTENT, 0) != null;
410 }
411
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200412 @Override
413 public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
Jason Monkb59f46f2016-09-27 12:29:18 -0400414 mRightAffordanceView.setClickable(touchExplorationEnabled);
Selim Cineke70d6532015-04-24 16:46:13 -0700415 mLeftAffordanceView.setClickable(touchExplorationEnabled);
Jason Monkb59f46f2016-09-27 12:29:18 -0400416 mRightAffordanceView.setFocusable(accessibilityEnabled);
Selim Cineke70d6532015-04-24 16:46:13 -0700417 mLeftAffordanceView.setFocusable(accessibilityEnabled);
Jorim Jaggia6310292014-04-16 14:11:52 +0200418 }
419
Selim Cinek4c6969a2014-05-26 19:22:17 +0200420 @Override
421 public void onClick(View v) {
Jason Monkb59f46f2016-09-27 12:29:18 -0400422 if (v == mRightAffordanceView) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700423 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
Selim Cineke70d6532015-04-24 16:46:13 -0700424 } else if (v == mLeftAffordanceView) {
425 launchLeftAffordance();
Selim Cinek4c6969a2014-05-26 19:22:17 +0200426 }
427 }
428
Jorim Jaggid9449862015-05-29 14:49:08 -0700429 public void bindCameraPrewarmService() {
Adrian Roosa06905b2014-05-28 12:13:48 +0200430 Intent intent = getCameraIntent();
Mark Renouf6b2331c2019-03-21 13:40:08 -0400431 ActivityInfo targetInfo = mActivityIntentHelper.getTargetActivityInfo(intent,
Selim Cinek5f145022016-08-02 16:00:12 -0700432 KeyguardUpdateMonitor.getCurrentUser(), true /* onlyDirectBootAware */);
Jorim Jaggi8b8fa3e2015-08-18 18:33:49 -0700433 if (targetInfo != null && targetInfo.metaData != null) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700434 String clazz = targetInfo.metaData.getString(
435 MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE);
436 if (clazz != null) {
437 Intent serviceIntent = new Intent();
438 serviceIntent.setClassName(targetInfo.packageName, clazz);
439 serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM);
440 try {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700441 if (getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection,
Selim Cinekedf47482015-09-01 18:05:08 -0700442 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
443 new UserHandle(UserHandle.USER_CURRENT))) {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700444 mPrewarmBound = true;
445 }
Jorim Jaggid9449862015-05-29 14:49:08 -0700446 } catch (SecurityException e) {
447 Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName
448 + " class=" + clazz, e);
449 }
450 }
Jorim Jaggia86790b2015-04-02 16:32:29 -0700451 }
452 }
453
Jorim Jaggid9449862015-05-29 14:49:08 -0700454 public void unbindCameraPrewarmService(boolean launched) {
455 if (mPrewarmBound) {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700456 if (mPrewarmMessenger != null && launched) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700457 try {
458 mPrewarmMessenger.send(Message.obtain(null /* handler */,
459 CameraPrewarmService.MSG_CAMERA_FIRED));
460 } catch (RemoteException e) {
461 Log.w(TAG, "Error sending camera fired message", e);
462 }
463 }
464 mContext.unbindService(mPrewarmConnection);
465 mPrewarmBound = false;
Jorim Jaggia86790b2015-04-02 16:32:29 -0700466 }
467 }
468
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700469 public void launchCamera(String source) {
Jorim Jaggia86790b2015-04-02 16:32:29 -0700470 final Intent intent = getCameraIntent();
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700471 intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
Mark Renouf6b2331c2019-03-21 13:40:08 -0400472 boolean wouldLaunchResolverActivity = mActivityIntentHelper.wouldLaunchResolverActivity(
473 intent, KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200474 if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
Jorim Jaggia86790b2015-04-02 16:32:29 -0700475 AsyncTask.execute(new Runnable() {
476 @Override
477 public void run() {
Jorim Jaggid9449862015-05-29 14:49:08 -0700478 int result = ActivityManager.START_CANCELED;
Robert Carrfd10cd12016-06-29 16:41:50 -0700479
480 // Normally an activity will set it's requested rotation
481 // animation on its window. However when launching an activity
482 // causes the orientation to change this is too late. In these cases
483 // the default animation is used. This doesn't look good for
484 // the camera (as it rotates the camera contents out of sync
485 // with physical reality). So, we ask the WindowManager to
486 // force the crossfade animation if an orientation change
487 // happens to occur during the launch.
488 ActivityOptions o = ActivityOptions.makeBasic();
Winson Chungf7e03e12017-08-22 11:32:16 -0700489 o.setDisallowEnterPictureInPictureWhileLaunching(true);
Robert Carrfd10cd12016-06-29 16:41:50 -0700490 o.setRotationAnimationHint(
Robert Carr57d9fbd2016-08-15 12:00:35 -0700491 WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
Jorim Jaggid9449862015-05-29 14:49:08 -0700492 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700493 result = ActivityTaskManager.getService().startActivityAsUser(
Jorim Jaggid9449862015-05-29 14:49:08 -0700494 null, getContext().getBasePackageName(),
Philip P. Moltmann9c5226f2020-01-10 08:53:43 -0800495 getContext().getFeatureId(), intent,
Jorim Jaggid9449862015-05-29 14:49:08 -0700496 intent.resolveTypeIfNeeded(getContext().getContentResolver()),
Robert Carrfd10cd12016-06-29 16:41:50 -0700497 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, o.toBundle(),
Jorim Jaggid9449862015-05-29 14:49:08 -0700498 UserHandle.CURRENT.getIdentifier());
499 } catch (RemoteException e) {
500 Log.w(TAG, "Unable to start camera activity", e);
501 }
Jorim Jaggid9449862015-05-29 14:49:08 -0700502 final boolean launched = isSuccessfulLaunch(result);
503 post(new Runnable() {
504 @Override
505 public void run() {
506 unbindCameraPrewarmService(launched);
507 }
508 });
Jorim Jaggia86790b2015-04-02 16:32:29 -0700509 }
510 });
Adrian Roosa06905b2014-05-28 12:13:48 +0200511 } else {
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200512
513 // We need to delay starting the activity because ResolverActivity finishes itself if
514 // launched behind lockscreen.
Jorim Jaggid9449862015-05-29 14:49:08 -0700515 mActivityStarter.startActivity(intent, false /* dismissShade */,
516 new ActivityStarter.Callback() {
517 @Override
518 public void onActivityStarted(int resultCode) {
519 unbindCameraPrewarmService(isSuccessfulLaunch(resultCode));
520 }
521 });
Adrian Roosa06905b2014-05-28 12:13:48 +0200522 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200523 }
524
Lucas Dupin4272f442018-01-13 22:00:35 -0800525 public void setDarkAmount(float darkAmount) {
526 if (darkAmount == mDarkAmount) {
527 return;
528 }
529 mDarkAmount = darkAmount;
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700530 dozeTimeTick();
Lucas Dupinf22194f2018-12-26 11:43:57 -0800531 }
532
Jorim Jaggid9449862015-05-29 14:49:08 -0700533 private static boolean isSuccessfulLaunch(int result) {
534 return result == ActivityManager.START_SUCCESS
535 || result == ActivityManager.START_DELIVERED_TO_TOP
536 || result == ActivityManager.START_TASK_TO_FRONT;
537 }
538
Selim Cineke70d6532015-04-24 16:46:13 -0700539 public void launchLeftAffordance() {
540 if (mLeftIsVoiceAssist) {
541 launchVoiceAssist();
542 } else {
543 launchPhone();
544 }
545 }
546
Lucas Dupincea7dee2018-10-16 12:43:37 -0700547 @VisibleForTesting
548 void launchVoiceAssist() {
Selim Cineke70d6532015-04-24 16:46:13 -0700549 Runnable runnable = new Runnable() {
550 @Override
551 public void run() {
Dave Mankoffaf8163f2020-01-08 14:24:35 -0500552 Dependency.get(AssistManager.class).launchVoiceAssistFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700553 }
554 };
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400555 if (!mKeyguardStateController.canDismissLockScreen()) {
Selim Cineke70d6532015-04-24 16:46:13 -0700556 AsyncTask.execute(runnable);
557 } else {
Jason Monkd6fa02f2017-01-25 18:26:50 -0500558 boolean dismissShade = !TextUtils.isEmpty(mRightButtonStr)
Jason Monkde850bb2017-02-01 19:26:30 -0500559 && Dependency.get(TunerService.class).getValue(LOCKSCREEN_RIGHT_UNLOCK, 1) != 0;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500560 mStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
Jason Monkd6fa02f2017-01-25 18:26:50 -0500561 dismissShade, false /* afterKeyguardGone */, true /* deferred */);
Selim Cineke70d6532015-04-24 16:46:13 -0700562 }
563 }
564
565 private boolean canLaunchVoiceAssist() {
Dave Mankoffaf8163f2020-01-08 14:24:35 -0500566 return Dependency.get(AssistManager.class).canVoiceAssistBeLaunchedFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700567 }
568
569 private void launchPhone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700570 final TelecomManager tm = TelecomManager.from(mContext);
Nancy Chen0eb1e402014-08-21 22:52:29 -0700571 if (tm.isInCall()) {
Yorke Lee583a20242014-08-12 18:47:08 -0700572 AsyncTask.execute(new Runnable() {
573 @Override
574 public void run() {
Nancy Chen0eb1e402014-08-21 22:52:29 -0700575 tm.showInCallScreen(false /* showDialpad */);
Yorke Lee583a20242014-08-12 18:47:08 -0700576 }
577 });
578 } else {
Jason Monkd6fa02f2017-01-25 18:26:50 -0500579 boolean dismissShade = !TextUtils.isEmpty(mLeftButtonStr)
Jason Monkde850bb2017-02-01 19:26:30 -0500580 && Dependency.get(TunerService.class).getValue(LOCKSCREEN_LEFT_UNLOCK, 1) != 0;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500581 mActivityStarter.startActivity(mLeftButton.getIntent(), dismissShade);
Yorke Lee583a20242014-08-12 18:47:08 -0700582 }
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200583 }
584
Adrian Roos2fe592d2014-05-17 03:11:59 +0200585
586 @Override
587 protected void onVisibilityChanged(View changedView, int visibility) {
588 super.onVisibilityChanged(changedView, visibility);
589 if (changedView == this && visibility == VISIBLE) {
Adrian Roosa06905b2014-05-28 12:13:48 +0200590 updateCameraVisibility();
Adrian Roos2fe592d2014-05-17 03:11:59 +0200591 }
592 }
593
Selim Cineke70d6532015-04-24 16:46:13 -0700594 public KeyguardAffordanceView getLeftView() {
595 return mLeftAffordanceView;
Selim Cinek4c6969a2014-05-26 19:22:17 +0200596 }
597
Selim Cineke70d6532015-04-24 16:46:13 -0700598 public KeyguardAffordanceView getRightView() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400599 return mRightAffordanceView;
Selim Cinek4c6969a2014-05-26 19:22:17 +0200600 }
601
Selim Cineke70d6532015-04-24 16:46:13 -0700602 public View getLeftPreview() {
603 return mLeftPreview;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200604 }
605
Selim Cineke70d6532015-04-24 16:46:13 -0700606 public View getRightPreview() {
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200607 return mCameraPreview;
608 }
609
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100610 public View getIndicationArea() {
611 return mIndicationArea;
Selim Cinekf99d0002014-06-13 07:36:01 +0200612 }
613
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200614 @Override
Jorim Jaggi2580a9762014-06-25 03:08:25 +0200615 public boolean hasOverlappingRendering() {
616 return false;
617 }
618
619 @Override
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400620 public void onUnlockedChanged() {
Adrian Roosa06905b2014-05-28 12:13:48 +0200621 updateCameraVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200622 }
Adrian Roosa06905b2014-05-28 12:13:48 +0200623
Selim Cineke70d6532015-04-24 16:46:13 -0700624 private void inflateCameraPreview() {
Selim Cinek5f145022016-08-02 16:00:12 -0700625 View previewBefore = mCameraPreview;
626 boolean visibleBefore = false;
627 if (previewBefore != null) {
628 mPreviewContainer.removeView(previewBefore);
629 visibleBefore = previewBefore.getVisibility() == View.VISIBLE;
630 }
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200631 mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200632 if (mCameraPreview != null) {
633 mPreviewContainer.addView(mCameraPreview);
Selim Cinek5f145022016-08-02 16:00:12 -0700634 mCameraPreview.setVisibility(visibleBefore ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200635 }
Jorim Jaggidadafd42016-09-30 07:20:25 -0700636 if (mAffordanceHelper != null) {
637 mAffordanceHelper.updatePreviews();
638 }
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200639 }
640
Selim Cineke70d6532015-04-24 16:46:13 -0700641 private void updateLeftPreview() {
642 View previewBefore = mLeftPreview;
643 if (previewBefore != null) {
644 mPreviewContainer.removeView(previewBefore);
645 }
646 if (mLeftIsVoiceAssist) {
647 mLeftPreview = mPreviewInflater.inflatePreviewFromService(
Dave Mankoffaf8163f2020-01-08 14:24:35 -0500648 Dependency.get(AssistManager.class).getVoiceInteractorComponentName());
Selim Cineke70d6532015-04-24 16:46:13 -0700649 } else {
Jason Monkb59f46f2016-09-27 12:29:18 -0400650 mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent());
Selim Cineke70d6532015-04-24 16:46:13 -0700651 }
652 if (mLeftPreview != null) {
653 mPreviewContainer.addView(mLeftPreview);
654 mLeftPreview.setVisibility(View.INVISIBLE);
655 }
Jorim Jaggidadafd42016-09-30 07:20:25 -0700656 if (mAffordanceHelper != null) {
657 mAffordanceHelper.updatePreviews();
658 }
Selim Cineke70d6532015-04-24 16:46:13 -0700659 }
660
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100661 public void startFinishDozeAnimation() {
662 long delay = 0;
Selim Cineke70d6532015-04-24 16:46:13 -0700663 if (mLeftAffordanceView.getVisibility() == View.VISIBLE) {
664 startFinishDozeAnimationElement(mLeftAffordanceView, delay);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100665 delay += DOZE_ANIMATION_STAGGER_DELAY;
666 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400667 if (mRightAffordanceView.getVisibility() == View.VISIBLE) {
668 startFinishDozeAnimationElement(mRightAffordanceView, delay);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100669 }
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100670 }
671
672 private void startFinishDozeAnimationElement(View element, long delay) {
673 element.setAlpha(0f);
674 element.setTranslationY(element.getHeight() / 2);
675 element.animate()
676 .alpha(1f)
677 .translationY(0f)
Selim Cinekc18010f2016-01-20 13:41:30 -0800678 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100679 .setStartDelay(delay)
680 .setDuration(DOZE_ANIMATION_ELEMENT_DURATION);
681 }
682
Adrian Roosa06905b2014-05-28 12:13:48 +0200683 private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
Jim Millerb29814c2015-08-05 19:03:01 -0700684 @Override
Adrian Roosa06905b2014-05-28 12:13:48 +0200685 public void onReceive(Context context, Intent intent) {
686 post(new Runnable() {
687 @Override
688 public void run() {
689 updateCameraVisibility();
690 }
691 });
692 }
693 };
694
695 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
696 new KeyguardUpdateMonitorCallback() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400697 @Override
698 public void onUserSwitchComplete(int userId) {
699 updateCameraVisibility();
700 }
Jorim Jaggie7b12522014-08-06 16:41:21 +0200701
Jason Monkb59f46f2016-09-27 12:29:18 -0400702 @Override
Jorim Jaggi90f62792016-10-07 15:11:44 +0200703 public void onUserUnlocked() {
704 inflateCameraPreview();
705 updateCameraVisibility();
706 updateLeftAffordance();
Jason Monkb59f46f2016-09-27 12:29:18 -0400707 }
708 };
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200709
Selim Cineke70d6532015-04-24 16:46:13 -0700710 public void updateLeftAffordance() {
711 updateLeftAffordanceIcon();
712 updateLeftPreview();
713 }
Selim Cinek5f145022016-08-02 16:00:12 -0700714
Jason Monkb59f46f2016-09-27 12:29:18 -0400715 private void setRightButton(IntentButton button) {
Jason Monk1d9632d2017-02-09 13:20:04 -0800716 mRightButton = button;
Jason Monkb59f46f2016-09-27 12:29:18 -0400717 updateRightAffordanceIcon();
718 updateCameraVisibility();
719 inflateCameraPreview();
720 }
721
722 private void setLeftButton(IntentButton button) {
Jason Monk1d9632d2017-02-09 13:20:04 -0800723 mLeftButton = button;
724 if (!(mLeftButton instanceof DefaultLeftButton)) {
725 mLeftIsVoiceAssist = false;
726 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400727 updateLeftAffordance();
728 }
729
Adrian Roos91ba3072017-02-14 16:50:46 +0100730 public void setDozing(boolean dozing, boolean animate) {
731 mDozing = dozing;
732
733 updateCameraVisibility();
734 updateLeftAffordanceIcon();
735
736 if (dozing) {
Philip Quinnb86efa42017-07-08 12:59:24 -0700737 mOverlayContainer.setVisibility(INVISIBLE);
Adrian Roos91ba3072017-02-14 16:50:46 +0100738 } else {
Philip Quinnb86efa42017-07-08 12:59:24 -0700739 mOverlayContainer.setVisibility(VISIBLE);
Adrian Roos91ba3072017-02-14 16:50:46 +0100740 if (animate) {
741 startFinishDozeAnimation();
742 }
743 }
744 }
745
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700746 public void dozeTimeTick() {
747 int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */)
748 - mBurnInYOffset;
749 mIndicationArea.setTranslationY(burnInYOffset * mDarkAmount);
750 }
751
752 public void setAntiBurnInOffsetX(int burnInXOffset) {
753 if (mBurnInXOffset == burnInXOffset) {
754 return;
755 }
756 mBurnInXOffset = burnInXOffset;
757 mIndicationArea.setTranslationX(burnInXOffset);
758 }
759
Lucas Dupin407cc582019-03-11 21:04:31 -0700760 /**
761 * Sets the alpha of the indication areas and affordances, excluding the lock icon.
762 */
763 public void setAffordanceAlpha(float alpha) {
764 mLeftAffordanceView.setAlpha(alpha);
765 mRightAffordanceView.setAlpha(alpha);
766 mIndicationArea.setAlpha(alpha);
767 }
768
Jason Monkb59f46f2016-09-27 12:29:18 -0400769 private class DefaultLeftButton implements IntentButton {
770
771 private IconState mIconState = new IconState();
772
773 @Override
774 public IconState getIcon() {
775 mLeftIsVoiceAssist = canLaunchVoiceAssist();
776 if (mLeftIsVoiceAssist) {
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700777 mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance;
Evan Roskyd388c752016-11-15 13:59:06 -0800778 if (mLeftAssistIcon == null) {
779 mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
780 } else {
781 mIconState.drawable = mLeftAssistIcon;
782 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400783 mIconState.contentDescription = mContext.getString(
784 R.string.accessibility_voice_assist_button);
785 } else {
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700786 mIconState.isVisible = mUserSetupComplete && mShowLeftAffordance
787 && isPhoneVisible();
Amin Shaikhf3a94272019-01-29 18:22:14 -0500788 mIconState.drawable = mContext.getDrawable(
789 com.android.internal.R.drawable.ic_phone);
Jason Monkb59f46f2016-09-27 12:29:18 -0400790 mIconState.contentDescription = mContext.getString(
791 R.string.accessibility_phone_button);
792 }
793 return mIconState;
794 }
795
796 @Override
797 public Intent getIntent() {
798 return PHONE_INTENT;
799 }
800 }
801
802 private class DefaultRightButton implements IntentButton {
803
804 private IconState mIconState = new IconState();
805
806 @Override
807 public IconState getIcon() {
Esteban Talavera40f8b992017-07-14 16:14:07 +0100808 boolean isCameraDisabled = (mStatusBar != null) && !mStatusBar.isCameraAllowedByAdmin();
Lucas Dupinc8add512019-08-28 12:08:58 -0700809 mIconState.isVisible = !isCameraDisabled
Lucas Dupinf8e04bc2019-10-04 12:34:10 -0700810 && mShowCameraAffordance
Lucas Dupinc8add512019-08-28 12:08:58 -0700811 && mUserSetupComplete
812 && resolveCameraIntent() != null;
Jason Monkb59f46f2016-09-27 12:29:18 -0400813 mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
814 mIconState.contentDescription =
815 mContext.getString(R.string.accessibility_camera_button);
816 return mIconState;
817 }
818
819 @Override
820 public Intent getIntent() {
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400821 boolean canDismissLs = mKeyguardStateController.canDismissLockScreen();
822 boolean secure = mKeyguardStateController.isMethodSecure();
823 return (secure && !canDismissLs) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
Jason Monkb59f46f2016-09-27 12:29:18 -0400824 }
825 }
Adrian Roos7e58a082018-03-09 16:40:56 +0100826
827 @Override
828 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
829 int bottom = insets.getDisplayCutout() != null
830 ? insets.getDisplayCutout().getSafeInsetBottom() : 0;
831 if (isPaddingRelative()) {
832 setPaddingRelative(getPaddingStart(), getPaddingTop(), getPaddingEnd(), bottom);
833 } else {
834 setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottom);
835 }
836 return insets;
837 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200838}