blob: 82e59c0249ad7ccf0da08f08bbb386c1609cf34d [file] [log] [blame]
Jorim Jaggia6310292014-04-16 14:11:52 +02001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar.phone;
18
19import android.app.ActivityManagerNative;
20import android.app.admin.DevicePolicyManager;
21import android.content.BroadcastReceiver;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
Jorim Jaggi97b63c42014-05-02 23:03:34 +020025import android.content.pm.PackageManager;
Adrian Roosa06905b2014-05-28 12:13:48 +020026import android.content.pm.ResolveInfo;
Jorim Jaggia6310292014-04-16 14:11:52 +020027import android.os.RemoteException;
28import android.os.UserHandle;
29import android.provider.MediaStore;
30import android.util.AttributeSet;
31import android.util.Log;
Jorim Jaggia6310292014-04-16 14:11:52 +020032import android.view.View;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020033import android.view.ViewGroup;
Jorim Jaggia6310292014-04-16 14:11:52 +020034import android.view.accessibility.AccessibilityManager;
Jorim Jaggia6310292014-04-16 14:11:52 +020035import android.widget.FrameLayout;
Adrian Roos2fe592d2014-05-17 03:11:59 +020036import android.widget.ImageView;
Adrian Roosa06905b2014-05-28 12:13:48 +020037
38import com.android.internal.widget.LockPatternUtils;
39import com.android.keyguard.KeyguardUpdateMonitor;
40import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jorim Jaggia6310292014-04-16 14:11:52 +020041import com.android.systemui.R;
Adrian Roos1e1d6ac2014-07-22 17:18:55 +020042import com.android.systemui.statusbar.policy.FlashlightController;
Selim Cinekbaa23272014-07-08 18:01:07 +020043import com.android.systemui.statusbar.KeyguardAffordanceView;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020044import com.android.systemui.statusbar.policy.PreviewInflater;
Jorim Jaggia6310292014-04-16 14:11:52 +020045
46/**
47 * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
48 * text.
49 */
Selim Cinek4c6969a2014-05-26 19:22:17 +020050public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
Jorim Jaggiecc798e2014-05-26 18:14:37 +020051 UnlockMethodCache.OnUnlockMethodChangedListener {
Jorim Jaggia6310292014-04-16 14:11:52 +020052
53 final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
54
Adrian Roosa06905b2014-05-28 12:13:48 +020055 private static final Intent SECURE_CAMERA_INTENT =
56 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
57 .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
58 private static final Intent INSECURE_CAMERA_INTENT =
59 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
Jorim Jaggi97b63c42014-05-02 23:03:34 +020060 private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
61
Selim Cinekbaa23272014-07-08 18:01:07 +020062 private KeyguardAffordanceView mCameraImageView;
63 private KeyguardAffordanceView mPhoneImageView;
64 private KeyguardAffordanceView mLockIcon;
Selim Cinekf99d0002014-06-13 07:36:01 +020065 private View mIndicationText;
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020066 private ViewGroup mPreviewContainer;
67
68 private View mPhonePreview;
69 private View mCameraPreview;
Jorim Jaggi97b63c42014-05-02 23:03:34 +020070
Jorim Jaggi97b63c42014-05-02 23:03:34 +020071 private ActivityStarter mActivityStarter;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020072 private UnlockMethodCache mUnlockMethodCache;
Adrian Roosa06905b2014-05-28 12:13:48 +020073 private LockPatternUtils mLockPatternUtils;
Adrian Roos1e1d6ac2014-07-22 17:18:55 +020074 private FlashlightController mFlashlightController;
Adrian Roos2fe592d2014-05-17 03:11:59 +020075
Jorim Jaggia6310292014-04-16 14:11:52 +020076 public KeyguardBottomAreaView(Context context) {
77 super(context);
78 }
79
80 public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
81 super(context, attrs);
82 }
83
84 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
85 super(context, attrs, defStyleAttr);
86 }
87
88 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
89 int defStyleRes) {
90 super(context, attrs, defStyleAttr, defStyleRes);
91 }
92
93 @Override
94 protected void onFinishInflate() {
95 super.onFinishInflate();
Adrian Roosa06905b2014-05-28 12:13:48 +020096 mLockPatternUtils = new LockPatternUtils(mContext);
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +020097 mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container);
Selim Cinekbaa23272014-07-08 18:01:07 +020098 mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
99 mPhoneImageView = (KeyguardAffordanceView) findViewById(R.id.phone_button);
100 mLockIcon = (KeyguardAffordanceView) findViewById(R.id.lock_icon);
Selim Cinekf99d0002014-06-13 07:36:01 +0200101 mIndicationText = findViewById(R.id.keyguard_indication_text);
Adrian Roosa06905b2014-05-28 12:13:48 +0200102 watchForCameraPolicyChanges();
Jorim Jaggia6310292014-04-16 14:11:52 +0200103 watchForAccessibilityChanges();
104 updateCameraVisibility();
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200105 updatePhoneVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200106 mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
107 mUnlockMethodCache.addListener(this);
Adrian Roos2fe592d2014-05-17 03:11:59 +0200108 updateTrust();
Selim Cinekbaa23272014-07-08 18:01:07 +0200109 setClipChildren(false);
110 setClipToPadding(false);
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200111 inflatePreviews();
Jorim Jaggia6310292014-04-16 14:11:52 +0200112 }
113
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200114 public void setActivityStarter(ActivityStarter activityStarter) {
115 mActivityStarter = activityStarter;
116 }
117
Adrian Roos1e1d6ac2014-07-22 17:18:55 +0200118 public void setFlashlightController(FlashlightController flashlightController) {
119 mFlashlightController = flashlightController;
120 }
121
Adrian Roosa06905b2014-05-28 12:13:48 +0200122 private Intent getCameraIntent() {
123 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
124 boolean currentUserHasTrust = updateMonitor.getUserHasTrust(
125 mLockPatternUtils.getCurrentUser());
126 return mLockPatternUtils.isSecure() && !currentUserHasTrust
127 ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
128 }
129
Jorim Jaggia6310292014-04-16 14:11:52 +0200130 private void updateCameraVisibility() {
Adrian Roosa06905b2014-05-28 12:13:48 +0200131 ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
132 PackageManager.MATCH_DEFAULT_ONLY,
133 mLockPatternUtils.getCurrentUser());
134 boolean visible = !isCameraDisabledByDpm() && resolved != null;
Selim Cinek4c6969a2014-05-26 19:22:17 +0200135 mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
Jorim Jaggia6310292014-04-16 14:11:52 +0200136 }
137
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200138 private void updatePhoneVisibility() {
139 boolean visible = isPhoneVisible();
Selim Cinek4c6969a2014-05-26 19:22:17 +0200140 mPhoneImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200141 }
142
143 private boolean isPhoneVisible() {
144 PackageManager pm = mContext.getPackageManager();
145 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
146 && pm.resolveActivity(PHONE_INTENT, 0) != null;
147 }
148
Jorim Jaggia6310292014-04-16 14:11:52 +0200149 private boolean isCameraDisabledByDpm() {
150 final DevicePolicyManager dpm =
151 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
152 if (dpm != null) {
153 try {
154 final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
155 final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
156 final boolean disabledBecauseKeyguardSecure =
157 (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
158 && KeyguardTouchDelegate.getInstance(getContext()).isSecure();
159 return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
160 } catch (RemoteException e) {
161 Log.e(TAG, "Can't get userId", e);
162 }
163 }
164 return false;
165 }
166
Adrian Roosa06905b2014-05-28 12:13:48 +0200167 private void watchForCameraPolicyChanges() {
Jorim Jaggia6310292014-04-16 14:11:52 +0200168 final IntentFilter filter = new IntentFilter();
169 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
Adrian Roosa06905b2014-05-28 12:13:48 +0200170 getContext().registerReceiverAsUser(mDevicePolicyReceiver,
171 UserHandle.ALL, filter, null, null);
172 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
Jorim Jaggia6310292014-04-16 14:11:52 +0200173 }
174
175 private void watchForAccessibilityChanges() {
176 final AccessibilityManager am =
177 (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
178
179 // Set the initial state
180 enableAccessibility(am.isTouchExplorationEnabled());
181
182 // Watch for changes
183 am.addTouchExplorationStateChangeListener(
184 new AccessibilityManager.TouchExplorationStateChangeListener() {
185 @Override
186 public void onTouchExplorationStateChanged(boolean enabled) {
187 enableAccessibility(enabled);
188 }
189 });
190 }
191
192 private void enableAccessibility(boolean touchExplorationEnabled) {
Selim Cinek4c6969a2014-05-26 19:22:17 +0200193 mCameraImageView.setOnClickListener(touchExplorationEnabled ? this : null);
194 mCameraImageView.setClickable(touchExplorationEnabled);
195 mPhoneImageView.setOnClickListener(touchExplorationEnabled ? this : null);
196 mPhoneImageView.setClickable(touchExplorationEnabled);
Jorim Jaggia6310292014-04-16 14:11:52 +0200197 }
198
Selim Cinek4c6969a2014-05-26 19:22:17 +0200199 @Override
200 public void onClick(View v) {
201 if (v == mCameraImageView) {
202 launchCamera();
203 } else if (v == mPhoneImageView) {
204 launchPhone();
205 }
206 }
207
208 public void launchCamera() {
Adrian Roos1e1d6ac2014-07-22 17:18:55 +0200209 mFlashlightController.killFlashlight();
Adrian Roosa06905b2014-05-28 12:13:48 +0200210 Intent intent = getCameraIntent();
211 if (intent == SECURE_CAMERA_INTENT) {
212 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
213 } else {
214 mActivityStarter.startActivity(intent);
215 }
Jorim Jaggia6310292014-04-16 14:11:52 +0200216 }
217
Selim Cinek4c6969a2014-05-26 19:22:17 +0200218 public void launchPhone() {
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200219 mActivityStarter.startActivity(PHONE_INTENT);
220 }
221
Adrian Roos2fe592d2014-05-17 03:11:59 +0200222
223 @Override
224 protected void onVisibilityChanged(View changedView, int visibility) {
225 super.onVisibilityChanged(changedView, visibility);
226 if (changedView == this && visibility == VISIBLE) {
227 updateTrust();
Adrian Roosa06905b2014-05-28 12:13:48 +0200228 updateCameraVisibility();
Adrian Roos2fe592d2014-05-17 03:11:59 +0200229 }
230 }
231
232 private void updateTrust() {
233 if (getVisibility() != VISIBLE) {
234 return;
235 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200236 int iconRes = mUnlockMethodCache.isMethodInsecure()
237 ? R.drawable.ic_lock_open_24dp
238 : R.drawable.ic_lock_24dp;
Adrian Roos2fe592d2014-05-17 03:11:59 +0200239 mLockIcon.setImageResource(iconRes);
Adrian Roos7861c662014-07-25 15:37:28 +0200240 boolean trustManaged = mUnlockMethodCache.isTrustManaged();
241 mLockIcon.setBackgroundResource(trustManaged ? R.drawable.trust_circle : 0);
Adrian Roos2fe592d2014-05-17 03:11:59 +0200242 }
243
Selim Cinekbaa23272014-07-08 18:01:07 +0200244 public KeyguardAffordanceView getPhoneView() {
Selim Cinek4c6969a2014-05-26 19:22:17 +0200245 return mPhoneImageView;
246 }
247
Selim Cinekbaa23272014-07-08 18:01:07 +0200248 public KeyguardAffordanceView getCameraView() {
Selim Cinek4c6969a2014-05-26 19:22:17 +0200249 return mCameraImageView;
250 }
251
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200252 public View getPhonePreview() {
253 return mPhonePreview;
254 }
255
256 public View getCameraPreview() {
257 return mCameraPreview;
258 }
259
Selim Cinekbaa23272014-07-08 18:01:07 +0200260 public KeyguardAffordanceView getLockIcon() {
Selim Cinek4c6969a2014-05-26 19:22:17 +0200261 return mLockIcon;
262 }
263
Selim Cinekf99d0002014-06-13 07:36:01 +0200264 public View getIndicationView() {
265 return mIndicationText;
266 }
267
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200268 @Override
Jorim Jaggi2580a9762014-06-25 03:08:25 +0200269 public boolean hasOverlappingRendering() {
270 return false;
271 }
272
273 @Override
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200274 public void onMethodSecureChanged(boolean methodSecure) {
275 updateTrust();
Adrian Roosa06905b2014-05-28 12:13:48 +0200276 updateCameraVisibility();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200277 }
Adrian Roosa06905b2014-05-28 12:13:48 +0200278
Jorim Jaggib6cdcbc2014-07-25 21:58:29 +0200279 private void inflatePreviews() {
280 PreviewInflater inflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
281 mPhonePreview = inflater.inflatePreview(PHONE_INTENT);
282 mCameraPreview = inflater.inflatePreview(getCameraIntent());
283 if (mPhonePreview != null) {
284 mPreviewContainer.addView(mPhonePreview);
285 mPhonePreview.setVisibility(View.INVISIBLE);
286 }
287 if (mCameraPreview != null) {
288 mPreviewContainer.addView(mCameraPreview);
289 mCameraPreview.setVisibility(View.INVISIBLE);
290 }
291 }
292
Adrian Roosa06905b2014-05-28 12:13:48 +0200293 private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
294 public void onReceive(Context context, Intent intent) {
295 post(new Runnable() {
296 @Override
297 public void run() {
298 updateCameraVisibility();
299 }
300 });
301 }
302 };
303
304 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
305 new KeyguardUpdateMonitorCallback() {
306 @Override
307 public void onUserSwitchComplete(int userId) {
308 updateCameraVisibility();
309 }
310 };
Jorim Jaggia6310292014-04-16 14:11:52 +0200311}