KeyguardHostView.java revision dfb57cdcfc6a1fd48395c13af98ecc2722fd5254
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2012 The Android Open Source Project
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * you may not use this file except in compliance with the License.
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * You may obtain a copy of the License at
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch * Unless required by applicable law or agreed to in writing, software
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See the License for the specific language governing permissions and
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * limitations under the License.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)package com.android.internal.policy.impl.keyguard;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.app.Activity;
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import android.app.ActivityManager;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.app.ActivityOptions;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.app.AlertDialog;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.app.SearchManager;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.app.admin.DevicePolicyManager;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.appwidget.AppWidgetHost;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.appwidget.AppWidgetHostView;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.appwidget.AppWidgetManager;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.appwidget.AppWidgetProviderInfo;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.ComponentName;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.Context;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.Intent;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.IntentSender;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.pm.PackageManager.NameNotFoundException;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.pm.UserInfo;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.res.Resources;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.graphics.Canvas;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.graphics.Rect;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.media.RemoteControlClient;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Looper;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Parcel;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Parcelable;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.os.SystemClock;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.os.UserHandle;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.os.UserManager;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.provider.Settings;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.util.AttributeSet;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.util.Log;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.util.Slog;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.view.KeyEvent;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.view.LayoutInflater;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.MotionEvent;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.View;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.WindowManager;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.animation.AnimationUtils;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.widget.RemoteViews.OnClickHandler;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import com.android.internal.R;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityMode;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import com.android.internal.policy.impl.keyguard.KeyguardUpdateMonitor.DisplayClientState;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import com.android.internal.widget.LockPatternUtils;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import java.io.File;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import java.util.List;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public class KeyguardHostView extends KeyguardViewBase {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static final String TAG = "KeyguardHostView";
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Transport control states.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static final int TRANSPORT_GONE = 0;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static final int TRANSPORT_INVISIBLE = 1;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static final int TRANSPORT_VISIBLE = 2;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private int mTransportState = TRANSPORT_GONE;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Use this to debug all of keyguard
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public static boolean DEBUG = KeyguardViewMediator.DEBUG;
76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    public static boolean DEBUGXPORT = true; // debug music transport control
77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Found in KeyguardAppWidgetPickActivity.java
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static final int APPWIDGET_HOST_ID = 0x4B455947;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private final int MAX_WIDGETS = 5;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private AppWidgetHost mAppWidgetHost;
84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    private AppWidgetManager mAppWidgetManager;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private KeyguardWidgetPager mAppWidgetContainer;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private KeyguardSecurityViewFlipper mSecurityViewContainer;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private KeyguardSelectorView mKeyguardSelectorView;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private KeyguardTransportControlView mTransportControl;
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    private boolean mIsVerifyUnlockOnly;
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private int mAppWidgetToShow;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private boolean mCheckAppWidgetConsistencyOnBootCompleted = false;
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    private boolean mCleanupAppWidgetsOnBootCompleted = false;
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protected OnDismissAction mDismissAction;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protected int mFailedAttempts;
1002385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    private LockPatternUtils mLockPatternUtils;
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    private KeyguardSecurityModel mSecurityModel;
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    private KeyguardViewStateManager mViewStateManager;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    private Rect mTempRect = new Rect();
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private int mDisabledFeatures;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private boolean mCameraDisabled;
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private boolean mSafeModeEnabled;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private boolean mUserSetupCompleted;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // User for whom this host view was created.  Final because we should never change the
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // id without reconstructing an instance of KeyguardHostView. See note below...
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private final int mUserId;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private KeyguardMultiUserSelectorView mKeyguardMultiUserSelectorView;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protected int mClientGeneration;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /*package*/ interface UserSwitcherCallback {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        void hideSecurityView(int duration);
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        void showSecurityView();
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        void showUnlockHint();
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        void userActivity();
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /*package*/ interface OnDismissAction {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        /* returns true if the dismiss should be deferred */
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        boolean onDismiss();
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public KeyguardHostView(Context context) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        this(context, null);
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    public KeyguardHostView(Context context, AttributeSet attrs) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        super(context, attrs);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (DEBUG) Log.e(TAG, "KeyguardHostView()");
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mLockPatternUtils = new LockPatternUtils(context);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Note: This depends on KeyguardHostView getting reconstructed every time the
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // user switches, since mUserId will be used for the entire session.
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Once created, keyguard should *never* re-use this instance with another user.
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // In other words, mUserId should never change - hence it's marked final.
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mUserId = mLockPatternUtils.getCurrentUser();
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DevicePolicyManager dpm =
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (dpm != null) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mDisabledFeatures = getDisabledFeatures(dpm);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mCameraDisabled = dpm.getCameraDisabled(null);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mSafeModeEnabled = LockPatternUtils.isSafeModeEnabled();
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // These need to be created with the user context...
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Context userContext = null;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        try {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            final String packageName = "system";
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            userContext = mContext.createPackageContextAsUser(packageName, 0,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    new UserHandle(mUserId));
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } catch (NameNotFoundException e) {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            e.printStackTrace();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // This should never happen, but it's better to have no widgets than to crash.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            userContext = context;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mAppWidgetHost = new AppWidgetHost(userContext, APPWIDGET_HOST_ID, mOnClickHandler,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                Looper.myLooper());
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cleanupAppWidgetIds();
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mAppWidgetManager = AppWidgetManager.getInstance(userContext);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mSecurityModel = new KeyguardSecurityModel(context);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mViewStateManager = new KeyguardViewStateManager(this);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mUserSetupCompleted = Settings.Secure.getIntForUser(mContext.getContentResolver(),
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        // Ensure we have the current state *before* we call showAppropriateWidgetPage()
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        getInitialTransportState();
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mSafeModeEnabled) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            Log.v(TAG, "Keyguard widgets disabled by safe mode");
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0) {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            Log.v(TAG, "Keyguard widgets disabled by DPM");
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0) {
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            Log.v(TAG, "Keyguard secure camera disabled by DPM");
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void getInitialTransportState() {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DisplayClientState dcs = KeyguardUpdateMonitor.getInstance(mContext)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                .getCachedDisplayClientState();
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mTransportState = (dcs.clearing ? TRANSPORT_GONE :
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            (isMusicPlaying(dcs.playbackState) ? TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (DEBUG) Log.v(TAG, "Initial transport state: "
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                + mTransportState + ", pbstate=" + dcs.playbackState);
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void cleanupAppWidgetIds() {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Since this method may delete a widget (which we can't do until boot completed) we
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // may have to defer it until after boot complete.
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mCleanupAppWidgetsOnBootCompleted = true;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!mSafeModeEnabled && !widgetsDisabledByDpm()) {
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // Clean up appWidgetIds that are bound to lockscreen, but not actually used
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // This is only to clean up after another bug: we used to not call
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // deleteAppWidgetId when a user manually deleted a widget in keyguard. This code
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // shouldn't have to run more than once per user. AppWidgetProviders rely on callbacks
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // that are triggered by deleteAppWidgetId, which is why we're doing this
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            int[] appWidgetIdsInKeyguardSettings = mLockPatternUtils.getAppWidgets();
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            int[] appWidgetIdsBoundToHost = mAppWidgetHost.getAppWidgetIds();
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            for (int i = 0; i < appWidgetIdsBoundToHost.length; i++) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                int appWidgetId = appWidgetIdsBoundToHost[i];
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (!contains(appWidgetIdsInKeyguardSettings, appWidgetId)) {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    Log.d(TAG, "Found a appWidgetId that's not being used by keyguard, deleting id "
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            + appWidgetId);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    mAppWidgetHost.deleteAppWidgetId(appWidgetId);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static boolean contains(int[] array, int target) {
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (int value : array) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (value == target) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return true;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new KeyguardUpdateMonitorCallback() {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void onBootCompleted() {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (mCheckAppWidgetConsistencyOnBootCompleted) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                checkAppWidgetConsistency();
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                mSwitchPageRunnable.run();
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                mCheckAppWidgetConsistencyOnBootCompleted = false;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (mCleanupAppWidgetsOnBootCompleted) {
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                cleanupAppWidgetIds();
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                mCleanupAppWidgetsOnBootCompleted = false;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void onUserSwitchComplete(int userId) {
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (mKeyguardMultiUserSelectorView != null) {
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                mKeyguardMultiUserSelectorView.finalizeActiveUserView(true);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        void onMusicClientIdChanged(
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                int clientGeneration, boolean clearing, android.app.PendingIntent intent) {
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // Set transport state to invisible until we know music is playing (below)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (DEBUGXPORT && (mClientGeneration != clientGeneration || clearing)) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                Log.v(TAG, (clearing ? "hide" : "show") + " transport, gen:" + clientGeneration);
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mClientGeneration = clientGeneration;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            final int newState = (clearing ? TRANSPORT_GONE
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    : (mTransportState == TRANSPORT_VISIBLE ?
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE));
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (newState != mTransportState) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                mTransportState = newState;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (DEBUGXPORT) Log.v(TAG, "update widget: transport state changed");
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                KeyguardHostView.this.post(mSwitchPageRunnable);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void onMusicPlaybackStateChanged(int playbackState, long eventTime) {
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (DEBUGXPORT) Log.v(TAG, "music state changed: " + playbackState);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (mTransportState != TRANSPORT_GONE) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                final int newState = (isMusicPlaying(playbackState) ?
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        TRANSPORT_VISIBLE : TRANSPORT_INVISIBLE);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (newState != mTransportState) {
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    mTransportState = newState;
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    if (DEBUGXPORT) Log.v(TAG, "update widget: play state changed");
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    KeyguardHostView.this.post(mSwitchPageRunnable);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static final boolean isMusicPlaying(int playbackState) {
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // This should agree with the list in AudioService.isPlaystateActive()
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        switch (playbackState) {
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case RemoteControlClient.PLAYSTATE_PLAYING:
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case RemoteControlClient.PLAYSTATE_BUFFERING:
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case RemoteControlClient.PLAYSTATE_REWINDING:
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return true;
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            default:
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return false;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private SlidingChallengeLayout mSlidingChallengeLayout;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @Override
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public boolean onTouchEvent(MotionEvent ev) {
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        boolean result = super.onTouchEvent(ev);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mTempRect.set(0, 0, 0, 0);
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        offsetRectIntoDescendantCoords(mSecurityViewContainer, mTempRect);
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ev.offsetLocation(mTempRect.left, mTempRect.top);
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        result = mSecurityViewContainer.dispatchTouchEvent(ev) || result;
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ev.offsetLocation(-mTempRect.left, -mTempRect.top);
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return result;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @Override
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protected void dispatchDraw(Canvas canvas) {
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        super.dispatchDraw(canvas);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mViewMediatorCallback != null) {
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mViewMediatorCallback.keyguardDoneDrawing();
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private int getWidgetPosition(int id) {
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final KeyguardWidgetPager appWidgetContainer = mAppWidgetContainer;
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final int children = appWidgetContainer.getChildCount();
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (int i = 0; i < children; i++) {
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            final View content = appWidgetContainer.getWidgetPageAt(i).getContent();
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (content != null && content.getId() == id) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return i;
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            } else if (content == null) {
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                // Attempt to track down bug #8886916
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                Log.w(TAG, "*** Null content at " + "i=" + i + ",id=" + id + ",N=" + children);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return -1;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @Override
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protected void onFinishInflate() {
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Grab instances of and make any necessary changes to the main layouts. Create
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // view state manager and wire up necessary listeners / callbacks.
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        View deleteDropTarget = findViewById(R.id.keyguard_widget_pager_delete_target);
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mAppWidgetContainer.setVisibility(VISIBLE);
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mAppWidgetContainer.setCallbacks(mWidgetCallbacks);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mAppWidgetContainer.setDeleteDropTarget(deleteDropTarget);
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mAppWidgetContainer.setMinScale(0.5f);
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        mSlidingChallengeLayout = (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mSlidingChallengeLayout != null) {
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mSlidingChallengeLayout.setOnChallengeScrolledListener(mViewStateManager);
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mAppWidgetContainer.setViewStateManager(mViewStateManager);
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mAppWidgetContainer.setLockPatternUtils(mLockPatternUtils);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ChallengeLayout challenge = mSlidingChallengeLayout != null ? mSlidingChallengeLayout :
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (ChallengeLayout) findViewById(R.id.multi_pane_challenge);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        challenge.setOnBouncerStateChangedListener(mViewStateManager);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mAppWidgetContainer.setBouncerAnimationDuration(challenge.getBouncerAnimationDuration());
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mViewStateManager.setPagedView(mAppWidgetContainer);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mViewStateManager.setChallengeLayout(challenge);
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mSecurityViewContainer = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mKeyguardSelectorView = (KeyguardSelectorView) findViewById(R.id.keyguard_selector_view);
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mViewStateManager.setSecurityViewContainer(mSecurityViewContainer);
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        setBackButtonEnabled(false);
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        addDefaultWidgets();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        addWidgetsFromSettings();
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!shouldEnableAddWidget()) {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mAppWidgetContainer.setAddWidgetEnabled(false);
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        checkAppWidgetConsistency();
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mSwitchPageRunnable.run();
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // This needs to be called after the pages are all added.
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mViewStateManager.showUsabilityHints();
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        showPrimarySecurityScreen(false);
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        updateSecurityViews();
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    private void setBackButtonEnabled(boolean enabled) {
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (mContext instanceof Activity) return;  // always enabled in activity mode
3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        setSystemUiVisibility(enabled ?
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private boolean shouldEnableAddWidget() {
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return numWidgets() < MAX_WIDGETS && mUserSetupCompleted;
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    private int getDisabledFeatures(DevicePolicyManager dpm) {
4077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        int disabledFeatures = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (dpm != null) {
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            final int currentUser = mLockPatternUtils.getCurrentUser();
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUser);
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return disabledFeatures;
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private boolean widgetsDisabledByDpm() {
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0;
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    private boolean cameraDisabledByDpm() {
4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        return mCameraDisabled
4217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                || (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void updateSecurityViews() {
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int children = mSecurityViewContainer.getChildCount();
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (int i = 0; i < children; i++) {
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            updateSecurityView(mSecurityViewContainer.getChildAt(i));
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    private void updateSecurityView(View view) {
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (view instanceof KeyguardSecurityView) {
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            KeyguardSecurityView ksv = (KeyguardSecurityView) view;
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ksv.setKeyguardCallback(mCallback);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ksv.setLockPatternUtils(mLockPatternUtils);
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (mViewStateManager.isBouncing()) {
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                ksv.showBouncer(0);
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            } else {
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                ksv.hideBouncer(0);
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            Log.w(TAG, "View " + view + " is not a KeyguardSecurityView");
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void setLockPatternUtils(LockPatternUtils utils) {
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mSecurityModel.setLockPatternUtils(utils);
4487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        mLockPatternUtils = utils;
4497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        updateSecurityViews();
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    @Override
4537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    protected void onAttachedToWindow() {
4547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        super.onAttachedToWindow();
4557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        mAppWidgetHost.startListening();
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @Override
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protected void onDetachedFromWindow() {
4617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        super.onDetachedFromWindow();
4627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        mAppWidgetHost.stopListening();
4637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
4647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void addWidget(AppWidgetHostView view, int pageIndex) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mAppWidgetContainer.addWidget(view, pageIndex);
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private KeyguardWidgetPager.Callbacks mWidgetCallbacks
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            = new KeyguardWidgetPager.Callbacks() {
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void userActivity() {
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            KeyguardHostView.this.userActivity();
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void onUserActivityTimeoutChanged() {
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            KeyguardHostView.this.onUserActivityTimeoutChanged();
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void onAddView(View v) {
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (!shouldEnableAddWidget()) {
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                mAppWidgetContainer.setAddWidgetEnabled(false);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void onRemoveView(View v, boolean deletePermanently) {
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (deletePermanently) {
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID &&
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        appWidgetId != LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    mAppWidgetHost.deleteAppWidgetId(appWidgetId);
496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                }
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void onRemoveViewAnimationCompleted() {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (shouldEnableAddWidget()) {
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                mAppWidgetContainer.setAddWidgetEnabled(true);
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
5077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    public void initializeSwitchingUserState(boolean switching) {
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!switching && mKeyguardMultiUserSelectorView != null) {
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mKeyguardMultiUserSelectorView.finalizeActiveUserView(false);
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public void userActivity() {
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mViewMediatorCallback != null) {
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mViewMediatorCallback.userActivity();
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public void onUserActivityTimeoutChanged() {
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mViewMediatorCallback != null) {
5227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            mViewMediatorCallback.onUserActivityTimeoutChanged();
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @Override
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public long getUserActivityTimeout() {
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Currently only considering user activity timeouts needed by widgets.
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Could also take into account longer timeouts for certain security views.
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mAppWidgetContainer != null) {
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return mAppWidgetContainer.getUserActivityTimeout();
5327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return -1;
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void userActivity(long timeout) {
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (mViewMediatorCallback != null) {
5407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                mViewMediatorCallback.userActivity(timeout);
5417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            }
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void dismiss(boolean authenticated) {
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            showNextSecurityScreenOrFinish(authenticated);
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public boolean isVerifyUnlockOnly() {
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return mIsVerifyUnlockOnly;
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void reportSuccessfulUnlockAttempt() {
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            KeyguardUpdateMonitor.getInstance(mContext).clearFailedUnlockAttempts();
5547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            mLockPatternUtils.reportSuccessfulPasswordAttempt();
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void reportFailedUnlockAttempt() {
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (mCurrentSecuritySelection == SecurityMode.Biometric) {
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                KeyguardUpdateMonitor.getInstance(mContext).reportFailedBiometricUnlockAttempt();
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            } else {
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                KeyguardHostView.this.reportFailedUnlockAttempt();
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public int getFailedAttempts() {
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
5677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void showBackupSecurity() {
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            KeyguardHostView.this.showBackupSecurityScreen();
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        @Override
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void setOnDismissAction(OnDismissAction action) {
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            KeyguardHostView.this.setOnDismissAction(action);
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void showDialog(String title, String message) {
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final AlertDialog dialog = new AlertDialog.Builder(mContext)
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            .setTitle(title)
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            .setMessage(message)
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            .setNeutralButton(com.android.internal.R.string.ok, null)
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            .create();
5877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (!(mContext instanceof Activity)) {
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dialog.show();
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void showTimeoutDialog() {
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int messageId = 0;
5967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        switch (mSecurityModel.getSecurityMode()) {
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case Pattern:
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                messageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message;
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                break;
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case PIN:
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                messageId = R.string.kg_too_many_failed_pin_attempts_dialog_message;
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                break;
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case Password:
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                messageId = R.string.kg_too_many_failed_password_attempts_dialog_message;
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                break;
6077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (messageId != 0) {
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            final String message = mContext.getString(messageId,
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(),
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    timeoutInSeconds);
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            showDialog(null, message);
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void showAlmostAtWipeDialog(int attempts, int remaining) {
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        String message = mContext.getString(R.string.kg_failed_attempts_almost_at_wipe,
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                attempts, remaining);
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        showDialog(null, message);
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void showWipeDialog(int attempts) {
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        String message = mContext.getString(R.string.kg_failed_attempts_now_wiping, attempts);
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        showDialog(null, message);
6277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    private void showAlmostAtAccountLoginDialog() {
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        String message = mContext.getString(R.string.kg_failed_attempts_almost_at_login,
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        showDialog(null, message);
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void reportFailedUnlockAttempt() {
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
6407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        final int failedAttempts = monitor.getFailedUnlockAttempts() + 1; // +1 for this time
6417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SecurityMode mode = mSecurityModel.getSecurityMode();
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                .getMaximumFailedPasswordsForWipe(null, mLockPatternUtils.getCurrentUser());
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                (failedAttemptsBeforeWipe - failedAttempts)
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        boolean showTimeout = false;
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // If we reach this code, it means the user has installed a DevicePolicyManager
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // that requests device wipe after N attempts.  Once we get below the grace
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // period, we'll post this dialog every time as a clear warning until the
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // bombshell hits and the device is wiped.
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (remainingBeforeWipe > 0) {
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            } else {
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                // Too many attempts. The device will be wiped shortly.
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                Slog.i(TAG, "Too many unlock attempts; device will be wiped!");
6687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                showWipeDialog(failedAttempts);
6697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            }
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            showTimeout =
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (usingPattern && mEnableFallback) {
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (failedAttempts == failedAttemptWarning) {
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    showAlmostAtAccountLoginDialog();
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    showTimeout = false; // don't show both dialogs
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    mLockPatternUtils.setPermanentlyLocked(true);
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    showSecurityScreen(SecurityMode.Account);
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    // don't show timeout dialog because we show account unlock screen next
6812385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                    showTimeout = false;
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        monitor.reportFailedUnlockAttempt();
6867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        mLockPatternUtils.reportFailedPasswordAttempt();
6877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (showTimeout) {
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            showTimeoutDialog();
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Shows the primary security screen for the user. This will be either the multi-selector
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * or the user's security method.
6957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch     * @param turningOff true if the device is being turned off
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void showPrimarySecurityScreen(boolean turningOff) {
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SecurityMode securityMode = mSecurityModel.getSecurityMode();
6992385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!turningOff &&
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                KeyguardUpdateMonitor.getInstance(mContext).isAlternateUnlockEnabled()) {
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // If we're not turning off, then allow biometric alternate.
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // We'll reload it when the device comes back on.
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            securityMode = mSecurityModel.getAlternateFor(securityMode);
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        showSecurityScreen(securityMode);
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Shows the backup security screen for the current security mode.  This could be used for
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * password recovery screens but is currently only used for pattern unlock to show the
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * account unlock screen and biometric unlock to show the user's normal unlock.
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void showBackupSecurityScreen() {
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (DEBUG) Log.d(TAG, "showBackupSecurity()");
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SecurityMode backup = mSecurityModel.getBackupSecurityMode(mCurrentSecuritySelection);
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        showSecurityScreen(backup);
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public boolean showNextSecurityScreenIfPresent() {
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SecurityMode securityMode = mSecurityModel.getSecurityMode();
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Allow an alternate, such as biometric unlock
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        securityMode = mSecurityModel.getAlternateFor(securityMode);
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (SecurityMode.None == securityMode) {
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return false;
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            showSecurityScreen(securityMode); // switch to the alternate security view
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return true;
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private void showNextSecurityScreenOrFinish(boolean authenticated) {
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        boolean finish = false;
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (SecurityMode.None == mCurrentSecuritySelection) {
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            SecurityMode securityMode = mSecurityModel.getSecurityMode();
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // Allow an alternate, such as biometric unlock
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            securityMode = mSecurityModel.getAlternateFor(securityMode);
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (SecurityMode.None == securityMode) {
7407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                finish = true; // no security required
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            } else {
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                showSecurityScreen(securityMode); // switch to the alternate security view
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else if (authenticated) {
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            switch (mCurrentSecuritySelection) {
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                case Pattern:
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                case Password:
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                case PIN:
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                case Account:
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                case Biometric:
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    finish = true;
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    break;
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                case SimPin:
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                case SimPuk:
7567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
7577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    SecurityMode securityMode = mSecurityModel.getSecurityMode();
7587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    if (securityMode != SecurityMode.None) {
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        showSecurityScreen(securityMode);
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    } else {
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        finish = true;
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    }
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    break;
764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                default:
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    showPrimarySecurityScreen(false);
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    break;
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
7707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        } else {
7717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            showPrimarySecurityScreen(false);
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
7737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (finish) {
7747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            // If the alternate unlock was suppressed, it can now be safely
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // enabled because the user has left keyguard.
776ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
777ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
778ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            // If there's a pending runnable because the user interacted with a widget
779ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            // and we're leaving keyguard, then run it.
780ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            boolean deferKeyguardDone = false;
781ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            if (mDismissAction != null) {
782ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                deferKeyguardDone = mDismissAction.onDismiss();
783ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                mDismissAction = null;
784ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            }
785ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            if (mViewMediatorCallback != null) {
786ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                if (deferKeyguardDone) {
787ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    mViewMediatorCallback.keyguardDonePending();
788ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                } else {
789ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    mViewMediatorCallback.keyguardDone(true);
790ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                }
791ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            }
792ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        } else {
793ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            mViewStateManager.showBouncer(true);
794ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
795ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
796ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
797ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    private OnClickHandler mOnClickHandler = new OnClickHandler() {
798ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        @Override
799ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        public boolean onClickHandler(final View view,
800ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                final android.app.PendingIntent pendingIntent,
801ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                final Intent fillInIntent) {
802ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            if (pendingIntent.isActivity()) {
803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                setOnDismissAction(new OnDismissAction() {
804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    public boolean onDismiss() {
805ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        try {
806ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                              // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
807ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                              Context context = view.getContext();
808ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                              ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
809ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                      0, 0,
810ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                      view.getMeasuredWidth(), view.getMeasuredHeight());
811ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                              context.startIntentSender(
812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                      pendingIntent.getIntentSender(), fillInIntent,
813ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                      Intent.FLAG_ACTIVITY_NEW_TASK,
814ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                      Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        } catch (IntentSender.SendIntentException e) {
816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                            android.util.Log.e(TAG, "Cannot send pending intent: ", e);
817ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        } catch (Exception e) {
818ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                            android.util.Log.e(TAG, "Cannot send pending intent due to " +
819ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                    "unknown exception: ", e);
820ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        }
821ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        return false;
822ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    }
823ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                });
824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                if (mViewStateManager.isChallengeShowing()) {
826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    mViewStateManager.showBouncer(true);
827ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                } else {
828ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    mCallback.dismiss(false);
829ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                }
830ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                return true;
831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            } else {
832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                return super.onClickHandler(view, pendingIntent, fillInIntent);
833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            }
834ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        };
835ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    };
836ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
837ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Used to ignore callbacks from methods that are no longer current (e.g. face unlock).
838ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // This avoids unwanted asynchronous events from messing with the state.
839ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
840ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
841ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        @Override
842ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        public void userActivity(long timeout) {
843ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
844ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
845ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        @Override
846ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        public void showBackupSecurity() {
847ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
848ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        @Override
850ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        public void setOnDismissAction(OnDismissAction action) {
851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
852ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
853ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        @Override
854ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        public void reportSuccessfulUnlockAttempt() {
855ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
856ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
857ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        @Override
858ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        public void reportFailedUnlockAttempt() {
859ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
860ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
861ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        @Override
862ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        public boolean isVerifyUnlockOnly() {
863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            return false;
864ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
865ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
866ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        @Override
867ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        public int getFailedAttempts() {
868            return 0;
869        }
870
871        @Override
872        public void dismiss(boolean securityVerified) {
873        }
874    };
875
876    protected boolean mShowSecurityWhenReturn;
877
878    @Override
879    public void reset() {
880        mIsVerifyUnlockOnly = false;
881        mAppWidgetContainer.setCurrentPage(getWidgetPosition(R.id.keyguard_status_view));
882    }
883
884    /**
885     * Sets an action to perform when keyguard is dismissed.
886     * @param action
887     */
888    protected void setOnDismissAction(OnDismissAction action) {
889        mDismissAction = action;
890    }
891
892    private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
893        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
894        KeyguardSecurityView view = null;
895        final int children = mSecurityViewContainer.getChildCount();
896        for (int child = 0; child < children; child++) {
897            if (mSecurityViewContainer.getChildAt(child).getId() == securityViewIdForMode) {
898                view = ((KeyguardSecurityView)mSecurityViewContainer.getChildAt(child));
899                break;
900            }
901        }
902        int layoutId = getLayoutIdFor(securityMode);
903        if (view == null && layoutId != 0) {
904            final LayoutInflater inflater = LayoutInflater.from(mContext);
905            if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
906            View v = inflater.inflate(layoutId, mSecurityViewContainer, false);
907            mSecurityViewContainer.addView(v);
908            updateSecurityView(v);
909            view = (KeyguardSecurityView)v;
910        }
911
912        if (view instanceof KeyguardSelectorView) {
913            KeyguardSelectorView selectorView = (KeyguardSelectorView) view;
914            View carrierText = selectorView.findViewById(R.id.keyguard_selector_fade_container);
915            selectorView.setCarrierArea(carrierText);
916        }
917
918        return view;
919    }
920
921    /**
922     * Switches to the given security view unless it's already being shown, in which case
923     * this is a no-op.
924     *
925     * @param securityMode
926     */
927    private void showSecurityScreen(SecurityMode securityMode) {
928        if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
929
930        if (securityMode == mCurrentSecuritySelection) return;
931
932        KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
933        KeyguardSecurityView newView = getSecurityView(securityMode);
934
935        // Enter full screen mode if we're in SIM or Account screen
936        boolean fullScreenEnabled = getResources().getBoolean(
937                com.android.internal.R.bool.kg_sim_puk_account_full_screen);
938        boolean isSimOrAccount = securityMode == SecurityMode.SimPin
939                || securityMode == SecurityMode.SimPuk
940                || securityMode == SecurityMode.Account;
941        mAppWidgetContainer.setVisibility(
942                isSimOrAccount && fullScreenEnabled ? View.GONE : View.VISIBLE);
943
944        if (mSlidingChallengeLayout != null) {
945            mSlidingChallengeLayout.setChallengeInteractive(!fullScreenEnabled);
946        }
947
948        // Emulate Activity life cycle
949        if (oldView != null) {
950            oldView.onPause();
951            oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
952        }
953        newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
954        newView.setKeyguardCallback(mCallback);
955
956        final boolean needsInput = newView.needsInput();
957        if (mViewMediatorCallback != null) {
958            mViewMediatorCallback.setNeedsInput(needsInput);
959        }
960
961        // Find and show this child.
962        final int childCount = mSecurityViewContainer.getChildCount();
963
964        mSecurityViewContainer.setInAnimation(
965                AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_in));
966        mSecurityViewContainer.setOutAnimation(
967                AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_out));
968        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
969        for (int i = 0; i < childCount; i++) {
970            if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
971                mSecurityViewContainer.setDisplayedChild(i);
972                break;
973            }
974        }
975
976        if (securityMode == SecurityMode.None) {
977            // Discard current runnable if we're switching back to the selector view
978            setOnDismissAction(null);
979        }
980        if (securityMode == SecurityMode.Account && !mLockPatternUtils.isPermanentlyLocked()) {
981            // we're showing account as a backup, provide a way to get back to primary
982            setBackButtonEnabled(true);
983        }
984        mCurrentSecuritySelection = securityMode;
985    }
986
987    @Override
988    public void onScreenTurnedOn() {
989        if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
990        showPrimarySecurityScreen(false);
991        getSecurityView(mCurrentSecuritySelection).onResume(KeyguardSecurityView.SCREEN_ON);
992
993        // This is a an attempt to fix bug 7137389 where the device comes back on but the entire
994        // layout is blank but forcing a layout causes it to reappear (e.g. with with
995        // hierarchyviewer).
996        requestLayout();
997
998        if (mViewStateManager != null) {
999            mViewStateManager.showUsabilityHints();
1000        }
1001        requestFocus();
1002    }
1003
1004    @Override
1005    public void onScreenTurnedOff() {
1006        if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
1007                Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
1008        // Once the screen turns off, we no longer consider this to be first boot and we want the
1009        // biometric unlock to start next time keyguard is shown.
1010        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
1011        // We use mAppWidgetToShow to show a particular widget after you add it-- once the screen
1012        // turns off we reset that behavior
1013        clearAppWidgetToShow();
1014        checkAppWidgetConsistency();
1015        showPrimarySecurityScreen(true);
1016        getSecurityView(mCurrentSecuritySelection).onPause();
1017        CameraWidgetFrame cameraPage = findCameraPage();
1018        if (cameraPage != null) {
1019            cameraPage.onScreenTurnedOff();
1020        }
1021        clearFocus();
1022    }
1023
1024    public void clearAppWidgetToShow() {
1025        mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
1026    }
1027
1028    @Override
1029    public void show() {
1030        if (DEBUG) Log.d(TAG, "show()");
1031        showPrimarySecurityScreen(false);
1032    }
1033
1034    private boolean isSecure() {
1035        SecurityMode mode = mSecurityModel.getSecurityMode();
1036        switch (mode) {
1037            case Pattern:
1038                return mLockPatternUtils.isLockPatternEnabled();
1039            case Password:
1040            case PIN:
1041                return mLockPatternUtils.isLockPasswordEnabled();
1042            case SimPin:
1043            case SimPuk:
1044            case Account:
1045                return true;
1046            case None:
1047                return false;
1048            default:
1049                throw new IllegalStateException("Unknown security mode " + mode);
1050        }
1051    }
1052
1053    @Override
1054    public void wakeWhenReadyTq(int keyCode) {
1055        if (DEBUG) Log.d(TAG, "onWakeKey");
1056        if (keyCode == KeyEvent.KEYCODE_MENU && isSecure()) {
1057            if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU");
1058            showSecurityScreen(SecurityMode.None);
1059        } else {
1060            if (DEBUG) Log.d(TAG, "poking wake lock immediately");
1061        }
1062        if (mViewMediatorCallback != null) {
1063            mViewMediatorCallback.wakeUp();
1064        }
1065    }
1066
1067    @Override
1068    public void verifyUnlock() {
1069        SecurityMode securityMode = mSecurityModel.getSecurityMode();
1070        if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
1071            if (mViewMediatorCallback != null) {
1072                mViewMediatorCallback.keyguardDone(true);
1073            }
1074        } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
1075                && securityMode != KeyguardSecurityModel.SecurityMode.PIN
1076                && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
1077            // can only verify unlock when in pattern/password mode
1078            if (mViewMediatorCallback != null) {
1079                mViewMediatorCallback.keyguardDone(false);
1080            }
1081        } else {
1082            // otherwise, go to the unlock screen, see if they can verify it
1083            mIsVerifyUnlockOnly = true;
1084            showSecurityScreen(securityMode);
1085        }
1086    }
1087
1088    private int getSecurityViewIdForMode(SecurityMode securityMode) {
1089        switch (securityMode) {
1090            case None: return R.id.keyguard_selector_view;
1091            case Pattern: return R.id.keyguard_pattern_view;
1092            case PIN: return R.id.keyguard_pin_view;
1093            case Password: return R.id.keyguard_password_view;
1094            case Biometric: return R.id.keyguard_face_unlock_view;
1095            case Account: return R.id.keyguard_account_view;
1096            case SimPin: return R.id.keyguard_sim_pin_view;
1097            case SimPuk: return R.id.keyguard_sim_puk_view;
1098        }
1099        return 0;
1100    }
1101
1102    private int getLayoutIdFor(SecurityMode securityMode) {
1103        switch (securityMode) {
1104            case None: return R.layout.keyguard_selector_view;
1105            case Pattern: return R.layout.keyguard_pattern_view;
1106            case PIN: return R.layout.keyguard_pin_view;
1107            case Password: return R.layout.keyguard_password_view;
1108            case Biometric: return R.layout.keyguard_face_unlock_view;
1109            case Account: return R.layout.keyguard_account_view;
1110            case SimPin: return R.layout.keyguard_sim_pin_view;
1111            case SimPuk: return R.layout.keyguard_sim_puk_view;
1112            default:
1113                return 0;
1114        }
1115    }
1116
1117    private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) {
1118        AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
1119        if (appWidgetInfo != null) {
1120            AppWidgetHostView view = mAppWidgetHost.createView(mContext, appId, appWidgetInfo);
1121            addWidget(view, pageIndex);
1122            return true;
1123        } else {
1124            if (updateDbIfFailed) {
1125                Log.w(TAG, "*** AppWidgetInfo for app widget id " + appId + "  was null for user"
1126                        + mUserId + ", deleting");
1127                mAppWidgetHost.deleteAppWidgetId(appId);
1128                mLockPatternUtils.removeAppWidget(appId);
1129            }
1130            return false;
1131        }
1132    }
1133
1134    private final CameraWidgetFrame.Callbacks mCameraWidgetCallbacks =
1135        new CameraWidgetFrame.Callbacks() {
1136            @Override
1137            public void onLaunchingCamera() {
1138                setSliderHandleAlpha(0);
1139            }
1140
1141            @Override
1142            public void onCameraLaunchedSuccessfully() {
1143                if (mAppWidgetContainer.isCameraPage(mAppWidgetContainer.getCurrentPage())) {
1144                    mAppWidgetContainer.scrollLeft();
1145                }
1146                setSliderHandleAlpha(1);
1147                mShowSecurityWhenReturn = true;
1148            }
1149
1150            @Override
1151            public void onCameraLaunchedUnsuccessfully() {
1152                setSliderHandleAlpha(1);
1153            }
1154
1155            private void setSliderHandleAlpha(float alpha) {
1156                SlidingChallengeLayout slider =
1157                        (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
1158                if (slider != null) {
1159                    slider.setHandleAlpha(alpha);
1160                }
1161            }
1162        };
1163
1164    private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
1165        @Override
1166        Context getContext() {
1167            return mContext;
1168        }
1169
1170        @Override
1171        KeyguardSecurityCallback getCallback() {
1172            return mCallback;
1173        }
1174
1175        @Override
1176        LockPatternUtils getLockPatternUtils() {
1177            return mLockPatternUtils;
1178        }
1179    };
1180
1181    private int numWidgets() {
1182        final int childCount = mAppWidgetContainer.getChildCount();
1183        int widgetCount = 0;
1184        for (int i = 0; i < childCount; i++) {
1185            if (mAppWidgetContainer.isWidgetPage(i)) {
1186                widgetCount++;
1187            }
1188        }
1189        return widgetCount;
1190    }
1191
1192    private void addDefaultWidgets() {
1193        if (!mSafeModeEnabled && !widgetsDisabledByDpm()) {
1194            LayoutInflater inflater = LayoutInflater.from(mContext);
1195            View addWidget = inflater.inflate(R.layout.keyguard_add_widget, this, false);
1196            mAppWidgetContainer.addWidget(addWidget, 0);
1197            View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
1198            addWidgetButton.setOnClickListener(new OnClickListener() {
1199                @Override
1200                public void onClick(View v) {
1201                    // Pass in an invalid widget id... the picker will allocate an ID for us
1202                    mActivityLauncher.launchWidgetPicker(AppWidgetManager.INVALID_APPWIDGET_ID);
1203                }
1204            });
1205        }
1206
1207        // We currently disable cameras in safe mode because we support loading 3rd party
1208        // cameras we can't trust.  TODO: plumb safe mode into camera creation code and only
1209        // inflate system-provided camera?
1210        if (!mSafeModeEnabled && !cameraDisabledByDpm() && mUserSetupCompleted
1211                && mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
1212            View cameraWidget =
1213                    CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks, mActivityLauncher);
1214            if (cameraWidget != null) {
1215                mAppWidgetContainer.addWidget(cameraWidget);
1216            }
1217        }
1218
1219        enableUserSelectorIfNecessary();
1220    }
1221
1222    /**
1223     * Create KeyguardTransportControlView on demand.
1224     * @return
1225     */
1226    private KeyguardTransportControlView getOrCreateTransportControl() {
1227        if (mTransportControl == null) {
1228            LayoutInflater inflater = LayoutInflater.from(mContext);
1229            mTransportControl = (KeyguardTransportControlView)
1230                    inflater.inflate(R.layout.keyguard_transport_control_view, this, false);
1231        }
1232        return mTransportControl;
1233    }
1234
1235    private int getInsertPageIndex() {
1236        View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
1237        int insertionIndex = mAppWidgetContainer.indexOfChild(addWidget);
1238        if (insertionIndex < 0) {
1239            insertionIndex = 0; // no add widget page found
1240        } else {
1241            insertionIndex++; // place after add widget
1242        }
1243        return insertionIndex;
1244    }
1245
1246    private void addDefaultStatusWidget(int index) {
1247        LayoutInflater inflater = LayoutInflater.from(mContext);
1248        View statusWidget = inflater.inflate(R.layout.keyguard_status_view, null, true);
1249        mAppWidgetContainer.addWidget(statusWidget, index);
1250    }
1251
1252    private void addWidgetsFromSettings() {
1253        if (mSafeModeEnabled || widgetsDisabledByDpm()) {
1254            return;
1255        }
1256
1257        int insertionIndex = getInsertPageIndex();
1258
1259        // Add user-selected widget
1260        final int[] widgets = mLockPatternUtils.getAppWidgets();
1261
1262        if (widgets == null) {
1263            Log.d(TAG, "Problem reading widgets");
1264        } else {
1265            for (int i = widgets.length -1; i >= 0; i--) {
1266                if (widgets[i] == LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
1267                    addDefaultStatusWidget(insertionIndex);
1268                } else {
1269                    // We add the widgets from left to right, starting after the first page after
1270                    // the add page. We count down, since the order will be persisted from right
1271                    // to left, starting after camera.
1272                    addWidget(widgets[i], insertionIndex, true);
1273                }
1274            }
1275        }
1276    }
1277
1278    private int allocateIdForDefaultAppWidget() {
1279        int appWidgetId;
1280        Resources res = getContext().getResources();
1281        ComponentName defaultAppWidget = new ComponentName(
1282                res.getString(R.string.widget_default_package_name),
1283                res.getString(R.string.widget_default_class_name));
1284
1285        // Note: we don't support configuring the widget
1286        appWidgetId = mAppWidgetHost.allocateAppWidgetId();
1287
1288        try {
1289            mAppWidgetManager.bindAppWidgetId(appWidgetId, defaultAppWidget);
1290
1291        } catch (IllegalArgumentException e) {
1292            Log.e(TAG, "Error when trying to bind default AppWidget: " + e);
1293            mAppWidgetHost.deleteAppWidgetId(appWidgetId);
1294            appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
1295        }
1296        return appWidgetId;
1297    }
1298    public void checkAppWidgetConsistency() {
1299        // Since this method may bind a widget (which we can't do until boot completed) we
1300        // may have to defer it until after boot complete.
1301        if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
1302            mCheckAppWidgetConsistencyOnBootCompleted = true;
1303            return;
1304        }
1305        final int childCount = mAppWidgetContainer.getChildCount();
1306        boolean widgetPageExists = false;
1307        for (int i = 0; i < childCount; i++) {
1308            if (mAppWidgetContainer.isWidgetPage(i)) {
1309                widgetPageExists = true;
1310                break;
1311            }
1312        }
1313        if (!widgetPageExists) {
1314            final int insertPageIndex = getInsertPageIndex();
1315
1316            final boolean userAddedWidgetsEnabled = !widgetsDisabledByDpm();
1317            boolean addedDefaultAppWidget = false;
1318
1319            if (!mSafeModeEnabled) {
1320                if (userAddedWidgetsEnabled) {
1321                    int appWidgetId = allocateIdForDefaultAppWidget();
1322                    if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
1323                        addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, true);
1324                    }
1325                } else {
1326                    // note: even if widgetsDisabledByDpm() returns true, we still bind/create
1327                    // the default appwidget if possible
1328                    int appWidgetId = mLockPatternUtils.getFallbackAppWidgetId();
1329                    if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
1330                        appWidgetId = allocateIdForDefaultAppWidget();
1331                        if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
1332                            mLockPatternUtils.writeFallbackAppWidgetId(appWidgetId);
1333                        }
1334                    }
1335                    if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
1336                        addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, false);
1337                        if (!addedDefaultAppWidget) {
1338                            mAppWidgetHost.deleteAppWidgetId(appWidgetId);
1339                            mLockPatternUtils.writeFallbackAppWidgetId(
1340                                    AppWidgetManager.INVALID_APPWIDGET_ID);
1341                        }
1342                    }
1343                }
1344            }
1345
1346            // Use the built-in status/clock view if we can't inflate the default widget
1347            if (!addedDefaultAppWidget) {
1348                addDefaultStatusWidget(insertPageIndex);
1349            }
1350
1351            // trigger DB updates only if user-added widgets are enabled
1352            if (!mSafeModeEnabled && userAddedWidgetsEnabled) {
1353                mAppWidgetContainer.onAddView(
1354                        mAppWidgetContainer.getChildAt(insertPageIndex), insertPageIndex);
1355            }
1356        }
1357    }
1358
1359    Runnable mSwitchPageRunnable = new Runnable() {
1360        @Override
1361        public void run() {
1362           showAppropriateWidgetPage();
1363        }
1364    };
1365
1366    static class SavedState extends BaseSavedState {
1367        int transportState;
1368        int appWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
1369
1370        SavedState(Parcelable superState) {
1371            super(superState);
1372        }
1373
1374        private SavedState(Parcel in) {
1375            super(in);
1376            this.transportState = in.readInt();
1377            this.appWidgetToShow = in.readInt();
1378        }
1379
1380        @Override
1381        public void writeToParcel(Parcel out, int flags) {
1382            super.writeToParcel(out, flags);
1383            out.writeInt(this.transportState);
1384            out.writeInt(this.appWidgetToShow);
1385        }
1386
1387        public static final Parcelable.Creator<SavedState> CREATOR
1388                = new Parcelable.Creator<SavedState>() {
1389            public SavedState createFromParcel(Parcel in) {
1390                return new SavedState(in);
1391            }
1392
1393            public SavedState[] newArray(int size) {
1394                return new SavedState[size];
1395            }
1396        };
1397    }
1398
1399    @Override
1400    public Parcelable onSaveInstanceState() {
1401        if (DEBUG) Log.d(TAG, "onSaveInstanceState, tstate=" + mTransportState);
1402        Parcelable superState = super.onSaveInstanceState();
1403        SavedState ss = new SavedState(superState);
1404        // If the transport is showing, force it to show it on restore.
1405        final boolean showing = mTransportControl != null
1406                && mAppWidgetContainer.getWidgetPageIndex(mTransportControl) >= 0;
1407        ss.transportState =  showing ? TRANSPORT_VISIBLE : mTransportState;
1408        ss.appWidgetToShow = mAppWidgetToShow;
1409        return ss;
1410    }
1411
1412    @Override
1413    public void onRestoreInstanceState(Parcelable state) {
1414        if (!(state instanceof SavedState)) {
1415            super.onRestoreInstanceState(state);
1416            return;
1417        }
1418        SavedState ss = (SavedState) state;
1419        super.onRestoreInstanceState(ss.getSuperState());
1420        mTransportState = (ss.transportState);
1421        mAppWidgetToShow = ss.appWidgetToShow;
1422        if (DEBUG) Log.d(TAG, "onRestoreInstanceState, transport=" + mTransportState);
1423        post(mSwitchPageRunnable);
1424    }
1425
1426    @Override
1427    public void onWindowFocusChanged(boolean hasWindowFocus) {
1428        super.onWindowFocusChanged(hasWindowFocus);
1429        if (DEBUG) Log.d(TAG, "Window is " + (hasWindowFocus ? "focused" : "unfocused"));
1430        if (hasWindowFocus && mShowSecurityWhenReturn) {
1431            SlidingChallengeLayout slider =
1432                (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
1433            if (slider != null) {
1434                slider.setHandleAlpha(1);
1435                slider.showChallenge(true);
1436            }
1437            mShowSecurityWhenReturn = false;
1438        }
1439    }
1440
1441    private void showAppropriateWidgetPage() {
1442        int state = mTransportState;
1443        ensureTransportPresentOrRemoved(state);
1444        int pageToShow = getAppropriateWidgetPage(state);
1445        mAppWidgetContainer.setCurrentPage(pageToShow);
1446    }
1447
1448    /**
1449     * Examines the current state and adds the transport to the widget pager when the state changes.
1450     *
1451     * Showing the initial transport and keeping it around is a bit tricky because the signals
1452     * coming from music players aren't always clear. Here's how the states are handled:
1453     *
1454     * {@link TRANSPORT_GONE} means we have no reason to show the transport - remove it if present.
1455     *
1456     * {@link TRANSPORT_INVISIBLE} means we have potential to show the transport because a music
1457     * player is registered but not currently playing music (or we don't know the state yet). The
1458     * code adds it conditionally on play state.
1459     *
1460     * {@link #TRANSPORT_VISIBLE} means a music player is active and transport should be showing.
1461     *
1462     * Once the transport is showing, we always show it until keyguard is dismissed. This state is
1463     * maintained by onSave/RestoreInstanceState(). This state is cleared in
1464     * {@link KeyguardViewManager#hide} when keyguard is dismissed, which causes the transport to be
1465     * gone when keyguard is restarted until we get an update with the current state.
1466     *
1467     * @param state
1468     */
1469    private void ensureTransportPresentOrRemoved(int state) {
1470        final boolean showing = getWidgetPosition(R.id.keyguard_transport_control) != -1;
1471        final boolean visible = state == TRANSPORT_VISIBLE;
1472        final boolean shouldBeVisible = state == TRANSPORT_INVISIBLE && isMusicPlaying(state);
1473        if (!showing && (visible || shouldBeVisible)) {
1474            if (DEBUGXPORT) Log.v(TAG, "add transport");
1475            // insert to left of camera if it exists, otherwise after right-most widget
1476            int lastWidget = mAppWidgetContainer.getChildCount() - 1;
1477            int position = 0; // handle no widget case
1478            if (lastWidget >= 0) {
1479                position = mAppWidgetContainer.isCameraPage(lastWidget) ?
1480                        lastWidget : lastWidget + 1;
1481            }
1482            mAppWidgetContainer.addWidget(getOrCreateTransportControl(), position);
1483        } else if (showing && state == TRANSPORT_GONE) {
1484            if (DEBUGXPORT) Log.v(TAG, "remove transport");
1485            mAppWidgetContainer.removeWidget(getOrCreateTransportControl());
1486            mTransportControl = null;
1487        }
1488    }
1489
1490    private CameraWidgetFrame findCameraPage() {
1491        for (int i = mAppWidgetContainer.getChildCount() - 1; i >= 0; i--) {
1492            if (mAppWidgetContainer.isCameraPage(i)) {
1493                return (CameraWidgetFrame) mAppWidgetContainer.getChildAt(i);
1494            }
1495        }
1496        return null;
1497    }
1498
1499    boolean isMusicPage(int pageIndex) {
1500        return pageIndex >= 0 && pageIndex == getWidgetPosition(R.id.keyguard_transport_control);
1501    }
1502
1503    private int getAppropriateWidgetPage(int musicTransportState) {
1504        // assumes at least one widget (besides camera + add)
1505        if (mAppWidgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
1506            final int childCount = mAppWidgetContainer.getChildCount();
1507            for (int i = 0; i < childCount; i++) {
1508                if (mAppWidgetContainer.getWidgetPageAt(i).getContentAppWidgetId()
1509                        == mAppWidgetToShow) {
1510                    return i;
1511                }
1512            }
1513            mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
1514        }
1515        // if music playing, show transport
1516        if (musicTransportState == TRANSPORT_VISIBLE) {
1517            if (DEBUG) Log.d(TAG, "Music playing, show transport");
1518            return mAppWidgetContainer.getWidgetPageIndex(getOrCreateTransportControl());
1519        }
1520
1521        // else show the right-most widget (except for camera)
1522        int rightMost = mAppWidgetContainer.getChildCount() - 1;
1523        if (mAppWidgetContainer.isCameraPage(rightMost)) {
1524            rightMost--;
1525        }
1526        if (DEBUG) Log.d(TAG, "Show right-most page " + rightMost);
1527        return rightMost;
1528    }
1529
1530    private void enableUserSelectorIfNecessary() {
1531        if (!UserManager.supportsMultipleUsers()) {
1532            return; // device doesn't support multi-user mode
1533        }
1534        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1535        if (um == null) {
1536            Throwable t = new Throwable();
1537            t.fillInStackTrace();
1538            Log.e(TAG, "user service is null.", t);
1539            return;
1540        }
1541
1542        // if there are multiple users, we need to enable to multi-user switcher
1543        final List<UserInfo> users = um.getUsers(true);
1544        if (users == null) {
1545            Throwable t = new Throwable();
1546            t.fillInStackTrace();
1547            Log.e(TAG, "list of users is null.", t);
1548            return;
1549        }
1550
1551        final View multiUserView = findViewById(R.id.keyguard_user_selector);
1552        if (multiUserView == null) {
1553            Throwable t = new Throwable();
1554            t.fillInStackTrace();
1555            Log.e(TAG, "can't find user_selector in layout.", t);
1556            return;
1557        }
1558
1559        if (users.size() > 1) {
1560            if (multiUserView instanceof KeyguardMultiUserSelectorView) {
1561                mKeyguardMultiUserSelectorView = (KeyguardMultiUserSelectorView) multiUserView;
1562                mKeyguardMultiUserSelectorView.setVisibility(View.VISIBLE);
1563                mKeyguardMultiUserSelectorView.addUsers(users);
1564                UserSwitcherCallback callback = new UserSwitcherCallback() {
1565                    @Override
1566                    public void hideSecurityView(int duration) {
1567                        mSecurityViewContainer.animate().alpha(0).setDuration(duration);
1568                    }
1569
1570                    @Override
1571                    public void showSecurityView() {
1572                        mSecurityViewContainer.setAlpha(1.0f);
1573                    }
1574
1575                    @Override
1576                    public void showUnlockHint() {
1577                        if (mKeyguardSelectorView != null) {
1578                            mKeyguardSelectorView.showUsabilityHint();
1579                        }
1580                    }
1581
1582                    @Override
1583                    public void userActivity() {
1584                        if (mViewMediatorCallback != null) {
1585                            mViewMediatorCallback.userActivity();
1586                        }
1587                    }
1588                };
1589                mKeyguardMultiUserSelectorView.setCallback(callback);
1590            } else {
1591                Throwable t = new Throwable();
1592                t.fillInStackTrace();
1593                if (multiUserView == null) {
1594                    Log.e(TAG, "could not find the user_selector.", t);
1595                } else {
1596                    Log.e(TAG, "user_selector is the wrong type.", t);
1597                }
1598            }
1599        }
1600    }
1601
1602    @Override
1603    public void cleanUp() {
1604        // Make sure we let go of all widgets and their package contexts promptly. If we don't do
1605        // this, and the associated application is uninstalled, it can cause a soft reboot.
1606        int count = mAppWidgetContainer.getChildCount();
1607        for (int i = 0; i < count; i++) {
1608            KeyguardWidgetFrame frame = mAppWidgetContainer.getWidgetPageAt(i);
1609            frame.removeAllViews();
1610        }
1611    }
1612
1613    /**
1614     * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
1615     * some cases where we wish to disable it, notably when the menu button placement or technology
1616     * is prone to false positives.
1617     *
1618     * @return true if the menu key should be enabled
1619     */
1620    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
1621    private boolean shouldEnableMenuKey() {
1622        final Resources res = getResources();
1623        final boolean configDisabled = res.getBoolean(
1624                com.android.internal.R.bool.config_disableMenuKeyInLockScreen);
1625        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
1626        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
1627        return !configDisabled || isTestHarness || fileOverride;
1628    }
1629
1630    public void goToUserSwitcher() {
1631        mAppWidgetContainer.setCurrentPage(getWidgetPosition(R.id.keyguard_multi_user_selector));
1632    }
1633
1634    public void goToWidget(int appWidgetId) {
1635        mAppWidgetToShow = appWidgetId;
1636        mSwitchPageRunnable.run();
1637    }
1638
1639    public boolean handleMenuKey() {
1640        // The following enables the MENU key to work for testing automation
1641        if (shouldEnableMenuKey()) {
1642            showNextSecurityScreenOrFinish(false);
1643            return true;
1644        }
1645        return false;
1646    }
1647
1648    public boolean handleBackKey() {
1649        if (mCurrentSecuritySelection == SecurityMode.Account) {
1650            // go back to primary screen and re-disable back
1651            setBackButtonEnabled(false);
1652            showPrimarySecurityScreen(false /*turningOff*/);
1653            return true;
1654        }
1655        if (mCurrentSecuritySelection != SecurityMode.None) {
1656            mCallback.dismiss(false);
1657            return true;
1658        }
1659        return false;
1660    }
1661
1662    /**
1663     *  Dismisses the keyguard by going to the next screen or making it gone.
1664     */
1665    public void dismiss() {
1666        showNextSecurityScreenOrFinish(false);
1667    }
1668
1669    public void showAssistant() {
1670        final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
1671          .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
1672
1673        if (intent == null) return;
1674
1675        final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
1676                R.anim.keyguard_action_assist_enter, R.anim.keyguard_action_assist_exit,
1677                getHandler(), null);
1678
1679        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1680
1681        mActivityLauncher.launchActivityWithAnimation(
1682                intent, false, opts.toBundle(), null, null);
1683    }
1684}
1685