OSDN Git Service

DO NOT MERGE. Grant MMS Uri permissions as the calling UID.
[android-x86/frameworks-base.git] / packages / SystemUI / src / com / android / systemui / statusbar / policy / PreviewInflater.java
1 /*
2  * Copyright (C) 2014 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
17 package com.android.systemui.statusbar.policy;
18
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;
29
30 import com.android.internal.widget.LockPatternUtils;
31 import com.android.keyguard.KeyguardUpdateMonitor;
32 import com.android.systemui.statusbar.phone.KeyguardPreviewContainer;
33
34 import java.util.List;
35
36 /**
37  * Utility class to inflate previews for phone and camera affordance.
38  */
39 public class PreviewInflater {
40
41     private static final String TAG = "PreviewInflater";
42
43     private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
44
45     private Context mContext;
46     private LockPatternUtils mLockPatternUtils;
47
48     public PreviewInflater(Context context, LockPatternUtils lockPatternUtils) {
49         mContext = context;
50         mLockPatternUtils = lockPatternUtils;
51     }
52
53     public View inflatePreview(Intent intent) {
54         WidgetInfo info = getWidgetInfo(intent);
55         return inflatePreview(info);
56     }
57
58     public View inflatePreviewFromService(ComponentName componentName) {
59         WidgetInfo info = getWidgetInfoFromService(componentName);
60         return inflatePreview(info);
61     }
62
63     private KeyguardPreviewContainer inflatePreview(WidgetInfo info) {
64         if (info == null) {
65             return null;
66         }
67         View v = inflateWidgetView(info);
68         if (v == null) {
69             return null;
70         }
71         KeyguardPreviewContainer container = new KeyguardPreviewContainer(mContext, null);
72         container.addView(v);
73         return container;
74     }
75
76     private View inflateWidgetView(WidgetInfo widgetInfo) {
77         View widgetView = null;
78         try {
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);
87         }
88         return widgetView;
89     }
90
91     private WidgetInfo getWidgetInfoFromService(ComponentName componentName) {
92         PackageManager packageManager = mContext.getPackageManager();
93         // Look for the preview specified in the service meta-data
94         try {
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()
100                     + " not found", e);
101         }
102         return null;
103     }
104
105     private WidgetInfo getWidgetInfoFromMetaData(String contextPackage,
106             Bundle metaData) {
107         if (metaData == null) {
108             return null;
109         }
110         int layoutId = metaData.getInt(META_DATA_KEYGUARD_LAYOUT);
111         if (layoutId == 0) {
112             return null;
113         }
114         WidgetInfo info = new WidgetInfo();
115         info.contextPackage = contextPackage;
116         info.layoutId = layoutId;
117         return info;
118     }
119
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) {
128             return null;
129         }
130         ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
131                 flags | PackageManager.GET_META_DATA,
132                 KeyguardUpdateMonitor.getCurrentUser());
133         if (wouldLaunchResolverActivity(resolved, appList)) {
134             return null;
135         }
136         if (resolved == null || resolved.activityInfo == null) {
137             return null;
138         }
139         return getWidgetInfoFromMetaData(resolved.activityInfo.packageName,
140                 resolved.activityInfo.metaData);
141     }
142
143     public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
144             int currentUserId) {
145         return getTargetActivityInfo(ctx, intent, currentUserId, false /* onlyDirectBootAware */)
146                 == null;
147     }
148
149     /**
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
155      */
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;
163         }
164         final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
165                 intent, flags, currentUserId);
166         if (appList.size() == 0) {
167             return null;
168         }
169         ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
170                 flags | PackageManager.GET_META_DATA, currentUserId);
171         if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
172             return null;
173         } else {
174             return resolved.activityInfo;
175         }
176     }
177
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)) {
186                 return false;
187             }
188         }
189         return true;
190     }
191
192     private static class WidgetInfo {
193         String contextPackage;
194         int layoutId;
195     }
196 }