1/*
2 * Copyright (C) 2012 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 */
16package com.android.internal.policy.impl.keyguard;
17
18import android.animation.ObjectAnimator;
19import android.app.SearchManager;
20import android.app.admin.DevicePolicyManager;
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.graphics.drawable.Drawable;
25import android.os.UserHandle;
26import android.provider.Settings;
27import android.util.AttributeSet;
28import android.util.Log;
29import android.util.Slog;
30import android.view.View;
31import android.widget.LinearLayout;
32
33import com.android.internal.telephony.IccCardConstants.State;
34import com.android.internal.widget.LockPatternUtils;
35import com.android.internal.widget.multiwaveview.GlowPadView;
36import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
37import com.android.internal.R;
38
39public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
40    private static final boolean DEBUG = KeyguardHostView.DEBUG;
41    private static final String TAG = "SecuritySelectorView";
42    private static final String ASSIST_ICON_METADATA_NAME =
43        "com.android.systemui.action_assist_icon";
44
45    private KeyguardSecurityCallback mCallback;
46    private GlowPadView mGlowPadView;
47    private ObjectAnimator mAnim;
48    private View mFadeView;
49    private boolean mIsBouncing;
50    private boolean mCameraDisabled;
51    private boolean mSearchDisabled;
52    private LockPatternUtils mLockPatternUtils;
53    private SecurityMessageDisplay mSecurityMessageDisplay;
54    private Drawable mBouncerFrame;
55
56    OnTriggerListener mOnTriggerListener = new OnTriggerListener() {
57
58        public void onTrigger(View v, int target) {
59            final int resId = mGlowPadView.getResourceIdForTarget(target);
60            switch (resId) {
61                case com.android.internal.R.drawable.ic_action_assist_generic:
62                    Intent assistIntent =
63                            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
64                            .getAssistIntent(mContext, UserHandle.USER_CURRENT);
65                    if (assistIntent != null) {
66                        mActivityLauncher.launchActivity(assistIntent, false, true, null, null);
67                    } else {
68                        Log.w(TAG, "Failed to get intent for assist activity");
69                    }
70                    mCallback.userActivity(0);
71                    break;
72
73                case com.android.internal.R.drawable.ic_lockscreen_camera:
74                    mActivityLauncher.launchCamera(null, null);
75                    mCallback.userActivity(0);
76                    break;
77
78                case com.android.internal.R.drawable.ic_lockscreen_unlock_phantom:
79                case com.android.internal.R.drawable.ic_lockscreen_unlock:
80                    mCallback.userActivity(0);
81                    mCallback.dismiss(false);
82                break;
83            }
84        }
85
86        public void onReleased(View v, int handle) {
87            if (!mIsBouncing) {
88                doTransition(mFadeView, 1.0f);
89            }
90        }
91
92        public void onGrabbed(View v, int handle) {
93            mCallback.userActivity(0);
94            doTransition(mFadeView, 0.0f);
95        }
96
97        public void onGrabbedStateChange(View v, int handle) {
98
99        }
100
101        public void onFinishFinalAnimation() {
102
103        }
104
105    };
106
107    KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
108
109        @Override
110        public void onDevicePolicyManagerStateChanged() {
111            updateTargets();
112        }
113
114        @Override
115        public void onSimStateChanged(State simState) {
116            updateTargets();
117        }
118    };
119
120    private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
121
122        @Override
123        KeyguardSecurityCallback getCallback() {
124            return mCallback;
125        }
126
127        @Override
128        LockPatternUtils getLockPatternUtils() {
129            return mLockPatternUtils;
130        }
131
132        @Override
133        Context getContext() {
134            return mContext;
135        }};
136
137    public KeyguardSelectorView(Context context) {
138        this(context, null);
139    }
140
141    public KeyguardSelectorView(Context context, AttributeSet attrs) {
142        super(context, attrs);
143        mLockPatternUtils = new LockPatternUtils(getContext());
144    }
145
146    @Override
147    protected void onFinishInflate() {
148        super.onFinishInflate();
149        mGlowPadView = (GlowPadView) findViewById(R.id.glow_pad_view);
150        mGlowPadView.setOnTriggerListener(mOnTriggerListener);
151        updateTargets();
152
153        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
154        View bouncerFrameView = findViewById(R.id.keyguard_selector_view_frame);
155        mBouncerFrame = bouncerFrameView.getBackground();
156    }
157
158    public void setCarrierArea(View carrierArea) {
159        mFadeView = carrierArea;
160    }
161
162    public boolean isTargetPresent(int resId) {
163        return mGlowPadView.getTargetPosition(resId) != -1;
164    }
165
166    @Override
167    public void showUsabilityHint() {
168        mGlowPadView.ping();
169    }
170
171    private void updateTargets() {
172        int currentUserHandle = mLockPatternUtils.getCurrentUser();
173        DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
174        int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUserHandle);
175        boolean secureCameraDisabled = mLockPatternUtils.isSecure()
176                && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
177        boolean cameraDisabledByAdmin = dpm.getCameraDisabled(null, currentUserHandle)
178                || secureCameraDisabled;
179        final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(getContext());
180        boolean disabledBySimState = monitor.isSimLocked();
181        boolean cameraTargetPresent =
182            isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_camera);
183        boolean searchTargetPresent =
184            isTargetPresent(com.android.internal.R.drawable.ic_action_assist_generic);
185
186        if (cameraDisabledByAdmin) {
187            Log.v(TAG, "Camera disabled by Device Policy");
188        } else if (disabledBySimState) {
189            Log.v(TAG, "Camera disabled by Sim State");
190        }
191        boolean currentUserSetup = 0 != Settings.Secure.getIntForUser(
192                mContext.getContentResolver(),
193                Settings.Secure.USER_SETUP_COMPLETE,
194                0 /*default */,
195                currentUserHandle);
196        boolean searchActionAvailable =
197                ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
198                .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
199        mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent
200                || !currentUserSetup;
201        mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent
202                || !currentUserSetup;
203        updateResources();
204    }
205
206    public void updateResources() {
207        // Update the search icon with drawable from the search .apk
208        if (!mSearchDisabled) {
209            Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
210                    .getAssistIntent(mContext, UserHandle.USER_CURRENT);
211            if (intent != null) {
212                // XXX Hack. We need to substitute the icon here but haven't formalized
213                // the public API. The "_google" metadata will be going away, so
214                // DON'T USE IT!
215                ComponentName component = intent.getComponent();
216                boolean replaced = mGlowPadView.replaceTargetDrawablesIfPresent(component,
217                        ASSIST_ICON_METADATA_NAME + "_google",
218                        com.android.internal.R.drawable.ic_action_assist_generic);
219
220                if (!replaced && !mGlowPadView.replaceTargetDrawablesIfPresent(component,
221                            ASSIST_ICON_METADATA_NAME,
222                            com.android.internal.R.drawable.ic_action_assist_generic)) {
223                        Slog.w(TAG, "Couldn't grab icon from package " + component);
224                }
225            }
226        }
227
228        mGlowPadView.setEnableTarget(com.android.internal.R.drawable
229                .ic_lockscreen_camera, !mCameraDisabled);
230        mGlowPadView.setEnableTarget(com.android.internal.R.drawable
231                .ic_action_assist_generic, !mSearchDisabled);
232    }
233
234    void doTransition(View view, float to) {
235        if (mAnim != null) {
236            mAnim.cancel();
237        }
238        mAnim = ObjectAnimator.ofFloat(view, "alpha", to);
239        mAnim.start();
240    }
241
242    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
243        mCallback = callback;
244    }
245
246    public void setLockPatternUtils(LockPatternUtils utils) {
247        mLockPatternUtils = utils;
248    }
249
250    @Override
251    public void reset() {
252        mGlowPadView.reset(false);
253    }
254
255    @Override
256    public boolean needsInput() {
257        return false;
258    }
259
260    @Override
261    public void onPause() {
262        KeyguardUpdateMonitor.getInstance(getContext()).removeCallback(mInfoCallback);
263    }
264
265    @Override
266    public void onResume(int reason) {
267        KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mInfoCallback);
268    }
269
270    @Override
271    public KeyguardSecurityCallback getCallback() {
272        return mCallback;
273    }
274
275    @Override
276    public void showBouncer(int duration) {
277        mIsBouncing = true;
278        KeyguardSecurityViewHelper.
279                showBouncer(mSecurityMessageDisplay, mFadeView, mBouncerFrame, duration);
280    }
281
282    @Override
283    public void hideBouncer(int duration) {
284        mIsBouncing = false;
285        KeyguardSecurityViewHelper.
286                hideBouncer(mSecurityMessageDisplay, mFadeView, mBouncerFrame, duration);
287    }
288}
289