KeyguardBottomAreaView.java revision 2580a976ec93a01ed00fae51364ad872bc591d95
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.accessibility.AccessibilityManager; 34import android.widget.FrameLayout; 35import android.widget.ImageView; 36 37import com.android.internal.widget.LockPatternUtils; 38import com.android.keyguard.KeyguardUpdateMonitor; 39import com.android.keyguard.KeyguardUpdateMonitorCallback; 40import com.android.systemui.R; 41 42/** 43 * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status 44 * text. 45 */ 46public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener, 47 UnlockMethodCache.OnUnlockMethodChangedListener { 48 49 final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView"; 50 51 private static final Intent SECURE_CAMERA_INTENT = 52 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE) 53 .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 54 private static final Intent INSECURE_CAMERA_INTENT = 55 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 56 private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL); 57 58 private ImageView mCameraImageView; 59 private ImageView mPhoneImageView; 60 private ImageView mLockIcon; 61 private View mIndicationText; 62 63 private ActivityStarter mActivityStarter; 64 private UnlockMethodCache mUnlockMethodCache; 65 private LockPatternUtils mLockPatternUtils; 66 67 public KeyguardBottomAreaView(Context context) { 68 super(context); 69 } 70 71 public KeyguardBottomAreaView(Context context, AttributeSet attrs) { 72 super(context, attrs); 73 } 74 75 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) { 76 super(context, attrs, defStyleAttr); 77 } 78 79 public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr, 80 int defStyleRes) { 81 super(context, attrs, defStyleAttr, defStyleRes); 82 } 83 84 @Override 85 protected void onFinishInflate() { 86 super.onFinishInflate(); 87 mLockPatternUtils = new LockPatternUtils(mContext); 88 mCameraImageView = (ImageView) findViewById(R.id.camera_button); 89 mPhoneImageView = (ImageView) findViewById(R.id.phone_button); 90 mLockIcon = (ImageView) findViewById(R.id.lock_icon); 91 mIndicationText = findViewById(R.id.keyguard_indication_text); 92 watchForCameraPolicyChanges(); 93 watchForAccessibilityChanges(); 94 updateCameraVisibility(); 95 updatePhoneVisibility(); 96 mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); 97 mUnlockMethodCache.addListener(this); 98 updateTrust(); 99 } 100 101 public void setActivityStarter(ActivityStarter activityStarter) { 102 mActivityStarter = activityStarter; 103 } 104 105 private Intent getCameraIntent() { 106 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); 107 boolean currentUserHasTrust = updateMonitor.getUserHasTrust( 108 mLockPatternUtils.getCurrentUser()); 109 return mLockPatternUtils.isSecure() && !currentUserHasTrust 110 ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT; 111 } 112 113 private void updateCameraVisibility() { 114 ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(), 115 PackageManager.MATCH_DEFAULT_ONLY, 116 mLockPatternUtils.getCurrentUser()); 117 boolean visible = !isCameraDisabledByDpm() && resolved != null; 118 mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE); 119 } 120 121 private void updatePhoneVisibility() { 122 boolean visible = isPhoneVisible(); 123 mPhoneImageView.setVisibility(visible ? View.VISIBLE : View.GONE); 124 } 125 126 private boolean isPhoneVisible() { 127 PackageManager pm = mContext.getPackageManager(); 128 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) 129 && pm.resolveActivity(PHONE_INTENT, 0) != null; 130 } 131 132 private boolean isCameraDisabledByDpm() { 133 final DevicePolicyManager dpm = 134 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE); 135 if (dpm != null) { 136 try { 137 final int userId = ActivityManagerNative.getDefault().getCurrentUser().id; 138 final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId); 139 final boolean disabledBecauseKeyguardSecure = 140 (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0 141 && KeyguardTouchDelegate.getInstance(getContext()).isSecure(); 142 return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure; 143 } catch (RemoteException e) { 144 Log.e(TAG, "Can't get userId", e); 145 } 146 } 147 return false; 148 } 149 150 private void watchForCameraPolicyChanges() { 151 final IntentFilter filter = new IntentFilter(); 152 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 153 getContext().registerReceiverAsUser(mDevicePolicyReceiver, 154 UserHandle.ALL, filter, null, null); 155 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback); 156 } 157 158 private void watchForAccessibilityChanges() { 159 final AccessibilityManager am = 160 (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 161 162 // Set the initial state 163 enableAccessibility(am.isTouchExplorationEnabled()); 164 165 // Watch for changes 166 am.addTouchExplorationStateChangeListener( 167 new AccessibilityManager.TouchExplorationStateChangeListener() { 168 @Override 169 public void onTouchExplorationStateChanged(boolean enabled) { 170 enableAccessibility(enabled); 171 } 172 }); 173 } 174 175 private void enableAccessibility(boolean touchExplorationEnabled) { 176 mCameraImageView.setOnClickListener(touchExplorationEnabled ? this : null); 177 mCameraImageView.setClickable(touchExplorationEnabled); 178 mPhoneImageView.setOnClickListener(touchExplorationEnabled ? this : null); 179 mPhoneImageView.setClickable(touchExplorationEnabled); 180 } 181 182 @Override 183 public void onClick(View v) { 184 if (v == mCameraImageView) { 185 launchCamera(); 186 } else if (v == mPhoneImageView) { 187 launchPhone(); 188 } 189 } 190 191 public void launchCamera() { 192 Intent intent = getCameraIntent(); 193 if (intent == SECURE_CAMERA_INTENT) { 194 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 195 } else { 196 mActivityStarter.startActivity(intent); 197 } 198 } 199 200 public void launchPhone() { 201 mActivityStarter.startActivity(PHONE_INTENT); 202 } 203 204 205 @Override 206 protected void onVisibilityChanged(View changedView, int visibility) { 207 super.onVisibilityChanged(changedView, visibility); 208 if (changedView == this && visibility == VISIBLE) { 209 updateTrust(); 210 updateCameraVisibility(); 211 } 212 } 213 214 private void updateTrust() { 215 if (getVisibility() != VISIBLE) { 216 return; 217 } 218 int iconRes = mUnlockMethodCache.isMethodInsecure() 219 ? R.drawable.ic_lock_open_24dp 220 : R.drawable.ic_lock_24dp; 221 mLockIcon.setImageResource(iconRes); 222 } 223 224 public ImageView getPhoneImageView() { 225 return mPhoneImageView; 226 } 227 228 public ImageView getCameraImageView() { 229 return mCameraImageView; 230 } 231 232 public ImageView getLockIcon() { 233 return mLockIcon; 234 } 235 236 public View getIndicationView() { 237 return mIndicationText; 238 } 239 240 @Override 241 public boolean hasOverlappingRendering() { 242 return false; 243 } 244 245 @Override 246 public void onMethodSecureChanged(boolean methodSecure) { 247 updateTrust(); 248 updateCameraVisibility(); 249 } 250 251 private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { 252 public void onReceive(Context context, Intent intent) { 253 post(new Runnable() { 254 @Override 255 public void run() { 256 updateCameraVisibility(); 257 } 258 }); 259 } 260 }; 261 262 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = 263 new KeyguardUpdateMonitorCallback() { 264 @Override 265 public void onUserSwitchComplete(int userId) { 266 updateCameraVisibility(); 267 } 268 }; 269} 270