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