KeyguardSelectorView.java revision dcb3d84b82cc2448d04e73359a716581bfb657db
136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn/*
236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn * Copyright (C) 2012 The Android Open Source Project
336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn *
436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn * you may not use this file except in compliance with the License.
636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn * You may obtain a copy of the License at
736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn *
836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn *
1036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
1136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
1236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn * See the License for the specific language governing permissions and
1436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn * limitations under the License.
1536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn */
1636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornpackage com.android.internal.policy.impl.keyguard;
1736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
1836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.animation.ObjectAnimator;
1936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.app.ActivityManagerNative;
2036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.app.SearchManager;
2136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.content.ActivityNotFoundException;
2236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.content.ComponentName;
2336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.content.Context;
2436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.content.Intent;
2536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.os.RemoteException;
2636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.os.UserHandle;
2736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.provider.MediaStore;
2836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.util.AttributeSet;
2936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.util.Log;
3036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.util.Slog;
3136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.view.View;
3236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.widget.Button;
3336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport android.widget.LinearLayout;
3436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
3536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport com.android.internal.telephony.IccCardConstants;
3636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport com.android.internal.widget.LockPatternUtils;
3736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport com.android.internal.widget.multiwaveview.GlowPadView;
3836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
3936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornimport com.android.internal.R;
4036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
4136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackbornpublic class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
4236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private static final boolean DEBUG = KeyguardHostView.DEBUG;
4336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private static final String TAG = "SecuritySelectorView";
4436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private static final String ASSIST_ICON_METADATA_NAME =
4536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        "com.android.systemui.action_assist_icon";
4636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private KeyguardSecurityCallback mCallback;
4736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private GlowPadView mGlowPadView;
4836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private Button mEmergencyCallButton;
4936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private ObjectAnimator mAnim;
5036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private boolean mCameraDisabled;
5136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private boolean mSearchDisabled;
5236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    private LockPatternUtils mLockPatternUtils;
5336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
5436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn    OnTriggerListener mOnTriggerListener = new OnTriggerListener() {
5536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
5636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        public void onTrigger(View v, int target) {
5736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            final int resId = mGlowPadView.getResourceIdForTarget(target);
5836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            switch (resId) {
5936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                case com.android.internal.R.drawable.ic_action_assist_generic:
6036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    Intent assistIntent =
6136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
6236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                            .getAssistIntent(mContext, UserHandle.USER_CURRENT);
6336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    if (assistIntent != null) {
6436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                        launchActivity(assistIntent);
6536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    } else {
6636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                        Log.w(TAG, "Failed to get intent for assist activity");
6736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    }
6836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    mCallback.userActivity(0);
6936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    break;
7036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
7136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                case com.android.internal.R.drawable.ic_lockscreen_camera:
7236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA));
7336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    mCallback.userActivity(0);
7436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    break;
7536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
7636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                case com.android.internal.R.drawable.ic_lockscreen_unlock_phantom:
7736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                case com.android.internal.R.drawable.ic_lockscreen_unlock:
7836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                    mCallback.dismiss(false);
7936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn                break;
8036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            }
8136cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
8236cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
8336cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        public void onReleased(View v, int handle) {
8436cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            doTransition(mEmergencyCallButton, 1.0f);
8536cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
8636cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
8736cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        public void onGrabbed(View v, int handle) {
8836cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn            doTransition(mEmergencyCallButton, 0.0f);
8936cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn        }
9036cd41f8efa6f6a683d3353d309ff548295af9e9Dianne Hackborn
91        public void onGrabbedStateChange(View v, int handle) {
92
93        }
94
95        public void onFinishFinalAnimation() {
96
97        }
98
99    };
100
101    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
102
103        private boolean mEmergencyDialerDisableBecauseSimLocked;
104
105        @Override
106        public void onDevicePolicyManagerStateChanged() {
107            updateTargets();
108        }
109
110        @Override
111        public void onSimStateChanged(IccCardConstants.State simState) {
112            // Some carriers aren't capable of handling emergency calls while the SIM is locked
113            mEmergencyDialerDisableBecauseSimLocked = KeyguardUpdateMonitor.isSimLocked(simState)
114                    && !mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
115            updateTargets();
116        }
117
118        void onPhoneStateChanged(int phoneState) {
119            if (mEmergencyCallButton != null) {
120                mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
121                mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton,
122                        phoneState, !mEmergencyDialerDisableBecauseSimLocked);
123            }
124        };
125    };
126
127    public KeyguardSelectorView(Context context) {
128        this(context, null);
129    }
130
131    public KeyguardSelectorView(Context context, AttributeSet attrs) {
132        super(context, attrs);
133        mLockPatternUtils = new LockPatternUtils(getContext());
134    }
135
136    @Override
137    protected void onFinishInflate() {
138        super.onFinishInflate();
139        mGlowPadView = (GlowPadView) findViewById(R.id.glow_pad_view);
140        mGlowPadView.setOnTriggerListener(mOnTriggerListener);
141        mEmergencyCallButton = (Button) findViewById(R.id.emergency_call_button);
142        KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mInfoCallback);
143        updateTargets();
144    }
145
146    public boolean isTargetPresent(int resId) {
147        return mGlowPadView.getTargetPosition(resId) != -1;
148    }
149
150    private void updateTargets() {
151        boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager()
152                .getCameraDisabled(null);
153        final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(getContext());
154        boolean disabledBySimState = monitor.isSimLocked();
155        boolean cameraTargetPresent =
156            isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_camera);
157        boolean searchTargetPresent =
158            isTargetPresent(com.android.internal.R.drawable.ic_action_assist_generic);
159
160        if (disabledByAdmin) {
161            Log.v(TAG, "Camera disabled by Device Policy");
162        } else if (disabledBySimState) {
163            Log.v(TAG, "Camera disabled by Sim State");
164        }
165        boolean searchActionAvailable =
166                ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
167                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
168        mCameraDisabled = disabledByAdmin || disabledBySimState || !cameraTargetPresent;
169        mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent;
170        updateResources();
171    }
172
173    public void updateResources() {
174        // Update the search icon with drawable from the search .apk
175        if (!mSearchDisabled) {
176            Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
177                    .getAssistIntent(mContext, UserHandle.USER_CURRENT);
178            if (intent != null) {
179                // XXX Hack. We need to substitute the icon here but haven't formalized
180                // the public API. The "_google" metadata will be going away, so
181                // DON'T USE IT!
182                ComponentName component = intent.getComponent();
183                boolean replaced = mGlowPadView.replaceTargetDrawablesIfPresent(component,
184                        ASSIST_ICON_METADATA_NAME + "_google",
185                        com.android.internal.R.drawable.ic_action_assist_generic);
186
187                if (!replaced && !mGlowPadView.replaceTargetDrawablesIfPresent(component,
188                            ASSIST_ICON_METADATA_NAME,
189                            com.android.internal.R.drawable.ic_action_assist_generic)) {
190                        Slog.w(TAG, "Couldn't grab icon from package " + component);
191                }
192            }
193        }
194
195        mGlowPadView.setEnableTarget(com.android.internal.R.drawable
196                .ic_lockscreen_camera, !mCameraDisabled);
197        mGlowPadView.setEnableTarget(com.android.internal.R.drawable
198                .ic_action_assist_generic, !mSearchDisabled);
199    }
200
201    void doTransition(Object v, float to) {
202        if (mAnim != null) {
203            mAnim.cancel();
204        }
205        mAnim = ObjectAnimator.ofFloat(mEmergencyCallButton, "alpha", to);
206        mAnim.start();
207    }
208
209    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
210        mCallback = callback;
211    }
212
213    public void setLockPatternUtils(LockPatternUtils utils) {
214        mLockPatternUtils = utils;
215    }
216
217    /**
218     * Launches the said intent for the current foreground user.
219     * @param intent
220     */
221    private void launchActivity(Intent intent) {
222        intent.setFlags(
223                Intent.FLAG_ACTIVITY_NEW_TASK
224                | Intent.FLAG_ACTIVITY_SINGLE_TOP
225                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
226        try {
227            ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
228        } catch (RemoteException e) {
229            Log.w(TAG, "can't dismiss keyguard on launch");
230        }
231        try {
232            mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
233        } catch (ActivityNotFoundException e) {
234            Log.w(TAG, "Activity not found for intent + " + intent.getAction());
235        }
236    }
237
238    @Override
239    public void reset() {
240        mGlowPadView.reset(false);
241    }
242
243    @Override
244    public boolean needsInput() {
245        return false;
246    }
247
248    @Override
249    public void onPause() {
250        KeyguardUpdateMonitor.getInstance(getContext()).removeCallback(mInfoCallback);
251    }
252
253    @Override
254    public void onResume() {
255        KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mInfoCallback);
256    }
257
258    @Override
259    public KeyguardSecurityCallback getCallback() {
260        return mCallback;
261    }
262
263}
264