KeyguardBottomAreaView.java revision b6cdcbc66b4b862f83afde85b8e7109b6450b15e
1/* 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; 25import android.content.pm.PackageManager; 26import android.content.pm.ResolveInfo; 27import android.os.RemoteException; 28import android.os.UserHandle; 29import android.provider.MediaStore; 30import android.util.AttributeSet; 31import android.util.Log; 32import android.view.View; 33import android.view.ViewGroup; 34import android.view.accessibility.AccessibilityManager; 35import android.widget.FrameLayout; 36import android.widget.ImageView; 37 38import com.android.internal.widget.LockPatternUtils; 39import com.android.keyguard.KeyguardUpdateMonitor; 40import com.android.keyguard.KeyguardUpdateMonitorCallback; 41import com.android.systemui.R; 42import com.android.systemui.statusbar.policy.FlashlightController; 43import com.android.systemui.statusbar.KeyguardAffordanceView; 44import com.android.systemui.statusbar.policy.PreviewInflater; 45 46/** 47 * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status 48 * text. 49 */ 50public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener, 51 UnlockMethodCache.OnUnlockMethodChangedListener { 52 53 final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView"; 54 55 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); 60 private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL); 61 62 private KeyguardAffordanceView mCameraImageView; 63 private KeyguardAffordanceView mPhoneImageView; 64 private KeyguardAffordanceView mLockIcon; 65 private View mIndicationText; 66 private ViewGroup mPreviewContainer; 67 68 private View mPhonePreview; 69 private View mCameraPreview; 70 71 private ActivityStarter mActivityStarter; 72 private UnlockMethodCache mUnlockMethodCache; 73 private LockPatternUtils mLockPatternUtils; 74 private FlashlightController mFlashlightController; 75 76 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(); 96 mLockPatternUtils = new LockPatternUtils(mContext); 97 mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container); 98 mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button); 99 mPhoneImageView = (KeyguardAffordanceView) findViewById(R.id.phone_button); 100 mLockIcon = (KeyguardAffordanceView) findViewById(R.id.lock_icon); 101 mIndicationText = findViewById(R.id.keyguard_indication_text); 102 watchForCameraPolicyChanges(); 103 watchForAccessibilityChanges(); 104 updateCameraVisibility(); 105 updatePhoneVisibility(); 106 mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); 107 mUnlockMethodCache.addListener(this); 108 updateTrust(); 109 setClipChildren(false); 110 setClipToPadding(false); 111 inflatePreviews(); 112 } 113 114 public void setActivityStarter(ActivityStarter activityStarter) { 115 mActivityStarter = activityStarter; 116 } 117 118 public void setFlashlightController(FlashlightController flashlightController) { 119 mFlashlightController = flashlightController; 120 } 121 122 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 130 private void updateCameraVisibility() { 131 ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(), 132 PackageManager.MATCH_DEFAULT_ONLY, 133 mLockPatternUtils.getCurrentUser()); 134 boolean visible = !isCameraDisabledByDpm() && resolved != null; 135 mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE); 136 } 137 138 private void updatePhoneVisibility() { 139 boolean visible = isPhoneVisible(); 140 mPhoneImageView.setVisibility(visible ? View.VISIBLE : View.GONE); 141 } 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 149 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 167 private void watchForCameraPolicyChanges() { 168 final IntentFilter filter = new IntentFilter(); 169 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 170 getContext().registerReceiverAsUser(mDevicePolicyReceiver, 171 UserHandle.ALL, filter, null, null); 172 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback); 173 } 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) { 193 mCameraImageView.setOnClickListener(touchExplorationEnabled ? this : null); 194 mCameraImageView.setClickable(touchExplorationEnabled); 195 mPhoneImageView.setOnClickListener(touchExplorationEnabled ? this : null); 196 mPhoneImageView.setClickable(touchExplorationEnabled); 197 } 198 199 @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() { 209 mFlashlightController.killFlashlight(); 210 Intent intent = getCameraIntent(); 211 if (intent == SECURE_CAMERA_INTENT) { 212 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 213 } else { 214 mActivityStarter.startActivity(intent); 215 } 216 } 217 218 public void launchPhone() { 219 mActivityStarter.startActivity(PHONE_INTENT); 220 } 221 222 223 @Override 224 protected void onVisibilityChanged(View changedView, int visibility) { 225 super.onVisibilityChanged(changedView, visibility); 226 if (changedView == this && visibility == VISIBLE) { 227 updateTrust(); 228 updateCameraVisibility(); 229 } 230 } 231 232 private void updateTrust() { 233 if (getVisibility() != VISIBLE) { 234 return; 235 } 236 int iconRes = mUnlockMethodCache.isMethodInsecure() 237 ? R.drawable.ic_lock_open_24dp 238 : R.drawable.ic_lock_24dp; 239 mLockIcon.setImageResource(iconRes); 240 } 241 242 public KeyguardAffordanceView getPhoneView() { 243 return mPhoneImageView; 244 } 245 246 public KeyguardAffordanceView getCameraView() { 247 return mCameraImageView; 248 } 249 250 public View getPhonePreview() { 251 return mPhonePreview; 252 } 253 254 public View getCameraPreview() { 255 return mCameraPreview; 256 } 257 258 public KeyguardAffordanceView getLockIcon() { 259 return mLockIcon; 260 } 261 262 public View getIndicationView() { 263 return mIndicationText; 264 } 265 266 @Override 267 public boolean hasOverlappingRendering() { 268 return false; 269 } 270 271 @Override 272 public void onMethodSecureChanged(boolean methodSecure) { 273 updateTrust(); 274 updateCameraVisibility(); 275 } 276 277 private void inflatePreviews() { 278 PreviewInflater inflater = new PreviewInflater(mContext, new LockPatternUtils(mContext)); 279 mPhonePreview = inflater.inflatePreview(PHONE_INTENT); 280 mCameraPreview = inflater.inflatePreview(getCameraIntent()); 281 if (mPhonePreview != null) { 282 mPreviewContainer.addView(mPhonePreview); 283 mPhonePreview.setVisibility(View.INVISIBLE); 284 } 285 if (mCameraPreview != null) { 286 mPreviewContainer.addView(mCameraPreview); 287 mCameraPreview.setVisibility(View.INVISIBLE); 288 } 289 } 290 291 private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { 292 public void onReceive(Context context, Intent intent) { 293 post(new Runnable() { 294 @Override 295 public void run() { 296 updateCameraVisibility(); 297 } 298 }); 299 } 300 }; 301 302 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = 303 new KeyguardUpdateMonitorCallback() { 304 @Override 305 public void onUserSwitchComplete(int userId) { 306 updateCameraVisibility(); 307 } 308 }; 309} 310