KeyguardActivityLauncher.java revision dcc9681b0d4f52e1f441ef2abdda3eb949cc0c4b
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.policy.impl.keyguard; 18 19import android.app.ActivityManagerNative; 20import android.content.ActivityNotFoundException; 21import android.content.Context; 22import android.content.Intent; 23import android.content.pm.PackageManager; 24import android.content.pm.ResolveInfo; 25import android.os.RemoteException; 26import android.os.UserHandle; 27import android.provider.MediaStore; 28import android.util.Log; 29import android.view.WindowManager; 30 31import com.android.internal.widget.LockPatternUtils; 32 33import java.util.List; 34 35public abstract class KeyguardActivityLauncher { 36 private static final String TAG = KeyguardActivityLauncher.class.getSimpleName(); 37 private static final boolean DEBUG = KeyguardHostView.DEBUG; 38 private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout"; 39 private static final Intent SECURE_CAMERA_INTENT = 40 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE) 41 .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 42 private static final Intent INSECURE_CAMERA_INTENT = 43 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 44 45 abstract Context getContext(); 46 47 abstract KeyguardSecurityCallback getCallback(); 48 49 abstract LockPatternUtils getLockPatternUtils(); 50 51 public static class CameraWidgetInfo { 52 public String contextPackage; 53 public int layoutId; 54 } 55 56 public CameraWidgetInfo getCameraWidgetInfo() { 57 CameraWidgetInfo info = new CameraWidgetInfo(); 58 Intent intent = getCameraIntent(); 59 PackageManager packageManager = getContext().getPackageManager(); 60 final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser( 61 intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser()); 62 if (appList.size() == 0) { 63 if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Nothing found"); 64 return null; 65 } 66 ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, 67 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 68 getLockPatternUtils().getCurrentUser()); 69 if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): resolved: " + resolved); 70 if (wouldLaunchResolverActivity(resolved, appList)) { 71 if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Would launch resolver"); 72 return info; 73 } 74 if (resolved == null || resolved.activityInfo == null) { 75 return null; 76 } 77 if (resolved.activityInfo.metaData == null || resolved.activityInfo.metaData.isEmpty()) { 78 if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no metadata found"); 79 return info; 80 } 81 int layoutId = resolved.activityInfo.metaData.getInt(META_DATA_KEYGUARD_LAYOUT); 82 if (layoutId == 0) { 83 if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no layout specified"); 84 return info; 85 } 86 info.contextPackage = resolved.activityInfo.packageName; 87 info.layoutId = layoutId; 88 return info; 89 } 90 91 public void launchCamera() { 92 LockPatternUtils lockPatternUtils = getLockPatternUtils(); 93 if (lockPatternUtils.isSecure()) { 94 // Launch the secure version of the camera 95 if (wouldLaunchResolverActivity(SECURE_CAMERA_INTENT)) { 96 // TODO: Show disambiguation dialog instead. 97 // For now, we'll treat this like launching any other app from secure keyguard. 98 // When they do, user sees the system's ResolverActivity which lets them choose 99 // which secure camera to use. 100 launchActivity(SECURE_CAMERA_INTENT, false); 101 } else { 102 launchActivity(SECURE_CAMERA_INTENT, true); 103 } 104 } else { 105// wouldLaunchResolverActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA)); 106 // Launch the normal camera 107 launchActivity(INSECURE_CAMERA_INTENT, false); 108 } 109 } 110 111 /** 112 * Launches the said intent for the current foreground user. 113 * @param intent 114 * @param showsWhileLocked true if the activity can be run on top of keyguard. 115 * See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED} 116 */ 117 public void launchActivity(final Intent intent, boolean showsWhileLocked) { 118 final Context context = getContext(); 119 LockPatternUtils lockPatternUtils = getLockPatternUtils(); 120 intent.addFlags( 121 Intent.FLAG_ACTIVITY_NEW_TASK 122 | Intent.FLAG_ACTIVITY_SINGLE_TOP 123 | Intent.FLAG_ACTIVITY_CLEAR_TOP); 124 boolean isSecure = lockPatternUtils.isSecure(); 125 if (!isSecure || showsWhileLocked) { 126 if (!isSecure) try { 127 ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); 128 } catch (RemoteException e) { 129 Log.w(TAG, "can't dismiss keyguard on launch"); 130 } 131 try { 132 context.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 133 } catch (ActivityNotFoundException e) { 134 Log.w(TAG, "Activity not found for intent + " + intent.getAction()); 135 } 136 } else { 137 // Create a runnable to start the activity and ask the user to enter their 138 // credentials. 139 KeyguardSecurityCallback callback = getCallback(); 140 callback.setOnDismissRunnable(new Runnable() { 141 @Override 142 public void run() { 143 context.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 144 } 145 }); 146 callback.dismiss(false); 147 } 148 } 149 150 private Intent getCameraIntent() { 151 return getLockPatternUtils().isSecure() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT; 152 } 153 154 private boolean wouldLaunchResolverActivity(Intent intent) { 155 PackageManager packageManager = getContext().getPackageManager(); 156 ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, 157 PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser()); 158 List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser( 159 intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser()); 160 return wouldLaunchResolverActivity(resolved, appList); 161 } 162 163 private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) { 164 // If the list contains the above resolved activity, then it can't be 165 // ResolverActivity itself. 166 for (int i = 0; i < appList.size(); i++) { 167 ResolveInfo tmp = appList.get(i); 168 if (tmp.activityInfo.name.equals(resolved.activityInfo.name) 169 && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) { 170 return false; 171 } 172 } 173 return true; 174 } 175} 176