2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 package com.android.systemui.statusbar.policy;
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.ActivityInfo;
23 import android.content.pm.PackageManager;
24 import android.content.pm.ResolveInfo;
25 import android.os.Bundle;
26 import android.util.Log;
27 import android.view.LayoutInflater;
28 import android.view.View;
30 import com.android.internal.widget.LockPatternUtils;
31 import com.android.keyguard.KeyguardUpdateMonitor;
32 import com.android.systemui.statusbar.phone.KeyguardPreviewContainer;
34 import java.util.List;
37 * Utility class to inflate previews for phone and camera affordance.
39 public class PreviewInflater {
41 private static final String TAG = "PreviewInflater";
43 private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
45 private Context mContext;
46 private LockPatternUtils mLockPatternUtils;
48 public PreviewInflater(Context context, LockPatternUtils lockPatternUtils) {
50 mLockPatternUtils = lockPatternUtils;
53 public View inflatePreview(Intent intent) {
54 WidgetInfo info = getWidgetInfo(intent);
55 return inflatePreview(info);
58 public View inflatePreviewFromService(ComponentName componentName) {
59 WidgetInfo info = getWidgetInfoFromService(componentName);
60 return inflatePreview(info);
63 private KeyguardPreviewContainer inflatePreview(WidgetInfo info) {
67 View v = inflateWidgetView(info);
71 KeyguardPreviewContainer container = new KeyguardPreviewContainer(mContext, null);
76 private View inflateWidgetView(WidgetInfo widgetInfo) {
77 View widgetView = null;
79 Context appContext = mContext.createPackageContext(
80 widgetInfo.contextPackage, Context.CONTEXT_RESTRICTED);
81 LayoutInflater appInflater = (LayoutInflater)
82 appContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
83 appInflater = appInflater.cloneInContext(appContext);
84 widgetView = appInflater.inflate(widgetInfo.layoutId, null, false);
85 } catch (PackageManager.NameNotFoundException|RuntimeException e) {
86 Log.w(TAG, "Error creating widget view", e);
91 private WidgetInfo getWidgetInfoFromService(ComponentName componentName) {
92 PackageManager packageManager = mContext.getPackageManager();
93 // Look for the preview specified in the service meta-data
95 Bundle metaData = packageManager.getServiceInfo(
96 componentName, PackageManager.GET_META_DATA).metaData;
97 return getWidgetInfoFromMetaData(componentName.getPackageName(), metaData);
98 } catch (PackageManager.NameNotFoundException e) {
99 Log.w(TAG, "Failed to load preview; " + componentName.flattenToShortString()
105 private WidgetInfo getWidgetInfoFromMetaData(String contextPackage,
107 if (metaData == null) {
110 int layoutId = metaData.getInt(META_DATA_KEYGUARD_LAYOUT);
114 WidgetInfo info = new WidgetInfo();
115 info.contextPackage = contextPackage;
116 info.layoutId = layoutId;
120 private WidgetInfo getWidgetInfo(Intent intent) {
121 PackageManager packageManager = mContext.getPackageManager();
122 int flags = PackageManager.MATCH_DEFAULT_ONLY
123 | PackageManager.MATCH_DIRECT_BOOT_AWARE
124 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
125 final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
126 intent, flags, KeyguardUpdateMonitor.getCurrentUser());
127 if (appList.size() == 0) {
130 ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
131 flags | PackageManager.GET_META_DATA,
132 KeyguardUpdateMonitor.getCurrentUser());
133 if (wouldLaunchResolverActivity(resolved, appList)) {
136 if (resolved == null || resolved.activityInfo == null) {
139 return getWidgetInfoFromMetaData(resolved.activityInfo.packageName,
140 resolved.activityInfo.metaData);
143 public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
145 return getTargetActivityInfo(ctx, intent, currentUserId, false /* onlyDirectBootAware */)
150 * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must
151 * be direct boot aware when in direct boot mode if false, all
152 * packages are considered a match even if they are not aware.
153 * @return the target activity info of the intent it resolves to a specific package or
154 * {@code null} if it resolved to the resolver activity
156 public static ActivityInfo getTargetActivityInfo(Context ctx, Intent intent,
157 int currentUserId, boolean onlyDirectBootAware) {
158 PackageManager packageManager = ctx.getPackageManager();
159 int flags = PackageManager.MATCH_DEFAULT_ONLY;
160 if (!onlyDirectBootAware) {
161 flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
162 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
164 final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
165 intent, flags, currentUserId);
166 if (appList.size() == 0) {
169 ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
170 flags | PackageManager.GET_META_DATA, currentUserId);
171 if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
174 return resolved.activityInfo;
178 private static boolean wouldLaunchResolverActivity(
179 ResolveInfo resolved, List<ResolveInfo> appList) {
180 // If the list contains the above resolved activity, then it can't be
181 // ResolverActivity itself.
182 for (int i = 0; i < appList.size(); i++) {
183 ResolveInfo tmp = appList.get(i);
184 if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
185 && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
192 private static class WidgetInfo {
193 String contextPackage;