blob: 60d62d52995d36f585bc413bf4a2e764cf874894 [file] [log] [blame]
Jorim Jaggia6310292014-04-16 14:11:52 +02001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar.phone;
18
Selim Cinek5f145022016-08-02 16:00:12 -070019import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
20import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
Jason Monk2a6ea9c2017-01-26 11:14:51 -050021
Jason Monk1d9632d2017-02-09 13:20:04 -080022import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON;
Jason Monkd6fa02f2017-01-25 18:26:50 -050023import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
Jason Monk1d9632d2017-02-09 13:20:04 -080024import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON;
Jason Monkd6fa02f2017-01-25 18:26:50 -050025import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK;
Selim Cinek5f145022016-08-02 16:00:12 -070026
Jorim Jaggid9449862015-05-29 14:49:08 -070027import android.app.ActivityManager;
Robert Carrfd10cd12016-06-29 16:41:50 -070028import android.app.ActivityOptions;
Jorim Jaggia6310292014-04-16 14:11:52 +020029import android.app.admin.DevicePolicyManager;
30import android.content.BroadcastReceiver;
Jorim Jaggid9449862015-05-29 14:49:08 -070031import android.content.ComponentName;
Jorim Jaggia6310292014-04-16 14:11:52 +020032import android.content.Context;
33import android.content.Intent;
34import android.content.IntentFilter;
Jorim Jaggid9449862015-05-29 14:49:08 -070035import android.content.ServiceConnection;
36import android.content.pm.ActivityInfo;
Jorim Jaggi97b63c42014-05-02 23:03:34 +020037import android.content.pm.PackageManager;
Adrian Roosa06905b2014-05-28 12:13:48 +020038import android.content.pm.ResolveInfo;
Jorim Jaggie210cc82014-08-12 23:44:59 +020039import android.content.res.Configuration;
Evan Roskyd388c752016-11-15 13:59:06 -080040import android.graphics.drawable.Drawable;
Yorke Lee583a20242014-08-12 18:47:08 -070041import android.os.AsyncTask;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020042import android.os.Bundle;
Jorim Jaggid9449862015-05-29 14:49:08 -070043import android.os.IBinder;
44import android.os.Message;
45import android.os.Messenger;
Jorim Jaggia6310292014-04-16 14:11:52 +020046import android.os.RemoteException;
47import android.os.UserHandle;
48import android.provider.MediaStore;
Jorim Jaggid9449862015-05-29 14:49:08 -070049import android.service.media.CameraPrewarmService;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070050import android.telecom.TelecomManager;
Jason Monkd6fa02f2017-01-25 18:26:50 -050051import android.text.TextUtils;
Jorim Jaggia6310292014-04-16 14:11:52 +020052import android.util.AttributeSet;
53import android.util.Log;
Lucas Dupin4272f442018-01-13 22:00:35 -080054import android.util.MathUtils;
Jorim Jaggie210cc82014-08-12 23:44:59 +020055import android.util.TypedValue;
Jorim Jaggia6310292014-04-16 14:11:52 +020056import android.view.View;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020057import android.view.ViewGroup;
Adrian Roos7e58a082018-03-09 16:40:56 +010058import android.view.WindowInsets;
Robert Carrfd10cd12016-06-29 16:41:50 -070059import android.view.WindowManager;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020060import android.view.accessibility.AccessibilityNodeInfo;
Jorim Jaggia6310292014-04-16 14:11:52 +020061import android.widget.FrameLayout;
Jorim Jaggie210cc82014-08-12 23:44:59 +020062import android.widget.TextView;
Adrian Roosa06905b2014-05-28 12:13:48 +020063
Chris Wren27a52fa2017-02-01 14:21:43 -050064import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Adrian Roosa06905b2014-05-28 12:13:48 +020065import com.android.internal.widget.LockPatternUtils;
66import com.android.keyguard.KeyguardUpdateMonitor;
67import com.android.keyguard.KeyguardUpdateMonitorCallback;
Christoph Studerb0183992014-12-22 21:02:26 +010068import com.android.systemui.EventLogTags;
Jason Monk9c7844c2017-01-18 15:21:53 -050069import com.android.systemui.Dependency;
Winsonc0d70582016-01-29 10:24:39 -080070import com.android.systemui.Interpolators;
Jorim Jaggia6310292014-04-16 14:11:52 +020071import com.android.systemui.R;
Selim Cineke70d6532015-04-24 16:46:13 -070072import com.android.systemui.assist.AssistManager;
Jason Monkb59f46f2016-09-27 12:29:18 -040073import com.android.systemui.plugins.IntentButtonProvider;
74import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
75import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState;
76import com.android.systemui.plugins.PluginListener;
Jason Monkec34da82017-02-24 15:57:05 -050077import com.android.systemui.plugins.ActivityStarter;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020078import com.android.systemui.statusbar.CommandQueue;
Selim Cinekbaa23272014-07-08 18:01:07 +020079import com.android.systemui.statusbar.KeyguardAffordanceView;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020080import com.android.systemui.statusbar.KeyguardIndicationController;
81import com.android.systemui.statusbar.policy.AccessibilityController;
Jason Monk1d9632d2017-02-09 13:20:04 -080082import com.android.systemui.statusbar.policy.ExtensionController;
83import com.android.systemui.statusbar.policy.ExtensionController.Extension;
Jorim Jaggib2e104f2014-08-15 18:12:36 +020084import com.android.systemui.statusbar.policy.FlashlightController;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020085import com.android.systemui.statusbar.policy.PreviewInflater;
Jason Monk1d9632d2017-02-09 13:20:04 -080086import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory;
Jason Monkd6fa02f2017-01-25 18:26:50 -050087import com.android.systemui.tuner.TunerService;
Jorim Jaggia6310292014-04-16 14:11:52 +020088
89/**
90 * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
91 * text.
92 */
Selim Cinek4c6969a2014-05-26 19:22:17 +020093public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
Jorim Jaggib2e104f2014-08-15 18:12:36 +020094 UnlockMethodCache.OnUnlockMethodChangedListener,
Jason Monk1d9632d2017-02-09 13:20:04 -080095 AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
Jorim Jaggia6310292014-04-16 14:11:52 +020096
Jason Monk2a6ea9c2017-01-26 11:14:51 -050097 final static String TAG = "StatusBar/KeyguardBottomAreaView";
Jorim Jaggia6310292014-04-16 14:11:52 +020098
Jorim Jaggi40aa8812015-09-23 12:59:22 -070099 public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance";
100 public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture";
101 public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap";
Jonathan Solnita4138162017-05-10 21:06:04 -0700102 public static final String CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = "lift_to_launch_ml";
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700103
104 public static final String EXTRA_CAMERA_LAUNCH_SOURCE
105 = "com.android.systemui.camera_launch_source";
106
Jason Monkb59f46f2016-09-27 12:29:18 -0400107 private static final String LEFT_BUTTON_PLUGIN
108 = "com.android.systemui.action.PLUGIN_LOCKSCREEN_LEFT_BUTTON";
109 private static final String RIGHT_BUTTON_PLUGIN
110 = "com.android.systemui.action.PLUGIN_LOCKSCREEN_RIGHT_BUTTON";
111
Adrian Roosa06905b2014-05-28 12:13:48 +0200112 private static final Intent SECURE_CAMERA_INTENT =
113 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
114 .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Selim Cinek372d1bd2015-08-14 13:19:37 -0700115 public static final Intent INSECURE_CAMERA_INTENT =
Adrian Roosa06905b2014-05-28 12:13:48 +0200116 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200117 private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100118 private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
119 private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200120
Jason Monkb59f46f2016-09-27 12:29:18 -0400121 private KeyguardAffordanceView mRightAffordanceView;
Selim Cineke70d6532015-04-24 16:46:13 -0700122 private KeyguardAffordanceView mLeftAffordanceView;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700123 private LockIcon mLockIcon;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100124 private ViewGroup mIndicationArea;
125 private TextView mEnterpriseDisclosure;
Jorim Jaggie210cc82014-08-12 23:44:59 +0200126 private TextView mIndicationText;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200127 private ViewGroup mPreviewContainer;
Philip Quinnb86efa42017-07-08 12:59:24 -0700128 private ViewGroup mOverlayContainer;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200129
Selim Cineke70d6532015-04-24 16:46:13 -0700130 private View mLeftPreview;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200131 private View mCameraPreview;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200132
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200133 private ActivityStarter mActivityStarter;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200134 private UnlockMethodCache mUnlockMethodCache;
Adrian Roosa06905b2014-05-28 12:13:48 +0200135 private LockPatternUtils mLockPatternUtils;
Adrian Roos1e1d6ac2014-07-22 17:18:55 +0200136 private FlashlightController mFlashlightController;
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200137 private PreviewInflater mPreviewInflater;
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200138 private KeyguardIndicationController mIndicationController;
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200139 private AccessibilityController mAccessibilityController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500140 private StatusBar mStatusBar;
Jorim Jaggidadafd42016-09-30 07:20:25 -0700141 private KeyguardAffordanceHelper mAffordanceHelper;
Adrian Roos2fe592d2014-05-17 03:11:59 +0200142
Adrian Roosa4eba9f2015-07-22 18:13:04 -0700143 private boolean mUserSetupComplete;
Jorim Jaggid9449862015-05-29 14:49:08 -0700144 private boolean mPrewarmBound;
145 private Messenger mPrewarmMessenger;
146 private final ServiceConnection mPrewarmConnection = new ServiceConnection() {
147
148 @Override
149 public void onServiceConnected(ComponentName name, IBinder service) {
150 mPrewarmMessenger = new Messenger(service);
Jorim Jaggid9449862015-05-29 14:49:08 -0700151 }
152
153 @Override
154 public void onServiceDisconnected(ComponentName name) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700155 mPrewarmMessenger = null;
156 }
157 };
158
Selim Cineke70d6532015-04-24 16:46:13 -0700159 private boolean mLeftIsVoiceAssist;
160 private AssistManager mAssistManager;
Evan Roskyd388c752016-11-15 13:59:06 -0800161 private Drawable mLeftAssistIcon;
Adrian Roos72cc3702014-09-18 17:25:09 +0200162
Jason Monkb59f46f2016-09-27 12:29:18 -0400163 private IntentButton mRightButton = new DefaultRightButton();
Jason Monk1d9632d2017-02-09 13:20:04 -0800164 private Extension<IntentButton> mRightExtension;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500165 private String mRightButtonStr;
Jason Monkb59f46f2016-09-27 12:29:18 -0400166 private IntentButton mLeftButton = new DefaultLeftButton();
Jason Monk1d9632d2017-02-09 13:20:04 -0800167 private Extension<IntentButton> mLeftExtension;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500168 private String mLeftButtonStr;
Chris Wren27a52fa2017-02-01 14:21:43 -0500169 private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
Adrian Roos91ba3072017-02-14 16:50:46 +0100170 private boolean mDozing;
Lucas Dupin4272f442018-01-13 22:00:35 -0800171 private int mIndicationBottomMargin;
172 private int mIndicationBottomMarginAmbient;
173 private float mDarkAmount;
174 private int mBurnInXOffset;
Lucas Dupin8c556d72018-06-27 11:44:57 -0700175 private int mBurnInYOffset;
Jason Monkb59f46f2016-09-27 12:29:18 -0400176
Jorim Jaggia6310292014-04-16 14:11:52 +0200177 public KeyguardBottomAreaView(Context context) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200178 this(context, null);
Jorim Jaggia6310292014-04-16 14:11:52 +0200179 }
180
181 public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200182 this(context, attrs, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200183 }
184
185 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200186 this(context, attrs, defStyleAttr, 0);
Jorim Jaggia6310292014-04-16 14:11:52 +0200187 }
188
189 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
190 int defStyleRes) {
191 super(context, attrs, defStyleAttr, defStyleRes);
192 }
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;
199 if (host == mLockIcon) {
200 label = getResources().getString(R.string.unlock_label);
Jason Monkb59f46f2016-09-27 12:29:18 -0400201 } else if (host == mRightAffordanceView) {
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200202 label = getResources().getString(R.string.camera_label);
Selim Cineke70d6532015-04-24 16:46:13 -0700203 } else if (host == mLeftAffordanceView) {
204 if (mLeftIsVoiceAssist) {
205 label = getResources().getString(R.string.voice_assist_label);
206 } else {
207 label = getResources().getString(R.string.phone_label);
208 }
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200209 }
210 info.addAction(new AccessibilityAction(ACTION_CLICK, label));
211 }
212
213 @Override
214 public boolean performAccessibilityAction(View host, int action, Bundle args) {
215 if (action == ACTION_CLICK) {
216 if (host == mLockIcon) {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500217 mStatusBar.animateCollapsePanels(
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +0100218 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200219 return true;
Jason Monkb59f46f2016-09-27 12:29:18 -0400220 } else if (host == mRightAffordanceView) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700221 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200222 return true;
Selim Cineke70d6532015-04-24 16:46:13 -0700223 } else if (host == mLeftAffordanceView) {
224 launchLeftAffordance();
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200225 return true;
226 }
227 }
228 return super.performAccessibilityAction(host, action, args);
229 }
230 };
231
Jorim Jaggia6310292014-04-16 14:11:52 +0200232 @Override
233 protected void onFinishInflate() {
234 super.onFinishInflate();
Adrian Roosa06905b2014-05-28 12:13:48 +0200235 mLockPatternUtils = new LockPatternUtils(mContext);
Alan Viverette51efddb2017-04-05 10:00:01 -0400236 mPreviewContainer = findViewById(R.id.preview_container);
Philip Quinnb86efa42017-07-08 12:59:24 -0700237 mOverlayContainer = findViewById(R.id.overlay_container);
Alan Viverette51efddb2017-04-05 10:00:01 -0400238 mRightAffordanceView = findViewById(R.id.camera_button);
239 mLeftAffordanceView = findViewById(R.id.left_button);
240 mLockIcon = findViewById(R.id.lock_icon);
241 mIndicationArea = findViewById(R.id.keyguard_indication_area);
242 mEnterpriseDisclosure = findViewById(
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100243 R.id.keyguard_indication_enterprise_disclosure);
Alan Viverette51efddb2017-04-05 10:00:01 -0400244 mIndicationText = findViewById(R.id.keyguard_indication_text);
Lucas Dupin4272f442018-01-13 22:00:35 -0800245 mIndicationBottomMargin = getResources().getDimensionPixelSize(
246 R.dimen.keyguard_indication_margin_bottom);
247 mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
248 R.dimen.keyguard_indication_margin_bottom_ambient);
Lucas Dupin8c556d72018-06-27 11:44:57 -0700249 mBurnInYOffset = getResources().getDimensionPixelSize(
250 R.dimen.charging_indication_burn_in_prevention_offset_y);
Jorim Jaggia6310292014-04-16 14:11:52 +0200251 updateCameraVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200252 mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
253 mUnlockMethodCache.addListener(this);
Selim Cinek9a105312017-07-21 17:16:05 -0700254 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
255 mLockIcon.setScreenOn(updateMonitor.isScreenOn());
256 mLockIcon.setDeviceInteractive(updateMonitor.isDeviceInteractive());
Jorim Jaggi27267d62015-04-28 13:27:12 -0700257 mLockIcon.update();
Selim Cinekbaa23272014-07-08 18:01:07 +0200258 setClipChildren(false);
259 setClipToPadding(false);
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200260 mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
Selim Cineke70d6532015-04-24 16:46:13 -0700261 inflateCameraPreview();
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200262 mLockIcon.setOnClickListener(this);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200263 mLockIcon.setOnLongClickListener(this);
Jason Monkb59f46f2016-09-27 12:29:18 -0400264 mRightAffordanceView.setOnClickListener(this);
Selim Cineke70d6532015-04-24 16:46:13 -0700265 mLeftAffordanceView.setOnClickListener(this);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200266 initAccessibility();
Jason Monk9c7844c2017-01-18 15:21:53 -0500267 mActivityStarter = Dependency.get(ActivityStarter.class);
268 mFlashlightController = Dependency.get(FlashlightController.class);
269 mAccessibilityController = Dependency.get(AccessibilityController.class);
270 mAssistManager = Dependency.get(AssistManager.class);
Adrian Roos83c60c02017-07-06 15:36:32 +0200271 mLockIcon.setAccessibilityController(mAccessibilityController);
Jason Monk9c7844c2017-01-18 15:21:53 -0500272 updateLeftAffordance();
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200273 }
274
Jason Monkb59f46f2016-09-27 12:29:18 -0400275 @Override
276 protected void onAttachedToWindow() {
277 super.onAttachedToWindow();
Jason Monk9ef73072017-01-27 13:32:51 -0500278 mAccessibilityController.addStateChangedCallback(this);
Jason Monk1d9632d2017-02-09 13:20:04 -0800279 mRightExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
280 .withPlugin(IntentButtonProvider.class, RIGHT_BUTTON_PLUGIN,
281 p -> p.getIntentButton())
282 .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_RIGHT_BUTTON))
283 .withDefault(() -> new DefaultRightButton())
284 .withCallback(button -> setRightButton(button))
285 .build();
286 mLeftExtension = Dependency.get(ExtensionController.class).newExtension(IntentButton.class)
287 .withPlugin(IntentButtonProvider.class, LEFT_BUTTON_PLUGIN,
288 p -> p.getIntentButton())
289 .withTunerFactory(new LockButtonFactory(mContext, LOCKSCREEN_LEFT_BUTTON))
290 .withDefault(() -> new DefaultLeftButton())
291 .withCallback(button -> setLeftButton(button))
292 .build();
Selim Cinek9a105312017-07-21 17:16:05 -0700293 final IntentFilter filter = new IntentFilter();
294 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
295 getContext().registerReceiverAsUser(mDevicePolicyReceiver,
296 UserHandle.ALL, filter, null, null);
297 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
Jason Monkb59f46f2016-09-27 12:29:18 -0400298 }
299
300 @Override
301 protected void onDetachedFromWindow() {
302 super.onDetachedFromWindow();
Jason Monk9ef73072017-01-27 13:32:51 -0500303 mAccessibilityController.removeStateChangedCallback(this);
Jason Monk1d9632d2017-02-09 13:20:04 -0800304 mRightExtension.destroy();
305 mLeftExtension.destroy();
Selim Cinek9a105312017-07-21 17:16:05 -0700306 getContext().unregisterReceiver(mDevicePolicyReceiver);
307 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallback);
Jason Monkb59f46f2016-09-27 12:29:18 -0400308 }
309
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200310 private void initAccessibility() {
311 mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
Selim Cineke70d6532015-04-24 16:46:13 -0700312 mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
Jason Monkb59f46f2016-09-27 12:29:18 -0400313 mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
Jorim Jaggia6310292014-04-16 14:11:52 +0200314 }
315
Jorim Jaggie210cc82014-08-12 23:44:59 +0200316 @Override
317 protected void onConfigurationChanged(Configuration newConfig) {
318 super.onConfigurationChanged(newConfig);
Lucas Dupin4272f442018-01-13 22:00:35 -0800319 mIndicationBottomMargin = getResources().getDimensionPixelSize(
Jorim Jaggie210cc82014-08-12 23:44:59 +0200320 R.dimen.keyguard_indication_margin_bottom);
Lucas Dupin4272f442018-01-13 22:00:35 -0800321 mIndicationBottomMarginAmbient = getResources().getDimensionPixelSize(
322 R.dimen.keyguard_indication_margin_bottom_ambient);
Lucas Dupin8c556d72018-06-27 11:44:57 -0700323 mBurnInYOffset = getResources().getDimensionPixelSize(
324 R.dimen.charging_indication_burn_in_prevention_offset_y);
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100325 MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams();
Lucas Dupin4272f442018-01-13 22:00:35 -0800326 if (mlp.bottomMargin != mIndicationBottomMargin) {
327 mlp.bottomMargin = mIndicationBottomMargin;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100328 mIndicationArea.setLayoutParams(mlp);
Jorim Jaggie210cc82014-08-12 23:44:59 +0200329 }
330
331 // Respect font size setting.
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100332 mEnterpriseDisclosure.setTextSize(TypedValue.COMPLEX_UNIT_PX,
333 getResources().getDimensionPixelSize(
334 com.android.internal.R.dimen.text_size_small_material));
Jorim Jaggie210cc82014-08-12 23:44:59 +0200335 mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
336 getResources().getDimensionPixelSize(
337 com.android.internal.R.dimen.text_size_small_material));
Selim Cinek6ebba592016-05-31 15:28:28 -0700338
Jason Monkb59f46f2016-09-27 12:29:18 -0400339 ViewGroup.LayoutParams lp = mRightAffordanceView.getLayoutParams();
Selim Cinek6ebba592016-05-31 15:28:28 -0700340 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
341 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
Jason Monkb59f46f2016-09-27 12:29:18 -0400342 mRightAffordanceView.setLayoutParams(lp);
343 updateRightAffordanceIcon();
Selim Cinek6ebba592016-05-31 15:28:28 -0700344
345 lp = mLockIcon.getLayoutParams();
346 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
347 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
348 mLockIcon.setLayoutParams(lp);
Adrian Rooseffff9c2017-08-09 15:50:00 +0200349 mLockIcon.setContentDescription(getContext().getText(R.string.accessibility_unlock_button));
Selim Cinek6ebba592016-05-31 15:28:28 -0700350 mLockIcon.update(true /* force */);
351
352 lp = mLeftAffordanceView.getLayoutParams();
353 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
354 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
355 mLeftAffordanceView.setLayoutParams(lp);
356 updateLeftAffordanceIcon();
Jorim Jaggie210cc82014-08-12 23:44:59 +0200357 }
358
Jason Monkb59f46f2016-09-27 12:29:18 -0400359 private void updateRightAffordanceIcon() {
360 IconState state = mRightButton.getIcon();
Adrian Roos674b8ea2017-05-25 12:33:17 -0700361 mRightAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE);
Jason Monkca215682017-02-09 14:32:54 -0800362 mRightAffordanceView.setImageDrawable(state.drawable, state.tint);
Jason Monkb59f46f2016-09-27 12:29:18 -0400363 mRightAffordanceView.setContentDescription(state.contentDescription);
364 }
365
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500366 public void setStatusBar(StatusBar statusBar) {
367 mStatusBar = statusBar;
Dan Sandlere163a642015-03-01 22:58:32 -0500368 updateCameraVisibility(); // in case onFinishInflate() was called too early
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200369 }
370
Jorim Jaggidadafd42016-09-30 07:20:25 -0700371 public void setAffordanceHelper(KeyguardAffordanceHelper affordanceHelper) {
372 mAffordanceHelper = affordanceHelper;
373 }
374
Adrian Roosa4eba9f2015-07-22 18:13:04 -0700375 public void setUserSetupComplete(boolean userSetupComplete) {
376 mUserSetupComplete = userSetupComplete;
377 updateCameraVisibility();
378 updateLeftAffordanceIcon();
379 }
380
Adrian Roosa06905b2014-05-28 12:13:48 +0200381 private Intent getCameraIntent() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400382 return mRightButton.getIntent();
Adrian Roosa06905b2014-05-28 12:13:48 +0200383 }
384
Zhentao Sun04f97402015-08-26 17:37:30 -0700385 /**
386 * Resolves the intent to launch the camera application.
387 */
388 public ResolveInfo resolveCameraIntent() {
389 return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
390 PackageManager.MATCH_DEFAULT_ONLY,
391 KeyguardUpdateMonitor.getCurrentUser());
392 }
393
Jorim Jaggia6310292014-04-16 14:11:52 +0200394 private void updateCameraVisibility() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400395 if (mRightAffordanceView == null) {
Dan Sandlere163a642015-03-01 22:58:32 -0500396 // Things are not set up yet; reply hazy, ask again later
397 return;
398 }
Adrian Roos91ba3072017-02-14 16:50:46 +0100399 mRightAffordanceView.setVisibility(!mDozing && mRightButton.getIcon().isVisible
Jason Monkb59f46f2016-09-27 12:29:18 -0400400 ? View.VISIBLE : View.GONE);
Jorim Jaggia6310292014-04-16 14:11:52 +0200401 }
402
Evan Roskyd388c752016-11-15 13:59:06 -0800403 /**
404 * Set an alternate icon for the left assist affordance (replace the mic icon)
405 */
406 public void setLeftAssistIcon(Drawable drawable) {
407 mLeftAssistIcon = drawable;
408 updateLeftAffordanceIcon();
409 }
410
Selim Cineke70d6532015-04-24 16:46:13 -0700411 private void updateLeftAffordanceIcon() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400412 IconState state = mLeftButton.getIcon();
Adrian Roos91ba3072017-02-14 16:50:46 +0100413 mLeftAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE);
Jason Monkca215682017-02-09 14:32:54 -0800414 mLeftAffordanceView.setImageDrawable(state.drawable, state.tint);
Jason Monkb59f46f2016-09-27 12:29:18 -0400415 mLeftAffordanceView.setContentDescription(state.contentDescription);
Selim Cineke70d6532015-04-24 16:46:13 -0700416 }
417
418 public boolean isLeftVoiceAssist() {
419 return mLeftIsVoiceAssist;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200420 }
421
422 private boolean isPhoneVisible() {
423 PackageManager pm = mContext.getPackageManager();
424 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
425 && pm.resolveActivity(PHONE_INTENT, 0) != null;
426 }
427
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200428 @Override
429 public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
Jason Monkb59f46f2016-09-27 12:29:18 -0400430 mRightAffordanceView.setClickable(touchExplorationEnabled);
Selim Cineke70d6532015-04-24 16:46:13 -0700431 mLeftAffordanceView.setClickable(touchExplorationEnabled);
Jason Monkb59f46f2016-09-27 12:29:18 -0400432 mRightAffordanceView.setFocusable(accessibilityEnabled);
Selim Cineke70d6532015-04-24 16:46:13 -0700433 mLeftAffordanceView.setFocusable(accessibilityEnabled);
Jorim Jaggi27267d62015-04-28 13:27:12 -0700434 mLockIcon.update();
Jorim Jaggia6310292014-04-16 14:11:52 +0200435 }
436
Selim Cinek4c6969a2014-05-26 19:22:17 +0200437 @Override
438 public void onClick(View v) {
Jason Monkb59f46f2016-09-27 12:29:18 -0400439 if (v == mRightAffordanceView) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700440 launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
Selim Cineke70d6532015-04-24 16:46:13 -0700441 } else if (v == mLeftAffordanceView) {
442 launchLeftAffordance();
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200443 } if (v == mLockIcon) {
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200444 if (!mAccessibilityController.isAccessibilityEnabled()) {
445 handleTrustCircleClick();
446 } else {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500447 mStatusBar.animateCollapsePanels(
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200448 CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
449 }
Selim Cinek4c6969a2014-05-26 19:22:17 +0200450 }
451 }
452
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200453 @Override
454 public boolean onLongClick(View v) {
455 handleTrustCircleClick();
456 return true;
457 }
458
459 private void handleTrustCircleClick() {
Chris Wren27a52fa2017-02-01 14:21:43 -0500460 mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_LOCK, 0 /* lengthDp - N/A */,
Christoph Studerb0183992014-12-22 21:02:26 +0100461 0 /* velocityDp - N/A */);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200462 mIndicationController.showTransientIndication(
463 R.string.keyguard_indication_trust_disabled);
Adrian Roosd6aa6cb2015-04-16 19:31:29 -0700464 mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200465 }
466
Jorim Jaggid9449862015-05-29 14:49:08 -0700467 public void bindCameraPrewarmService() {
Adrian Roosa06905b2014-05-28 12:13:48 +0200468 Intent intent = getCameraIntent();
Jorim Jaggid9449862015-05-29 14:49:08 -0700469 ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent,
Selim Cinek5f145022016-08-02 16:00:12 -0700470 KeyguardUpdateMonitor.getCurrentUser(), true /* onlyDirectBootAware */);
Jorim Jaggi8b8fa3e2015-08-18 18:33:49 -0700471 if (targetInfo != null && targetInfo.metaData != null) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700472 String clazz = targetInfo.metaData.getString(
473 MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE);
474 if (clazz != null) {
475 Intent serviceIntent = new Intent();
476 serviceIntent.setClassName(targetInfo.packageName, clazz);
477 serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM);
478 try {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700479 if (getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection,
Selim Cinekedf47482015-09-01 18:05:08 -0700480 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
481 new UserHandle(UserHandle.USER_CURRENT))) {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700482 mPrewarmBound = true;
483 }
Jorim Jaggid9449862015-05-29 14:49:08 -0700484 } catch (SecurityException e) {
485 Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName
486 + " class=" + clazz, e);
487 }
488 }
Jorim Jaggia86790b2015-04-02 16:32:29 -0700489 }
490 }
491
Jorim Jaggid9449862015-05-29 14:49:08 -0700492 public void unbindCameraPrewarmService(boolean launched) {
493 if (mPrewarmBound) {
Jorim Jaggif610bd72015-08-17 20:17:30 -0700494 if (mPrewarmMessenger != null && launched) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700495 try {
496 mPrewarmMessenger.send(Message.obtain(null /* handler */,
497 CameraPrewarmService.MSG_CAMERA_FIRED));
498 } catch (RemoteException e) {
499 Log.w(TAG, "Error sending camera fired message", e);
500 }
501 }
502 mContext.unbindService(mPrewarmConnection);
503 mPrewarmBound = false;
Jorim Jaggia86790b2015-04-02 16:32:29 -0700504 }
505 }
506
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700507 public void launchCamera(String source) {
Jorim Jaggia86790b2015-04-02 16:32:29 -0700508 final Intent intent = getCameraIntent();
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700509 intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200510 boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
Adrian Roosd6aa6cb2015-04-16 19:31:29 -0700511 mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200512 if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
Jorim Jaggia86790b2015-04-02 16:32:29 -0700513 AsyncTask.execute(new Runnable() {
514 @Override
515 public void run() {
Jorim Jaggid9449862015-05-29 14:49:08 -0700516 int result = ActivityManager.START_CANCELED;
Robert Carrfd10cd12016-06-29 16:41:50 -0700517
518 // Normally an activity will set it's requested rotation
519 // animation on its window. However when launching an activity
520 // causes the orientation to change this is too late. In these cases
521 // the default animation is used. This doesn't look good for
522 // the camera (as it rotates the camera contents out of sync
523 // with physical reality). So, we ask the WindowManager to
524 // force the crossfade animation if an orientation change
525 // happens to occur during the launch.
526 ActivityOptions o = ActivityOptions.makeBasic();
Winson Chungf7e03e12017-08-22 11:32:16 -0700527 o.setDisallowEnterPictureInPictureWhileLaunching(true);
Robert Carrfd10cd12016-06-29 16:41:50 -0700528 o.setRotationAnimationHint(
Robert Carr57d9fbd2016-08-15 12:00:35 -0700529 WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
Jorim Jaggid9449862015-05-29 14:49:08 -0700530 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800531 result = ActivityManager.getService().startActivityAsUser(
Jorim Jaggid9449862015-05-29 14:49:08 -0700532 null, getContext().getBasePackageName(),
533 intent,
534 intent.resolveTypeIfNeeded(getContext().getContentResolver()),
Robert Carrfd10cd12016-06-29 16:41:50 -0700535 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, o.toBundle(),
Jorim Jaggid9449862015-05-29 14:49:08 -0700536 UserHandle.CURRENT.getIdentifier());
537 } catch (RemoteException e) {
538 Log.w(TAG, "Unable to start camera activity", e);
539 }
Jorim Jaggid9449862015-05-29 14:49:08 -0700540 final boolean launched = isSuccessfulLaunch(result);
541 post(new Runnable() {
542 @Override
543 public void run() {
544 unbindCameraPrewarmService(launched);
545 }
546 });
Jorim Jaggia86790b2015-04-02 16:32:29 -0700547 }
548 });
Adrian Roosa06905b2014-05-28 12:13:48 +0200549 } else {
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200550
551 // We need to delay starting the activity because ResolverActivity finishes itself if
552 // launched behind lockscreen.
Jorim Jaggid9449862015-05-29 14:49:08 -0700553 mActivityStarter.startActivity(intent, false /* dismissShade */,
554 new ActivityStarter.Callback() {
555 @Override
556 public void onActivityStarted(int resultCode) {
557 unbindCameraPrewarmService(isSuccessfulLaunch(resultCode));
558 }
559 });
Adrian Roosa06905b2014-05-28 12:13:48 +0200560 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200561 }
562
Lucas Dupin4272f442018-01-13 22:00:35 -0800563 public void setDarkAmount(float darkAmount) {
564 if (darkAmount == mDarkAmount) {
565 return;
566 }
567 mDarkAmount = darkAmount;
Lucas Dupin4272f442018-01-13 22:00:35 -0800568 mIndicationArea.setAlpha(MathUtils.lerp(1f, 0.7f, darkAmount));
569 mIndicationArea.setTranslationY(MathUtils.lerp(0,
570 mIndicationBottomMargin - mIndicationBottomMarginAmbient, darkAmount));
571 }
572
Jorim Jaggid9449862015-05-29 14:49:08 -0700573 private static boolean isSuccessfulLaunch(int result) {
574 return result == ActivityManager.START_SUCCESS
575 || result == ActivityManager.START_DELIVERED_TO_TOP
576 || result == ActivityManager.START_TASK_TO_FRONT;
577 }
578
Selim Cineke70d6532015-04-24 16:46:13 -0700579 public void launchLeftAffordance() {
580 if (mLeftIsVoiceAssist) {
581 launchVoiceAssist();
582 } else {
583 launchPhone();
584 }
585 }
586
587 private void launchVoiceAssist() {
588 Runnable runnable = new Runnable() {
589 @Override
590 public void run() {
591 mAssistManager.launchVoiceAssistFromKeyguard();
Selim Cineke70d6532015-04-24 16:46:13 -0700592 }
593 };
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500594 if (mStatusBar.isKeyguardCurrentlySecure()) {
Selim Cineke70d6532015-04-24 16:46:13 -0700595 AsyncTask.execute(runnable);
596 } else {
Jason Monkd6fa02f2017-01-25 18:26:50 -0500597 boolean dismissShade = !TextUtils.isEmpty(mRightButtonStr)
Jason Monkde850bb2017-02-01 19:26:30 -0500598 && Dependency.get(TunerService.class).getValue(LOCKSCREEN_RIGHT_UNLOCK, 1) != 0;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500599 mStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
Jason Monkd6fa02f2017-01-25 18:26:50 -0500600 dismissShade, false /* afterKeyguardGone */, true /* deferred */);
Selim Cineke70d6532015-04-24 16:46:13 -0700601 }
602 }
603
604 private boolean canLaunchVoiceAssist() {
605 return mAssistManager.canVoiceAssistBeLaunchedFromKeyguard();
606 }
607
608 private void launchPhone() {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700609 final TelecomManager tm = TelecomManager.from(mContext);
Nancy Chen0eb1e402014-08-21 22:52:29 -0700610 if (tm.isInCall()) {
Yorke Lee583a20242014-08-12 18:47:08 -0700611 AsyncTask.execute(new Runnable() {
612 @Override
613 public void run() {
Nancy Chen0eb1e402014-08-21 22:52:29 -0700614 tm.showInCallScreen(false /* showDialpad */);
Yorke Lee583a20242014-08-12 18:47:08 -0700615 }
616 });
617 } else {
Jason Monkd6fa02f2017-01-25 18:26:50 -0500618 boolean dismissShade = !TextUtils.isEmpty(mLeftButtonStr)
Jason Monkde850bb2017-02-01 19:26:30 -0500619 && Dependency.get(TunerService.class).getValue(LOCKSCREEN_LEFT_UNLOCK, 1) != 0;
Jason Monkd6fa02f2017-01-25 18:26:50 -0500620 mActivityStarter.startActivity(mLeftButton.getIntent(), dismissShade);
Yorke Lee583a20242014-08-12 18:47:08 -0700621 }
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200622 }
623
Adrian Roos2fe592d2014-05-17 03:11:59 +0200624
625 @Override
626 protected void onVisibilityChanged(View changedView, int visibility) {
627 super.onVisibilityChanged(changedView, visibility);
628 if (changedView == this && visibility == VISIBLE) {
Jorim Jaggi27267d62015-04-28 13:27:12 -0700629 mLockIcon.update();
Adrian Roosa06905b2014-05-28 12:13:48 +0200630 updateCameraVisibility();
Adrian Roos2fe592d2014-05-17 03:11:59 +0200631 }
632 }
633
Selim Cineke70d6532015-04-24 16:46:13 -0700634 public KeyguardAffordanceView getLeftView() {
635 return mLeftAffordanceView;
Selim Cinek4c6969a2014-05-26 19:22:17 +0200636 }
637
Selim Cineke70d6532015-04-24 16:46:13 -0700638 public KeyguardAffordanceView getRightView() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400639 return mRightAffordanceView;
Selim Cinek4c6969a2014-05-26 19:22:17 +0200640 }
641
Selim Cineke70d6532015-04-24 16:46:13 -0700642 public View getLeftPreview() {
643 return mLeftPreview;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200644 }
645
Selim Cineke70d6532015-04-24 16:46:13 -0700646 public View getRightPreview() {
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200647 return mCameraPreview;
648 }
649
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700650 public LockIcon getLockIcon() {
Selim Cinek4c6969a2014-05-26 19:22:17 +0200651 return mLockIcon;
652 }
653
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100654 public View getIndicationArea() {
655 return mIndicationArea;
Selim Cinekf99d0002014-06-13 07:36:01 +0200656 }
657
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200658 @Override
Jorim Jaggi2580a9762014-06-25 03:08:25 +0200659 public boolean hasOverlappingRendering() {
660 return false;
661 }
662
663 @Override
Christoph Studer2231c6e2014-12-19 12:40:13 +0100664 public void onUnlockMethodStateChanged() {
Jorim Jaggi27267d62015-04-28 13:27:12 -0700665 mLockIcon.update();
Adrian Roosa06905b2014-05-28 12:13:48 +0200666 updateCameraVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200667 }
Adrian Roosa06905b2014-05-28 12:13:48 +0200668
Selim Cineke70d6532015-04-24 16:46:13 -0700669 private void inflateCameraPreview() {
Selim Cinek5f145022016-08-02 16:00:12 -0700670 View previewBefore = mCameraPreview;
671 boolean visibleBefore = false;
672 if (previewBefore != null) {
673 mPreviewContainer.removeView(previewBefore);
674 visibleBefore = previewBefore.getVisibility() == View.VISIBLE;
675 }
Jorim Jaggi781c29c2014-08-05 20:39:15 +0200676 mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200677 if (mCameraPreview != null) {
678 mPreviewContainer.addView(mCameraPreview);
Selim Cinek5f145022016-08-02 16:00:12 -0700679 mCameraPreview.setVisibility(visibleBefore ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200680 }
Jorim Jaggidadafd42016-09-30 07:20:25 -0700681 if (mAffordanceHelper != null) {
682 mAffordanceHelper.updatePreviews();
683 }
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200684 }
685
Selim Cineke70d6532015-04-24 16:46:13 -0700686 private void updateLeftPreview() {
687 View previewBefore = mLeftPreview;
688 if (previewBefore != null) {
689 mPreviewContainer.removeView(previewBefore);
690 }
691 if (mLeftIsVoiceAssist) {
692 mLeftPreview = mPreviewInflater.inflatePreviewFromService(
693 mAssistManager.getVoiceInteractorComponentName());
694 } else {
Jason Monkb59f46f2016-09-27 12:29:18 -0400695 mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent());
Selim Cineke70d6532015-04-24 16:46:13 -0700696 }
697 if (mLeftPreview != null) {
698 mPreviewContainer.addView(mLeftPreview);
699 mLeftPreview.setVisibility(View.INVISIBLE);
700 }
Jorim Jaggidadafd42016-09-30 07:20:25 -0700701 if (mAffordanceHelper != null) {
702 mAffordanceHelper.updatePreviews();
703 }
Selim Cineke70d6532015-04-24 16:46:13 -0700704 }
705
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100706 public void startFinishDozeAnimation() {
707 long delay = 0;
Selim Cineke70d6532015-04-24 16:46:13 -0700708 if (mLeftAffordanceView.getVisibility() == View.VISIBLE) {
709 startFinishDozeAnimationElement(mLeftAffordanceView, delay);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100710 delay += DOZE_ANIMATION_STAGGER_DELAY;
711 }
712 startFinishDozeAnimationElement(mLockIcon, delay);
713 delay += DOZE_ANIMATION_STAGGER_DELAY;
Jason Monkb59f46f2016-09-27 12:29:18 -0400714 if (mRightAffordanceView.getVisibility() == View.VISIBLE) {
715 startFinishDozeAnimationElement(mRightAffordanceView, delay);
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100716 }
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100717 }
718
719 private void startFinishDozeAnimationElement(View element, long delay) {
720 element.setAlpha(0f);
721 element.setTranslationY(element.getHeight() / 2);
722 element.animate()
723 .alpha(1f)
724 .translationY(0f)
Selim Cinekc18010f2016-01-20 13:41:30 -0800725 .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
Jorim Jaggi16423aa2014-10-28 11:42:58 +0100726 .setStartDelay(delay)
727 .setDuration(DOZE_ANIMATION_ELEMENT_DURATION);
728 }
729
Adrian Roosa06905b2014-05-28 12:13:48 +0200730 private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
Jim Millerb29814c2015-08-05 19:03:01 -0700731 @Override
Adrian Roosa06905b2014-05-28 12:13:48 +0200732 public void onReceive(Context context, Intent intent) {
733 post(new Runnable() {
734 @Override
735 public void run() {
736 updateCameraVisibility();
737 }
738 });
739 }
740 };
741
742 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
743 new KeyguardUpdateMonitorCallback() {
Jason Monkb59f46f2016-09-27 12:29:18 -0400744 @Override
745 public void onUserSwitchComplete(int userId) {
746 updateCameraVisibility();
747 }
Jorim Jaggie7b12522014-08-06 16:41:21 +0200748
Jason Monkb59f46f2016-09-27 12:29:18 -0400749 @Override
750 public void onStartedWakingUp() {
751 mLockIcon.setDeviceInteractive(true);
752 }
Adrian Roos2e3ccbb2014-08-19 22:23:37 +0200753
Jason Monkb59f46f2016-09-27 12:29:18 -0400754 @Override
755 public void onFinishedGoingToSleep(int why) {
756 mLockIcon.setDeviceInteractive(false);
757 }
Adrian Roosb9ae0902014-10-27 14:20:30 +0100758
Jason Monkb59f46f2016-09-27 12:29:18 -0400759 @Override
760 public void onScreenTurnedOn() {
761 mLockIcon.setScreenOn(true);
762 }
Jorim Jaggif1518da2015-07-30 11:56:36 -0700763
Jason Monkb59f46f2016-09-27 12:29:18 -0400764 @Override
765 public void onScreenTurnedOff() {
766 mLockIcon.setScreenOn(false);
767 }
Jorim Jaggif1518da2015-07-30 11:56:36 -0700768
Jason Monkb59f46f2016-09-27 12:29:18 -0400769 @Override
770 public void onKeyguardVisibilityChanged(boolean showing) {
771 mLockIcon.update();
772 }
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700773
Jason Monkb59f46f2016-09-27 12:29:18 -0400774 @Override
775 public void onFingerprintRunningStateChanged(boolean running) {
776 mLockIcon.update();
777 }
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700778
Jason Monkb59f46f2016-09-27 12:29:18 -0400779 @Override
780 public void onStrongAuthStateChanged(int userId) {
781 mLockIcon.update();
Adrian Roosa06905b2014-05-28 12:13:48 +0200782 }
783
Jorim Jaggi90f62792016-10-07 15:11:44 +0200784 @Override
785 public void onUserUnlocked() {
786 inflateCameraPreview();
787 updateCameraVisibility();
788 updateLeftAffordance();
Jason Monkb59f46f2016-09-27 12:29:18 -0400789 }
790 };
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200791
792 public void setKeyguardIndicationController(
793 KeyguardIndicationController keyguardIndicationController) {
794 mIndicationController = keyguardIndicationController;
795 }
Selim Cineke70d6532015-04-24 16:46:13 -0700796
Selim Cineke70d6532015-04-24 16:46:13 -0700797 public void updateLeftAffordance() {
798 updateLeftAffordanceIcon();
799 updateLeftPreview();
800 }
Selim Cinek5f145022016-08-02 16:00:12 -0700801
802 public void onKeyguardShowingChanged() {
803 updateLeftAffordance();
804 inflateCameraPreview();
805 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400806
807 private void setRightButton(IntentButton button) {
Jason Monk1d9632d2017-02-09 13:20:04 -0800808 mRightButton = button;
Jason Monkb59f46f2016-09-27 12:29:18 -0400809 updateRightAffordanceIcon();
810 updateCameraVisibility();
811 inflateCameraPreview();
812 }
813
814 private void setLeftButton(IntentButton button) {
Jason Monk1d9632d2017-02-09 13:20:04 -0800815 mLeftButton = button;
816 if (!(mLeftButton instanceof DefaultLeftButton)) {
817 mLeftIsVoiceAssist = false;
818 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400819 updateLeftAffordance();
820 }
821
Adrian Roos91ba3072017-02-14 16:50:46 +0100822 public void setDozing(boolean dozing, boolean animate) {
823 mDozing = dozing;
824
825 updateCameraVisibility();
826 updateLeftAffordanceIcon();
827
828 if (dozing) {
829 mLockIcon.setVisibility(INVISIBLE);
Philip Quinnb86efa42017-07-08 12:59:24 -0700830 mOverlayContainer.setVisibility(INVISIBLE);
Adrian Roos91ba3072017-02-14 16:50:46 +0100831 } else {
832 mLockIcon.setVisibility(VISIBLE);
Philip Quinnb86efa42017-07-08 12:59:24 -0700833 mOverlayContainer.setVisibility(VISIBLE);
Adrian Roos91ba3072017-02-14 16:50:46 +0100834 if (animate) {
835 startFinishDozeAnimation();
836 }
837 }
838 }
839
Lucas Dupin4272f442018-01-13 22:00:35 -0800840 public void dozeTimeTick() {
841 if (mDarkAmount == 1) {
842 // Move indication every minute to avoid burn-in
Lucas Dupin8c556d72018-06-27 11:44:57 -0700843 int dozeTranslation = mIndicationBottomMargin - mIndicationBottomMarginAmbient;
844 int burnInYOffset = (int) (-mBurnInYOffset + Math.random() * mBurnInYOffset * 2);
845 mIndicationArea.setTranslationY(dozeTranslation + burnInYOffset);
Lucas Dupin4272f442018-01-13 22:00:35 -0800846 }
847 }
848
849 public void setBurnInXOffset(int burnInXOffset) {
850 if (mBurnInXOffset == burnInXOffset) {
851 return;
852 }
853 mBurnInXOffset = burnInXOffset;
854 mIndicationArea.setTranslationX(burnInXOffset);
855 }
856
Jason Monkb59f46f2016-09-27 12:29:18 -0400857 private class DefaultLeftButton implements IntentButton {
858
859 private IconState mIconState = new IconState();
860
861 @Override
862 public IconState getIcon() {
863 mLeftIsVoiceAssist = canLaunchVoiceAssist();
Lucas Dupinf78c5402018-01-05 12:57:27 -0800864 final boolean showAffordance =
865 getResources().getBoolean(R.bool.config_keyguardShowLeftAffordance);
Jason Monkb59f46f2016-09-27 12:29:18 -0400866 if (mLeftIsVoiceAssist) {
Lucas Dupinf78c5402018-01-05 12:57:27 -0800867 mIconState.isVisible = mUserSetupComplete && showAffordance;
Evan Roskyd388c752016-11-15 13:59:06 -0800868 if (mLeftAssistIcon == null) {
869 mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp);
870 } else {
871 mIconState.drawable = mLeftAssistIcon;
872 }
Jason Monkb59f46f2016-09-27 12:29:18 -0400873 mIconState.contentDescription = mContext.getString(
874 R.string.accessibility_voice_assist_button);
875 } else {
Lucas Dupinf78c5402018-01-05 12:57:27 -0800876 mIconState.isVisible = mUserSetupComplete && showAffordance && isPhoneVisible();
Jason Monkb59f46f2016-09-27 12:29:18 -0400877 mIconState.drawable = mContext.getDrawable(R.drawable.ic_phone_24dp);
878 mIconState.contentDescription = mContext.getString(
879 R.string.accessibility_phone_button);
880 }
881 return mIconState;
882 }
883
884 @Override
885 public Intent getIntent() {
886 return PHONE_INTENT;
887 }
888 }
889
890 private class DefaultRightButton implements IntentButton {
891
892 private IconState mIconState = new IconState();
893
894 @Override
895 public IconState getIcon() {
896 ResolveInfo resolved = resolveCameraIntent();
Esteban Talavera40f8b992017-07-14 16:14:07 +0100897 boolean isCameraDisabled = (mStatusBar != null) && !mStatusBar.isCameraAllowedByAdmin();
898 mIconState.isVisible = !isCameraDisabled && resolved != null
Jason Monkb59f46f2016-09-27 12:29:18 -0400899 && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
900 && mUserSetupComplete;
901 mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
902 mIconState.contentDescription =
903 mContext.getString(R.string.accessibility_camera_button);
904 return mIconState;
905 }
906
907 @Override
908 public Intent getIntent() {
909 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
910 boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer(
911 KeyguardUpdateMonitor.getCurrentUser());
912 boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser());
913 return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
914 }
915 }
Adrian Roos7e58a082018-03-09 16:40:56 +0100916
917 @Override
918 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
919 int bottom = insets.getDisplayCutout() != null
920 ? insets.getDisplayCutout().getSafeInsetBottom() : 0;
921 if (isPaddingRelative()) {
922 setPaddingRelative(getPaddingStart(), getPaddingTop(), getPaddingEnd(), bottom);
923 } else {
924 setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottom);
925 }
926 return insets;
927 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200928}