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