1b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi/* 2b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * Copyright (C) 2014 The Android Open Source Project 3b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * 4b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 5b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * you may not use this file except in compliance with the License. 6b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * You may obtain a copy of the License at 7b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * 8b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 9b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * 10b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * Unless required by applicable law or agreed to in writing, software 11b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 12b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * See the License for the specific language governing permissions and 14b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * limitations under the License 15b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi */ 16b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 17b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggipackage com.android.systemui.statusbar.policy; 18b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 19a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggiimport android.content.ComponentName; 20b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport android.content.Context; 21b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport android.content.Intent; 22d944986fbdb3d45fab9ae4120af76ca4f6b0909cJorim Jaggiimport android.content.pm.ActivityInfo; 23b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport android.content.pm.PackageManager; 24b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport android.content.pm.ResolveInfo; 25e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinekimport android.os.Bundle; 26b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport android.util.Log; 27b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport android.view.LayoutInflater; 28b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport android.view.View; 29b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 30b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport com.android.internal.widget.LockPatternUtils; 31d6aa6cb0cc8c70a30434048e25e14643b1645755Adrian Roosimport com.android.keyguard.KeyguardUpdateMonitor; 32b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport com.android.systemui.statusbar.phone.KeyguardPreviewContainer; 33b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 34b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggiimport java.util.List; 35b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 36b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi/** 37b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi * Utility class to inflate previews for phone and camera affordance. 38b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi */ 39b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggipublic class PreviewInflater { 40b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 41b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi private static final String TAG = "PreviewInflater"; 42b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 43b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout"; 44b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 45b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi private Context mContext; 46b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi private LockPatternUtils mLockPatternUtils; 47b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 48b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi public PreviewInflater(Context context, LockPatternUtils lockPatternUtils) { 49b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi mContext = context; 50b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi mLockPatternUtils = lockPatternUtils; 51b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 52b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 53b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi public View inflatePreview(Intent intent) { 54b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi WidgetInfo info = getWidgetInfo(intent); 55e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek return inflatePreview(info); 56e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek } 57e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek 58e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek public View inflatePreviewFromService(ComponentName componentName) { 59e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek WidgetInfo info = getWidgetInfoFromService(componentName); 60e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek return inflatePreview(info); 61e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek } 62e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek 63e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek private KeyguardPreviewContainer inflatePreview(WidgetInfo info) { 64b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi if (info == null) { 65b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi return null; 66b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 67b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi View v = inflateWidgetView(info); 68b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi if (v == null) { 69b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi return null; 70b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 71b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi KeyguardPreviewContainer container = new KeyguardPreviewContainer(mContext, null); 72b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi container.addView(v); 73b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi return container; 74b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 75b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 76b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi private View inflateWidgetView(WidgetInfo widgetInfo) { 77b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi View widgetView = null; 78b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi try { 79b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi Context appContext = mContext.createPackageContext( 80b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi widgetInfo.contextPackage, Context.CONTEXT_RESTRICTED); 81b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi LayoutInflater appInflater = (LayoutInflater) 82b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi appContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 83b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi appInflater = appInflater.cloneInContext(appContext); 84b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi widgetView = appInflater.inflate(widgetInfo.layoutId, null, false); 85b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } catch (PackageManager.NameNotFoundException|RuntimeException e) { 86b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi Log.w(TAG, "Error creating widget view", e); 87b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 88b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi return widgetView; 89b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 90b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 91e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek private WidgetInfo getWidgetInfoFromService(ComponentName componentName) { 92e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek PackageManager packageManager = mContext.getPackageManager(); 93e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek // Look for the preview specified in the service meta-data 94e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek try { 95e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek Bundle metaData = packageManager.getServiceInfo( 96e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek componentName, PackageManager.GET_META_DATA).metaData; 97e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek return getWidgetInfoFromMetaData(componentName.getPackageName(), metaData); 98e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek } catch (PackageManager.NameNotFoundException e) { 99e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek Log.w(TAG, "Failed to load preview; " + componentName.flattenToShortString() 100e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek + " not found", e); 101e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek } 102e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek return null; 103e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek } 104e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek 105e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek private WidgetInfo getWidgetInfoFromMetaData(String contextPackage, 106e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek Bundle metaData) { 107e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek if (metaData == null) { 108e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek return null; 109e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek } 110e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek int layoutId = metaData.getInt(META_DATA_KEYGUARD_LAYOUT); 111e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek if (layoutId == 0) { 112e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek return null; 113e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek } 114b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi WidgetInfo info = new WidgetInfo(); 115e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek info.contextPackage = contextPackage; 116e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek info.layoutId = layoutId; 117e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek return info; 118e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek } 119e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek 120e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek private WidgetInfo getWidgetInfo(Intent intent) { 121b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi PackageManager packageManager = mContext.getPackageManager(); 1225f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek int flags = PackageManager.MATCH_DEFAULT_ONLY 1235f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek | PackageManager.MATCH_DIRECT_BOOT_AWARE 1245f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; 125b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser( 1265f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek intent, flags, KeyguardUpdateMonitor.getCurrentUser()); 127b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi if (appList.size() == 0) { 128b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi return null; 129b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 130b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, 1315f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek flags | PackageManager.GET_META_DATA, 132d6aa6cb0cc8c70a30434048e25e14643b1645755Adrian Roos KeyguardUpdateMonitor.getCurrentUser()); 133b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi if (wouldLaunchResolverActivity(resolved, appList)) { 134b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi return null; 135b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 136b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi if (resolved == null || resolved.activityInfo == null) { 137b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi return null; 138b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 139e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek return getWidgetInfoFromMetaData(resolved.activityInfo.packageName, 140e70d6535237d2e6f03adcd0bdc11e45ea714dc97Selim Cinek resolved.activityInfo.metaData); 141b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 142b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 14385dc23cc696d4c5de4619da317c16c5a2b49a62aJorim Jaggi public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent, 14485dc23cc696d4c5de4619da317c16c5a2b49a62aJorim Jaggi int currentUserId) { 1455f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek return getTargetActivityInfo(ctx, intent, currentUserId, false /* onlyDirectBootAware */) 1465f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek == null; 147a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggi } 148a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggi 149a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggi /** 1505f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must 1515f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek * be direct boot aware when in direct boot mode if false, all 1525f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek * packages are considered a match even if they are not aware. 153d944986fbdb3d45fab9ae4120af76ca4f6b0909cJorim Jaggi * @return the target activity info of the intent it resolves to a specific package or 154d944986fbdb3d45fab9ae4120af76ca4f6b0909cJorim Jaggi * {@code null} if it resolved to the resolver activity 155a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggi */ 156d944986fbdb3d45fab9ae4120af76ca4f6b0909cJorim Jaggi public static ActivityInfo getTargetActivityInfo(Context ctx, Intent intent, 1575f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek int currentUserId, boolean onlyDirectBootAware) { 15885dc23cc696d4c5de4619da317c16c5a2b49a62aJorim Jaggi PackageManager packageManager = ctx.getPackageManager(); 1595f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek int flags = PackageManager.MATCH_DEFAULT_ONLY; 1605f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek if (!onlyDirectBootAware) { 1615f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE 1625f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; 1635f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek } 164781c29c9a866dbf0a01d76838e912a5fec9247feJorim Jaggi final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser( 1655f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek intent, flags, currentUserId); 166781c29c9a866dbf0a01d76838e912a5fec9247feJorim Jaggi if (appList.size() == 0) { 167a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggi return null; 168781c29c9a866dbf0a01d76838e912a5fec9247feJorim Jaggi } 169781c29c9a866dbf0a01d76838e912a5fec9247feJorim Jaggi ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, 1705f1450229bb8a827c4e6d4ed6dbc2de6e31aabffSelim Cinek flags | PackageManager.GET_META_DATA, currentUserId); 171a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggi if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) { 172a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggi return null; 173a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggi } else { 174d944986fbdb3d45fab9ae4120af76ca4f6b0909cJorim Jaggi return resolved.activityInfo; 175a86790bf23a98ede5fc0c29b996a5229e08181cdJorim Jaggi } 176781c29c9a866dbf0a01d76838e912a5fec9247feJorim Jaggi } 177781c29c9a866dbf0a01d76838e912a5fec9247feJorim Jaggi 17885dc23cc696d4c5de4619da317c16c5a2b49a62aJorim Jaggi private static boolean wouldLaunchResolverActivity( 17985dc23cc696d4c5de4619da317c16c5a2b49a62aJorim Jaggi ResolveInfo resolved, List<ResolveInfo> appList) { 180b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi // If the list contains the above resolved activity, then it can't be 181b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi // ResolverActivity itself. 182b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi for (int i = 0; i < appList.size(); i++) { 183b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi ResolveInfo tmp = appList.get(i); 184b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi if (tmp.activityInfo.name.equals(resolved.activityInfo.name) 185b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) { 186b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi return false; 187b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 188b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 189b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi return true; 190b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 191b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi 192b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi private static class WidgetInfo { 193b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi String contextPackage; 194b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi int layoutId; 195b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi } 196b6cdcbc66b4b862f83afde85b8e7109b6450b15eJorim Jaggi} 197