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.Activity; 20 import android.app.admin.DevicePolicyManager; 21 import android.app.DownloadManager; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.ActivityInfo; 26 import android.content.pm.PackageInfo; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.media.audiofx.AudioEffect; 30 import android.net.Uri; 31 import android.nfc.cardemulation.CardEmulation; 32 import android.os.Bundle; 33 import android.os.UserHandle; 34 import android.provider.AlarmClock; 35 import android.provider.CalendarContract.Events; 36 import android.provider.MediaStore; 37 import android.provider.Settings; 38 import android.speech.RecognizerIntent; 39 import android.util.Log; 40 import android.widget.Toast; 41 42 import java.util.ArrayList; 43 import java.util.List; 44 45 /** 46 * Helper class for testing if the required cross profile intent filters are set during the 47 * managed provisioning. 48 */ 49 public class IntentFiltersTestHelper { 50 51 private static final String TAG = "IntentFiltersTestHelper"; 52 53 // These are the intents which can be forwarded to the managed profile. 54 private static final Intent[] forwardedIntentsFromPrimary = new Intent[] { 55 new Intent(Intent.ACTION_SEND).setType("*/*"), 56 new Intent(Intent.ACTION_SEND_MULTIPLE).setType("*/*") 57 }; 58 59 // These are the intents which can be forwarded to the primary profile. 60 private static final Intent[] forwardedIntentsFromManaged = new Intent[] { 61 new Intent(AlarmClock.ACTION_SET_ALARM), 62 new Intent(AlarmClock.ACTION_SET_TIMER), 63 new Intent(AlarmClock.ACTION_SHOW_ALARMS), 64 new Intent(MediaStore.ACTION_IMAGE_CAPTURE), 65 new Intent(MediaStore.ACTION_VIDEO_CAPTURE), 66 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA), 67 new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA), 68 new Intent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE), 69 new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE), 70 new Intent(Intent.ACTION_SENDTO).setData(Uri.parse("sms:07700900100")), 71 new Intent(Intent.ACTION_SENDTO).setData(Uri.parse("smsto:07700900100")), 72 new Intent(Intent.ACTION_SENDTO).setData(Uri.parse("mms:07700900100")), 73 new Intent(Intent.ACTION_SENDTO).setData(Uri.parse("mmsto:07700900100")), 74 new Intent(Intent.ACTION_VIEW).setData( 75 Uri.parse("sms:07700900100?body=Hello%20world")).addCategory( 76 Intent.CATEGORY_BROWSABLE), 77 new Intent(Intent.ACTION_VIEW).setData( 78 Uri.parse("smsto:07700900100?body=Hello%20world")).addCategory( 79 Intent.CATEGORY_BROWSABLE), 80 new Intent(Intent.ACTION_VIEW).setData( 81 Uri.parse("mms:07700900100?body=Hello%20world")).addCategory( 82 Intent.CATEGORY_BROWSABLE), 83 new Intent(Intent.ACTION_VIEW).setData( 84 Uri.parse("mmsto:07700900100?body=Hello%20world")).addCategory( 85 Intent.CATEGORY_BROWSABLE), 86 new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 87 new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS), 88 new Intent(Settings.ACTION_APN_SETTINGS), 89 new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS), 90 new Intent(Settings.ACTION_CAPTIONING_SETTINGS), 91 new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS), 92 new Intent(Settings.ACTION_DATE_SETTINGS), 93 new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS), 94 new Intent(Settings.ACTION_DISPLAY_SETTINGS), 95 new Intent(Settings.ACTION_DREAM_SETTINGS), 96 new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 97 new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS), 98 new Intent(Settings.ACTION_LOCALE_SETTINGS), 99 new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS), 100 new Intent(Settings.ACTION_NFC_SETTINGS), 101 new Intent(Settings.ACTION_NFCSHARING_SETTINGS), 102 new Intent(Settings.ACTION_PRIVACY_SETTINGS), 103 new Intent(Settings.ACTION_SETTINGS), 104 new Intent(Settings.ACTION_SOUND_SETTINGS), 105 new Intent(Settings.ACTION_WIRELESS_SETTINGS), 106 new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD), 107 new Intent("android.net.vpn.SETTINGS"), 108 new Intent(CardEmulation.ACTION_CHANGE_DEFAULT), 109 new Intent("android.settings.ACCOUNT_SYNC_SETTINGS"), 110 new Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS), 111 new Intent(Settings.ACTION_HOME_SETTINGS), 112 new Intent("android.settings.LICENSE"), 113 new Intent("android.settings.NOTIFICATION_SETTINGS"), 114 new Intent(Settings.ACTION_SHOW_REGULATORY_INFO), 115 new Intent("android.settings.USER_SETTINGS"), 116 new Intent("android.settings.ZEN_MODE_SETTINGS"), 117 new Intent("com.android.settings.ACCESSIBILITY_COLOR_SPACE_SETTINGS"), 118 new Intent("com.android.settings.STORAGE_USB_SETTINGS"), 119 new Intent("com.android.settings.TTS_SETTINGS"), 120 new Intent("com.android.settings.USER_DICTIONARY_EDIT"), 121 new Intent(Intent.ACTION_CALL).setData(Uri.parse("tel:123")), 122 new Intent("android.intent.action.CALL_EMERGENCY").setData(Uri.parse("tel:123")), 123 new Intent("android.intent.action.CALL_PRIVILEGED").setData(Uri.parse("tel:123")), 124 new Intent(Intent.ACTION_DIAL).setData(Uri.parse("tel:123")), 125 new Intent(Intent.ACTION_VIEW).setData(Uri.parse("tel:123")).addCategory( 126 Intent.CATEGORY_BROWSABLE), 127 new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS), 128 new Intent(Settings.ACTION_NFC_PAYMENT_SETTINGS), 129 new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), 130 new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS), 131 new Intent(Settings.ACTION_SYNC_SETTINGS), 132 new Intent(Settings.ACTION_ADD_ACCOUNT), 133 new Intent(Intent.ACTION_GET_CONTENT).setType("*/*").addCategory( 134 Intent.CATEGORY_OPENABLE), 135 new Intent(Intent.ACTION_OPEN_DOCUMENT).setType("*/*").addCategory( 136 Intent.CATEGORY_OPENABLE), 137 new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS), 138 new Intent(Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS), 139 new Intent(Settings.ACTION_APPLICATION_SETTINGS), 140 new Intent("android.settings.ACTION_OTHER_SOUND_SETTINGS"), 141 new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION), 142 new Intent(Settings.ACTION_WIFI_IP_SETTINGS), 143 new Intent(Settings.ACTION_WIFI_SETTINGS), 144 new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) 145 }; 146 147 // These are the intents which cannot be forwarded to the primary profile. 148 private static final Intent[] notForwardedIntentsFromManaged = new Intent[] { 149 new Intent(Intent.ACTION_INSERT).setData( 150 Uri.parse("content://browser/bookmarks")), 151 new Intent(Intent.ACTION_VIEW).setData( 152 Uri.parse("http://www.example.com")).addCategory( 153 Intent.CATEGORY_BROWSABLE), 154 new Intent(Intent.ACTION_SENDTO).setData( 155 Uri.parse("mailto:user@example.com")), 156 new Intent(Intent.ACTION_VIEW).setData( 157 Uri.parse("mailto:user@example.com")).addCategory( 158 Intent.CATEGORY_BROWSABLE), 159 new Intent(Intent.ACTION_VIEW).setData( 160 Uri.parse("geo:0,0?q=BuckinghamPalace")), 161 new Intent(Intent.ACTION_VIEW).setData( 162 Uri.parse("http://example.com/oceans.mp4")).setType("video/mp4"), 163 new Intent(Intent.ACTION_VIEW).setData( 164 Uri.parse("http://www.example.com/horse.mp3")).setType("audio/*"), 165 new Intent(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH), 166 new Intent(Intent.ACTION_VIEW).setData( 167 Uri.parse("market://details?id=com.android.chrome")).addCategory( 168 Intent.CATEGORY_BROWSABLE), 169 new Intent(Intent.ACTION_WEB_SEARCH), 170 new Intent(Settings.ACTION_SEARCH_SETTINGS), 171 new Intent(Settings.ACTION_PRINT_SETTINGS), 172 new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE), 173 new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData( 174 Uri.parse("package:com.android.chrome")), 175 new Intent("android.settings.SHOW_INPUT_METHOD_PICKER"), 176 new Intent(Intent.ACTION_INSERT).setData(Events.CONTENT_URI), 177 new Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL), 178 new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS) 179 }; 180 181 // This flag specifies we are dealing with intents fired from the primary profile. 182 public static final int FLAG_INTENTS_FROM_PRIMARY = 1; 183 // This flag specifies we are dealing with intents fired from the managed profile. 184 public static final int FLAG_INTENTS_FROM_MANAGED = 2; 185 186 private Context mContext; 187 IntentFiltersTestHelper(Context context)188 IntentFiltersTestHelper(Context context) { 189 mContext = context; 190 } 191 checkCrossProfileIntentFilters(int flag)192 public boolean checkCrossProfileIntentFilters(int flag) { 193 boolean crossProfileIntentFiltersSet; 194 if (flag == FLAG_INTENTS_FROM_PRIMARY) { 195 crossProfileIntentFiltersSet = checkForIntentsFromPrimary(); 196 } else { 197 crossProfileIntentFiltersSet = checkForIntentsFromManaged(); 198 } 199 return crossProfileIntentFiltersSet; 200 } 201 202 /** 203 * Checks if required cross profile intent filters are set for the intents fired from the 204 * primary profile. 205 */ checkForIntentsFromPrimary()206 private boolean checkForIntentsFromPrimary() { 207 // Get the class name of the intentForwarderActivity in the primary profile by firing an 208 // intent which we know will be forwarded from primary profile to managed profile. 209 ActivityInfo forwarderActivityInfo = 210 getForwarderActivityInfo(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER); 211 if (forwarderActivityInfo == null) { 212 return false; 213 } 214 215 // Check for intents which can be forwarded to the managed profile. 216 Intent intent = checkForIntentsNotHandled(forwardedIntentsFromPrimary, 217 forwarderActivityInfo, true); 218 if (intent != null) { 219 Log.d(TAG, intent + " from primary profile should be forwarded to the " + 220 "managed profile but is not."); 221 return false; 222 } 223 224 return true; 225 } 226 227 /** 228 * Checks if required cross profile intent filters are set for the intents fired from the 229 * managed profile. 230 */ checkForIntentsFromManaged()231 private boolean checkForIntentsFromManaged() { 232 // Get the class name of the intentForwarderActivity in the managed profile by firing an 233 // intent which we know will be forwarded from managed profile to primary profile. 234 ActivityInfo forwarderActivityInfo = 235 getForwarderActivityInfo(ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS); 236 if (forwarderActivityInfo == null) { 237 return false; 238 } 239 240 // Check for intents which can be forwarded to the primary profile. 241 Intent intent = checkForIntentsNotHandled(forwardedIntentsFromManaged, 242 forwarderActivityInfo, true); 243 if (intent != null) { 244 Log.d(TAG, intent + " from managed profile should be forwarded to the " + 245 "primary profile but is not."); 246 return false; 247 } 248 249 // Check for intents which cannot be forwarded to the primary profile. 250 intent = checkForIntentsNotHandled(notForwardedIntentsFromManaged, 251 forwarderActivityInfo, false); 252 if (intent != null) { 253 Log.d(TAG, intent + " from managed profile should not be forwarded to the " + 254 "primary profile but it is."); 255 return false; 256 } 257 258 return true; 259 } 260 261 /** 262 * Checks if the intentForwarderActivity can handle the intent passed. 263 */ canForwarderActivityHandleIntent(Intent intent, ActivityInfo forwarderActivityInfo)264 private boolean canForwarderActivityHandleIntent(Intent intent, 265 ActivityInfo forwarderActivityInfo) { 266 // Get all the activities which can handle the intent. 267 List<ResolveInfo> resolveInfoList = 268 mContext.getPackageManager().queryIntentActivities(intent, 269 PackageManager.MATCH_DEFAULT_ONLY); 270 // Check if intentForwarderActivity is part of the list. 271 for (ResolveInfo resolveInfo : resolveInfoList) { 272 if (forwarderActivityInfo.packageName.equals(resolveInfo.activityInfo.packageName) 273 && forwarderActivityInfo.name.equals(resolveInfo.activityInfo.name)) { 274 return true; 275 } 276 } 277 return false; 278 } 279 280 /** 281 * Returns the class name of the intentForwarderActivity. 282 */ getForwarderActivityInfo(String action)283 private ActivityInfo getForwarderActivityInfo(String action) { 284 Intent intent = new Intent(action); 285 List<ResolveInfo> resolveInfoList = 286 mContext.getPackageManager().queryIntentActivities(intent, 287 PackageManager.MATCH_DEFAULT_ONLY); 288 if (resolveInfoList.isEmpty() || resolveInfoList.size() > 1) { 289 Log.d(TAG, "There should be exactly one activity IntentForwarder which " + 290 "handles the intent " + intent); 291 return null; 292 } 293 return resolveInfoList.get(0).activityInfo; 294 } 295 296 /** 297 * Checks if the intents passed are correctly handled. 298 * @return {@code null} if all the intents are correctly handled 299 * otherwise, the first intent in the list which is not handled correctly. 300 */ checkForIntentsNotHandled(Intent[] intentList, ActivityInfo expectedForwarderActivityInfo, boolean canResolve)301 private Intent checkForIntentsNotHandled(Intent[] intentList, 302 ActivityInfo expectedForwarderActivityInfo, boolean canResolve) { 303 for (Intent intent : intentList) { 304 if (canForwarderActivityHandleIntent(intent, 305 expectedForwarderActivityInfo) != canResolve) { 306 return intent; 307 } 308 } 309 return null; 310 } 311 } 312