1dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock/*
2dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock * Copyright (C) 2012 The Android Open Source Project
3dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock *
4dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
5dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock * you may not use this file except in compliance with the License.
6dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock * You may obtain a copy of the License at
7dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock *
8dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
9dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock *
10dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock * Unless required by applicable law or agreed to in writing, software
11dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
12dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock * See the License for the specific language governing permissions and
14dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock * limitations under the License.
15dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock */
16dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
17dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockpackage com.android.internal.policy.impl.keyguard;
18dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
19dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.app.ActivityManagerNative;
20cfc3086b18396df03f982fb98112649dc5b5a6f2Adam Powellimport android.app.ActivityOptions;
2157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlockimport android.app.IActivityManager.WaitResult;
2265cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlockimport android.appwidget.AppWidgetManager;
2365cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlockimport android.appwidget.AppWidgetProviderInfo;
24dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.content.ActivityNotFoundException;
25dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.content.Context;
26dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.content.Intent;
27dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.content.pm.PackageManager;
28dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.content.pm.ResolveInfo;
29cfc3086b18396df03f982fb98112649dc5b5a6f2Adam Powellimport android.os.Bundle;
3057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlockimport android.os.Handler;
31dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.os.RemoteException;
32dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlockimport android.os.SystemClock;
33dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.os.UserHandle;
34dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.provider.MediaStore;
35dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.util.Log;
36dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport android.view.WindowManager;
37dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
3814adfe425e67c9ec12b0841a62c5c03ce00838eaJohn Spurlockimport com.android.internal.policy.impl.keyguard.KeyguardHostView.OnDismissAction;
39dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport com.android.internal.widget.LockPatternUtils;
40dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
41dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockimport java.util.List;
42dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
43dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlockpublic abstract class KeyguardActivityLauncher {
44dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private static final String TAG = KeyguardActivityLauncher.class.getSimpleName();
45dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private static final boolean DEBUG = KeyguardHostView.DEBUG;
46dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
47dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private static final Intent SECURE_CAMERA_INTENT =
48dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
49dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                    .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
50dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private static final Intent INSECURE_CAMERA_INTENT =
51dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
52dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
53dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    abstract Context getContext();
54dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
55dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    abstract KeyguardSecurityCallback getCallback();
56dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
57dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    abstract LockPatternUtils getLockPatternUtils();
58dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
59dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    public static class CameraWidgetInfo {
60dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        public String contextPackage;
61dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        public int layoutId;
62dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    }
63dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
64dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    public CameraWidgetInfo getCameraWidgetInfo() {
65dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        CameraWidgetInfo info = new CameraWidgetInfo();
66dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        Intent intent = getCameraIntent();
67dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        PackageManager packageManager = getContext().getPackageManager();
68dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
69dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
70dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (appList.size() == 0) {
71dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Nothing found");
72dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            return null;
73dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        }
74dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
75dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
76dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                getLockPatternUtils().getCurrentUser());
77dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): resolved: " + resolved);
78dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (wouldLaunchResolverActivity(resolved, appList)) {
79dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Would launch resolver");
80dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            return info;
81dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        }
82dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (resolved == null || resolved.activityInfo == null) {
83dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            return null;
84dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        }
85dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (resolved.activityInfo.metaData == null || resolved.activityInfo.metaData.isEmpty()) {
86dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no metadata found");
87dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            return info;
88dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        }
89dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        int layoutId = resolved.activityInfo.metaData.getInt(META_DATA_KEYGUARD_LAYOUT);
90dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (layoutId == 0) {
91dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no layout specified");
92dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            return info;
93dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        }
94dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        info.contextPackage = resolved.activityInfo.packageName;
95dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        info.layoutId = layoutId;
96dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        return info;
97dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    }
98dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
9957f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    public void launchCamera(Handler worker, Runnable onSecureCameraStarted) {
100dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        LockPatternUtils lockPatternUtils = getLockPatternUtils();
101dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (lockPatternUtils.isSecure()) {
102dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            // Launch the secure version of the camera
103dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            if (wouldLaunchResolverActivity(SECURE_CAMERA_INTENT)) {
104dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                // TODO: Show disambiguation dialog instead.
105dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                // For now, we'll treat this like launching any other app from secure keyguard.
106dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                // When they do, user sees the system's ResolverActivity which lets them choose
107dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                // which secure camera to use.
10857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                launchActivity(SECURE_CAMERA_INTENT, false, false, null, null);
109dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            } else {
11057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                launchActivity(SECURE_CAMERA_INTENT, true, false, worker, onSecureCameraStarted);
111dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            }
112dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        } else {
113dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            // Launch the normal camera
11457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            launchActivity(INSECURE_CAMERA_INTENT, false, false, null, null);
115dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        }
116dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    }
117dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
11865cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock    public void launchWidgetPicker(int appWidgetId) {
11965cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
12065cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock
12165cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
12265cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false);
12365cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
12465cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock                AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
12565cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock
12665cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        Bundle options = new Bundle();
12765cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
12865cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock                AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
12965cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
13065cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        pickIntent.addFlags(
13165cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock                Intent.FLAG_ACTIVITY_NEW_TASK
13265cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock                | Intent.FLAG_ACTIVITY_SINGLE_TOP
13365cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock                | Intent.FLAG_ACTIVITY_CLEAR_TOP
13465cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
13565cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock
13665cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        launchActivity(pickIntent, false, false, null, null);
13765cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock    }
13865cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock
139dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    /**
140dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock     * Launches the said intent for the current foreground user.
14157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock     *
142dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock     * @param intent
143dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock     * @param showsWhileLocked true if the activity can be run on top of keyguard.
14457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock     *   See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED}
14557f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock     * @param useDefaultAnimations true if default transitions should be used, else suppressed.
14657f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock     * @param worker if supplied along with onStarted, used to launch the blocking activity call.
14757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock     * @param onStarted if supplied along with worker, called after activity is started.
148dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock     */
14957f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    public void launchActivity(final Intent intent,
15057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            boolean showsWhileLocked,
15157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            boolean useDefaultAnimations,
15257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            final Handler worker,
15357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            final Runnable onStarted) {
1546ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler
155dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        final Context context = getContext();
15665cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock        final Bundle animation = useDefaultAnimations ? null
15765cbcbea8a88a14dd9a001d23d09f0a02b0b3805John Spurlock                : ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle();
1586ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler        launchActivityWithAnimation(intent, showsWhileLocked, animation, worker, onStarted);
1596ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler    }
1606ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler
1616ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler    public void launchActivityWithAnimation(final Intent intent,
1626ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler            boolean showsWhileLocked,
1636ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler            final Bundle animation,
1646ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler            final Handler worker,
1656ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler            final Runnable onStarted) {
1666ed3fcafdbdeda9a10a62bbd0e5997017e8e2635Daniel Sandler
167dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        LockPatternUtils lockPatternUtils = getLockPatternUtils();
168dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        intent.addFlags(
169dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                Intent.FLAG_ACTIVITY_NEW_TASK
170dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                | Intent.FLAG_ACTIVITY_SINGLE_TOP
171dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
172dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        boolean isSecure = lockPatternUtils.isSecure();
173dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        if (!isSecure || showsWhileLocked) {
17434c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock            if (!isSecure) {
17534c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock                dismissKeyguardOnNextActivity();
176dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            }
177dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            try {
178dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock                if (DEBUG) Log.d(TAG, String.format("Starting activity for intent %s at %s",
179dbe24b7def8df3a539790827d3f395f4d933802bJohn Spurlock                        intent, SystemClock.uptimeMillis()));
18057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                startActivityForCurrentUser(intent, animation, worker, onStarted);
181dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            } catch (ActivityNotFoundException e) {
182dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                Log.w(TAG, "Activity not found for intent + " + intent.getAction());
183dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            }
184dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        } else {
185dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            // Create a runnable to start the activity and ask the user to enter their
186dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            // credentials.
187dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            KeyguardSecurityCallback callback = getCallback();
18834c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock            callback.setOnDismissAction(new OnDismissAction() {
189dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                @Override
19034c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock                public boolean onDismiss() {
19134c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock                    dismissKeyguardOnNextActivity();
19257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                    startActivityForCurrentUser(intent, animation, worker, onStarted);
19334c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock                    return true;
194dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                }
195dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            });
196dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            callback.dismiss(false);
197dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        }
198dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    }
199dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
20034c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock    private void dismissKeyguardOnNextActivity() {
20134c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock        try {
20234c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock            ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
20334c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock        } catch (RemoteException e) {
20434c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock            Log.w(TAG, "can't dismiss keyguard on launch");
20534c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock        }
20634c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock    }
20734c4fe523ad96fb59cec28832b38806d04a6bebfJohn Spurlock
20857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    private void startActivityForCurrentUser(final Intent intent, final Bundle options,
20957f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            Handler worker, final Runnable onStarted) {
21057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        final UserHandle user = new UserHandle(UserHandle.USER_CURRENT);
21157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        if (worker == null || onStarted == null) {
21257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            getContext().startActivityAsUser(intent, options, user);
21357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            return;
21457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        }
21557f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        // if worker + onStarted are supplied, run blocking activity launch call in the background
21657f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock        worker.post(new Runnable(){
21757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            @Override
21857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            public void run() {
21957f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                try {
22057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                    WaitResult result = ActivityManagerNative.getDefault().startActivityAndWait(
22157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            null /*caller*/,
22257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            intent,
22357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            intent.resolveTypeIfNeeded(getContext().getContentResolver()),
22457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            null /*resultTo*/,
22557f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            null /*resultWho*/,
22657f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            0 /*requestCode*/,
22757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            Intent.FLAG_ACTIVITY_NEW_TASK,
22857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            null /*profileFile*/,
22957f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            null /*profileFd*/,
23057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            options,
23157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            user.getIdentifier());
23257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                    if (DEBUG) Log.d(TAG, String.format("waitResult[%s,%s,%s,%s] at %s",
23357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            result.result, result.thisTime, result.totalTime, result.who,
23457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                            SystemClock.uptimeMillis()));
23557f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                } catch (RemoteException e) {
23657f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                    Log.w(TAG, "Error starting activity", e);
23757f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                    return;
23857f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                }
23957f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                try {
24057f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                    onStarted.run();
24157f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                } catch (Throwable t) {
24257f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                    Log.w(TAG, "Error running onStarted callback", t);
24357f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock                }
24457f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock            }});
24557f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock    }
24657f928fc4afc02d2fe45523efea687eee7f86c02John Spurlock
247dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private Intent getCameraIntent() {
248dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        return getLockPatternUtils().isSecure() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
249dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    }
250dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
251dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private boolean wouldLaunchResolverActivity(Intent intent) {
252dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        PackageManager packageManager = getContext().getPackageManager();
253dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
254dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
255dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
256dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
257dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        return wouldLaunchResolverActivity(resolved, appList);
258dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    }
259dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock
260dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
261dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        // If the list contains the above resolved activity, then it can't be
262dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        // ResolverActivity itself.
263dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        for (int i = 0; i < appList.size(); i++) {
264dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            ResolveInfo tmp = appList.get(i);
265dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
266dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                    && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
267dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock                return false;
268dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock            }
269dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        }
270dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock        return true;
271dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock    }
272dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4bJohn Spurlock}
273