• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.cts.verifier.managedprovisioning;
18 
19 import android.app.DownloadManager;
20 import android.app.admin.DevicePolicyManager;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.ActivityInfo;
24 import android.content.pm.PackageManager;
25 import android.content.pm.ResolveInfo;
26 import android.media.audiofx.AudioEffect;
27 import android.net.Uri;
28 import android.nfc.cardemulation.CardEmulation;
29 import android.os.Build;
30 import android.os.Environment;
31 import android.os.UserManager;
32 import android.provider.AlarmClock;
33 import android.provider.CalendarContract.Events;
34 import android.provider.MediaStore;
35 import android.provider.Settings;
36 import android.util.Log;
37 
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.List;
41 
42 /**
43  * Helper class for testing if the required cross profile intent filters are set during the
44  * managed provisioning.
45  */
46 public class IntentFiltersTestHelper {
47 
48     private static final String TAG = "IntentFiltersTestHelper";
49 
50     // These are the intents which can be forwarded to the managed profile.
51     private static final ArrayList<Intent> forwardedIntentsFromPrimary =
52             new ArrayList<>(Arrays.asList(
53                 new Intent(Intent.ACTION_SEND).setType("*/*"),
54                 new Intent(Intent.ACTION_SEND_MULTIPLE).setType("*/*")
55             ));
56 
57     // These are the intents which can be forwarded to the primary profile.
58     private static final ArrayList<Intent> forwardedIntentsFromManaged =
59             new ArrayList<>(Arrays.asList(
60                 new Intent(AlarmClock.ACTION_SET_ALARM),
61                 new Intent(AlarmClock.ACTION_SET_TIMER),
62                 new Intent(AlarmClock.ACTION_SHOW_ALARMS),
63                 new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS),
64                 new Intent(Settings.ACTION_CAPTIONING_SETTINGS),
65                 new Intent(Settings.ACTION_DATE_SETTINGS),
66                 new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS),
67                 new Intent(Settings.ACTION_DISPLAY_SETTINGS),
68                 new Intent(Settings.ACTION_LOCALE_SETTINGS),
69                 new Intent(Settings.ACTION_PRIVACY_SETTINGS),
70                 new Intent(Settings.ACTION_SETTINGS),
71                 new Intent(Settings.ACTION_WIRELESS_SETTINGS),
72                 new Intent("android.net.vpn.SETTINGS"),
73                 new Intent(Settings.ACTION_VPN_SETTINGS),
74                 new Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS),
75                 new Intent("android.settings.LICENSE"),
76                 new Intent("android.settings.NOTIFICATION_SETTINGS"),
77                 new Intent("android.settings.ZEN_MODE_SETTINGS"),
78                 new Intent("com.android.settings.ACCESSIBILITY_COLOR_SPACE_SETTINGS"),
79                 new Intent("com.android.settings.TTS_SETTINGS"),
80                 new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS),
81                 new Intent(Intent.ACTION_GET_CONTENT).setType("*/*").addCategory(
82                         Intent.CATEGORY_OPENABLE),
83                 new Intent(Intent.ACTION_OPEN_DOCUMENT).setType("*/*").addCategory(
84                         Intent.CATEGORY_OPENABLE)
85             ));
86 
87     // These are the intents which can either be handled directly in the managed profile,
88     // or be forwarded to the primary profile.
89     private static final ArrayList<Intent> forwardingOptionalIntentsFromManaged =
90             new ArrayList<>(Arrays.asList(
91                 new Intent(Settings.ACTION_SYNC_SETTINGS),
92                 new Intent(Settings.ACTION_ADD_ACCOUNT),
93                 new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS),
94                 new Intent(Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS),
95                 new Intent(Settings.ACTION_APPLICATION_SETTINGS),
96                 new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD),
97                 new Intent("android.settings.ACCOUNT_SYNC_SETTINGS")
98             ));
99 
100     // These are the intents which cannot be forwarded to the primary profile.
101     private static final ArrayList<Intent> notForwardedIntentsFromManaged =
102             new ArrayList<>(Arrays.asList(
103                 new Intent(Intent.ACTION_INSERT).setData(
104                         Uri.parse("content://browser/bookmarks")),
105                 new Intent(Intent.ACTION_VIEW).setData(
106                         Uri.parse("http://www.example.com")).addCategory(
107                         Intent.CATEGORY_BROWSABLE),
108                 new Intent(Intent.ACTION_SENDTO).setData(
109                         Uri.parse("mailto:user@example.com")),
110                 new Intent(Intent.ACTION_VIEW).setData(
111                         Uri.parse("mailto:user@example.com")).addCategory(
112                         Intent.CATEGORY_BROWSABLE),
113                 new Intent(Intent.ACTION_VIEW).setData(
114                         Uri.parse("geo:0,0?q=BuckinghamPalace")),
115                 new Intent(Intent.ACTION_VIEW).setData(
116                         Uri.parse("http://example.com/oceans.mp4")).setType("video/mp4"),
117                 new Intent(Intent.ACTION_VIEW).setData(
118                         Uri.parse("http://www.example.com/horse.mp3")).setType("audio/*"),
119                 new Intent(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH),
120                 new Intent(Intent.ACTION_VIEW).setData(
121                         Uri.parse("market://details?id=com.android.chrome")).addCategory(
122                         Intent.CATEGORY_BROWSABLE),
123                 new Intent(Intent.ACTION_WEB_SEARCH),
124                 new Intent(Settings.ACTION_SEARCH_SETTINGS),
125                 new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE),
126                 new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(
127                         Uri.parse("package:com.android.chrome")),
128                 new Intent(Intent.ACTION_INSERT).setData(Events.CONTENT_URI),
129                 new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
130             ));
131 
132     // This flag specifies we are dealing with intents fired from the primary profile.
133     public static final int FLAG_INTENTS_FROM_PRIMARY = 1;
134     // This flag specifies we are dealing with intents fired from the managed profile.
135     public static final int FLAG_INTENTS_FROM_MANAGED = 2;
136 
137     private Context mContext;
138 
IntentFiltersTestHelper(Context context)139     IntentFiltersTestHelper(Context context) {
140         mContext = context;
141 
142         addIntentsThatDependOnDeviceConfigs();
143         addIntentsThatDependOnDeviceFeatures();
144     }
145 
addIntentsThatDependOnDeviceConfigs()146     private void addIntentsThatDependOnDeviceConfigs() {
147         if (UserManager.supportsMultipleUsers()) {
148             forwardedIntentsFromManaged.add(
149                     new Intent("android.settings.USER_SETTINGS"));
150         }
151     }
152 
addIntentsThatDependOnDeviceFeatures()153     private void addIntentsThatDependOnDeviceFeatures() {
154         PackageManager pm = mContext.getPackageManager();
155 
156         if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
157                 && pm.hasSystemFeature(PackageManager.FEATURE_TELECOM)) {
158             forwardedIntentsFromManaged.addAll(Arrays.asList(
159                     new Intent("android.intent.action.CALL_EMERGENCY").setData(
160                             Uri.parse("tel:123")),
161                     new Intent("android.intent.action.CALL_PRIVILEGED").setData(
162                             Uri.parse("tel:123")),
163                     new Intent(Intent.ACTION_VIEW).setData(Uri.parse("tel:123")).addCategory(
164                             Intent.CATEGORY_BROWSABLE),
165                     new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS),
166                     new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS),
167                     new Intent(Intent.ACTION_SENDTO).setData(Uri.parse("sms:07700900100")),
168                     new Intent(Intent.ACTION_SENDTO).setData(Uri.parse("smsto:07700900100")),
169                     new Intent(Intent.ACTION_SENDTO).setData(Uri.parse("mms:07700900100")),
170                     new Intent(Intent.ACTION_SENDTO).setData(Uri.parse("mmsto:07700900100")),
171                     new Intent(Intent.ACTION_VIEW).setData(
172                             Uri.parse("sms:07700900100?body=Hello%20world")).addCategory(
173                             Intent.CATEGORY_BROWSABLE),
174                     new Intent(Intent.ACTION_VIEW).setData(
175                             Uri.parse("smsto:07700900100?body=Hello%20world")).addCategory(
176                             Intent.CATEGORY_BROWSABLE),
177                     new Intent(Intent.ACTION_VIEW).setData(
178                             Uri.parse("mms:07700900100?body=Hello%20world")).addCategory(
179                             Intent.CATEGORY_BROWSABLE),
180                     new Intent(Intent.ACTION_VIEW).setData(
181                             Uri.parse("mmsto:07700900100?body=Hello%20world")).addCategory(
182                             Intent.CATEGORY_BROWSABLE),
183                     new Intent(Settings.ACTION_APN_SETTINGS)));
184             notForwardedIntentsFromManaged.addAll(Arrays.asList(
185                     new Intent(Intent.ACTION_DIAL).setData(Uri.parse("tel:123")),
186                     new Intent(Intent.ACTION_CALL).setData(Uri.parse("tel:123"))));
187         }
188 
189         if (pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
190             forwardedIntentsFromManaged.addAll(Arrays.asList(
191                     new Intent(Settings.ACTION_NFC_SETTINGS),
192                     new Intent(Settings.ACTION_NFCSHARING_SETTINGS)));
193         }
194 
195         if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
196             forwardedIntentsFromManaged.addAll(Arrays.asList(
197                     new Intent(CardEmulation.ACTION_CHANGE_DEFAULT),
198                     new Intent(Settings.ACTION_NFC_PAYMENT_SETTINGS)));
199         }
200 
201         if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
202             forwardingOptionalIntentsFromManaged.addAll(Arrays.asList(
203                     new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
204                     new Intent(MediaStore.ACTION_VIDEO_CAPTURE),
205                     new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA),
206                     new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA),
207                     new Intent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE),
208                     new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)));
209         }
210 
211         final String state = Environment.getExternalStorageState();
212         if (Environment.MEDIA_MOUNTED.equals(state)) {
213             forwardedIntentsFromManaged.add(
214                     new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS));
215         }
216 
217         if (pm.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
218             forwardedIntentsFromManaged.addAll(Arrays.asList(
219                     new Intent(Settings.ACTION_WIFI_IP_SETTINGS),
220                     new Intent(Settings.ACTION_WIFI_SETTINGS)));
221         }
222 
223         if (pm.hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
224             forwardingOptionalIntentsFromManaged.add(
225                     new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION));
226         }
227 
228         if (pm.hasSystemFeature(PackageManager.FEATURE_LOCATION)) {
229             forwardingOptionalIntentsFromManaged.add(
230                     new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
231         }
232 
233         if (pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
234             forwardedIntentsFromManaged.addAll(Arrays.asList(
235                     new Intent(Settings.ACTION_SOUND_SETTINGS),
236                     new Intent("android.settings.ACTION_OTHER_SOUND_SETTINGS")));
237             notForwardedIntentsFromManaged.add(
238                     new Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL));
239         }
240 
241         if (pm.hasSystemFeature(PackageManager.FEATURE_HOME_SCREEN)) {
242             forwardingOptionalIntentsFromManaged.add(
243                     new Intent(Settings.ACTION_HOME_SETTINGS));
244         }
245 
246         if (pm.hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS)) {
247             notForwardedIntentsFromManaged.addAll(Arrays.asList(
248                     new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS),
249                     new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS)));
250         }
251 
252         if (!pm.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
253             forwardedIntentsFromManaged.add(
254                     new Intent(Settings.ACTION_DREAM_SETTINGS));
255         }
256 
257         if (!pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
258             forwardedIntentsFromManaged.add(
259                     new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS));
260         }
261 
262         if (pm.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
263             notForwardedIntentsFromManaged.add(
264                     new Intent(Settings.ACTION_PRINT_SETTINGS));
265         }
266 
267         if (Build.TYPE.equals("user")) {
268             forwardedIntentsFromManaged.add(
269                     new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
270         }
271     }
272 
checkCrossProfileIntentFilters(int flag)273     public boolean checkCrossProfileIntentFilters(int flag) {
274         boolean crossProfileIntentFiltersSet;
275         if (flag == FLAG_INTENTS_FROM_PRIMARY) {
276             crossProfileIntentFiltersSet = checkIntentForwardingFromPrimary();
277         } else {
278             crossProfileIntentFiltersSet =
279                     checkIntentForwardingFromManaged() &&
280                             checkIntentsWithOptionalForwardingFromManagedAreHandled();
281         }
282         return crossProfileIntentFiltersSet;
283     }
284 
285     /**
286      * Checks if required cross profile intent filters are set for the intents fired from the
287      * primary profile.
288      */
checkIntentForwardingFromPrimary()289     private boolean checkIntentForwardingFromPrimary() {
290         // Get the class name of the intentForwarderActivity in the primary profile by firing an
291         // intent which we know will be forwarded from primary profile to managed profile.
292         ActivityInfo forwarderActivityInfo =
293                 getForwarderActivityInfo(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
294         if (forwarderActivityInfo == null) {
295             return false;
296         }
297 
298         // Check for intents which can be forwarded to the managed profile.
299         return checkIntentForwarding(forwardedIntentsFromPrimary,
300                 forwarderActivityInfo, "from primary profile should be forwarded to the " +
301                 "managed profile but is not.", true);
302     }
303 
304     /**
305      * Checks that the required intents either have cross profile intent filters set up, or are
306      * handled directly in the managed profile.
307      */
checkIntentsWithOptionalForwardingFromManagedAreHandled()308     private boolean checkIntentsWithOptionalForwardingFromManagedAreHandled() {
309         for (Intent intent : forwardingOptionalIntentsFromManaged) {
310             List<ResolveInfo> resolveInfoList =
311                     mContext.getPackageManager().queryIntentActivities(intent,
312                             PackageManager.MATCH_DEFAULT_ONLY);
313 
314             if (resolveInfoList.isEmpty()) {
315                 Log.e(TAG, intent + " should be handled in or forwarded from the managed " +
316                         "profile, but it is not.");
317                 return false;
318             }
319         }
320 
321         return true;
322     }
323 
324     /**
325      * Checks if required cross profile intent filters are set for the intents fired from the
326      * managed profile.
327      */
checkIntentForwardingFromManaged()328     private boolean checkIntentForwardingFromManaged() {
329         // Get the class name of the intentForwarderActivity in the managed profile by firing an
330         // intent which we know will be forwarded from managed profile to primary profile.
331         ActivityInfo forwarderActivityInfo =
332                 getForwarderActivityInfo(ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS);
333         if (forwarderActivityInfo == null) {
334             return false;
335         }
336 
337         boolean success = true;
338         // Check for intents which can be forwarded to the primary profile.
339         success &= checkIntentForwarding(forwardedIntentsFromManaged,
340                 forwarderActivityInfo, " from managed profile should be forwarded to the " +
341                 "primary profile but is not.", true);
342 
343         // Check for intents which cannot be forwarded to the primary profile.
344         success &= checkIntentForwarding(notForwardedIntentsFromManaged,
345                 forwarderActivityInfo, "from managed profile should not be forwarded to the " +
346                 "primary profile but it is.", false);
347         return success;
348     }
349 
350     /**
351      * Checks if the intentForwarderActivity can handle the intent passed.
352      */
canForwarderActivityHandleIntent(Intent intent, ActivityInfo forwarderActivityInfo)353     private boolean canForwarderActivityHandleIntent(Intent intent,
354             ActivityInfo forwarderActivityInfo) {
355         // Get all the activities which can handle the intent.
356         List<ResolveInfo> resolveInfoList =
357                 mContext.getPackageManager().queryIntentActivities(intent,
358                         PackageManager.MATCH_DEFAULT_ONLY);
359         // Check if intentForwarderActivity is part of the list.
360         for (ResolveInfo resolveInfo : resolveInfoList) {
361             if (forwarderActivityInfo.packageName.equals(resolveInfo.activityInfo.packageName)
362                     && forwarderActivityInfo.name.equals(resolveInfo.activityInfo.name)) {
363                 return true;
364             }
365         }
366         return false;
367     }
368 
369     /**
370      * Returns the class name of the intentForwarderActivity.
371      */
getForwarderActivityInfo(String action)372     private ActivityInfo getForwarderActivityInfo(String action) {
373         Intent intent = new Intent(action);
374         List<ResolveInfo> resolveInfoList =
375                 mContext.getPackageManager().queryIntentActivities(intent,
376                         PackageManager.MATCH_DEFAULT_ONLY);
377         if (resolveInfoList.isEmpty() || resolveInfoList.size() > 1) {
378             Log.d(TAG, "There should be exactly one activity IntentForwarder which " +
379                     "handles the intent " + intent);
380             return null;
381         }
382         return resolveInfoList.get(0).activityInfo;
383     }
384 
385     /**
386      * Checks if the intents passed are correctly handled.
387      * @return {@code false} if at least one intent is not handled correctly.
388      */
checkIntentForwarding(ArrayList<Intent> intentList, ActivityInfo expectedForwarderActivityInfo, String errorMessage, boolean canResolve)389     private boolean checkIntentForwarding(ArrayList<Intent> intentList,
390             ActivityInfo expectedForwarderActivityInfo, String errorMessage, boolean canResolve) {
391         boolean success = true;
392         for (Intent intent : intentList) {
393             if (canForwarderActivityHandleIntent(intent,
394                     expectedForwarderActivityInfo) != canResolve) {
395                 Log.e(TAG, intent + " " + errorMessage);
396                 success = false;
397             }
398         }
399         return success;
400     }
401 }
402