1 /* 2 * Copyright (C) 2021 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.server.pm; 18 19 import static android.content.pm.PackageManager.ONLY_IF_NO_MATCH_FOUND; 20 import static android.content.pm.PackageManager.SKIP_CURRENT_PROFILE; 21 import static android.speech.RecognizerIntent.ACTION_RECOGNIZE_SPEECH; 22 23 import static com.android.server.pm.CrossProfileIntentFilter.FLAG_ALLOW_CHAINED_RESOLUTION; 24 import static com.android.server.pm.CrossProfileIntentFilter.FLAG_IS_PACKAGE_FOR_FILTER; 25 26 import android.content.Intent; 27 import android.hardware.usb.UsbManager; 28 import android.nfc.NfcAdapter; 29 import android.provider.AlarmClock; 30 import android.provider.MediaStore; 31 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.List; 35 36 /** 37 * Utility Class for {@link DefaultCrossProfileIntentFilter}. 38 */ 39 public class DefaultCrossProfileIntentFiltersUtils { 40 DefaultCrossProfileIntentFiltersUtils()41 private DefaultCrossProfileIntentFiltersUtils() { 42 } 43 44 // Intents from profile to parent user 45 /** Emergency call intent with mime type is always resolved by primary user. */ 46 private static final DefaultCrossProfileIntentFilter 47 EMERGENCY_CALL_MIME = 48 new DefaultCrossProfileIntentFilter.Builder( 49 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 50 SKIP_CURRENT_PROFILE, 51 /* letsPersonalDataIntoProfile= */ false) 52 .addAction(Intent.ACTION_CALL_EMERGENCY) 53 .addAction(Intent.ACTION_CALL_PRIVILEGED) 54 .addCategory(Intent.CATEGORY_DEFAULT) 55 .addCategory(Intent.CATEGORY_BROWSABLE) 56 .addDataType("vnd.android.cursor.item/phone") 57 .addDataType("vnd.android.cursor.item/phone_v2") 58 .addDataType("vnd.android.cursor.item/person") 59 .addDataType("vnd.android.cursor.dir/calls") 60 .addDataType("vnd.android.cursor.item/calls") 61 .build(); 62 63 /** Emergency call intent with data schemes is always resolved by primary user. */ 64 private static final DefaultCrossProfileIntentFilter 65 EMERGENCY_CALL_DATA = 66 new DefaultCrossProfileIntentFilter.Builder( 67 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 68 SKIP_CURRENT_PROFILE, 69 /* letsPersonalDataIntoProfile= */ false) 70 .addAction(Intent.ACTION_CALL_EMERGENCY) 71 .addAction(Intent.ACTION_CALL_PRIVILEGED) 72 .addCategory(Intent.CATEGORY_DEFAULT) 73 .addCategory(Intent.CATEGORY_BROWSABLE) 74 .addDataScheme("tel") 75 .addDataScheme("sip") 76 .addDataScheme("voicemail") 77 .build(); 78 79 /** Dial intent with mime type can be handled by either managed profile or its parent user. */ 80 private static final DefaultCrossProfileIntentFilter DIAL_MIME = 81 new DefaultCrossProfileIntentFilter.Builder( 82 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 83 ONLY_IF_NO_MATCH_FOUND, 84 /* letsPersonalDataIntoProfile= */ false) 85 .addAction(Intent.ACTION_DIAL) 86 .addAction(Intent.ACTION_VIEW) 87 .addCategory(Intent.CATEGORY_DEFAULT) 88 .addCategory(Intent.CATEGORY_BROWSABLE) 89 .addDataType("vnd.android.cursor.item/phone") 90 .addDataType("vnd.android.cursor.item/phone_v2") 91 .addDataType("vnd.android.cursor.item/person") 92 .addDataType("vnd.android.cursor.dir/calls") 93 .addDataType("vnd.android.cursor.item/calls") 94 .build(); 95 96 /** Dial intent with mime type exclusively handled by managed profile. */ 97 private static final DefaultCrossProfileIntentFilter DIAL_MIME_MANAGED_PROFILE = 98 new DefaultCrossProfileIntentFilter.Builder( 99 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 100 SKIP_CURRENT_PROFILE, 101 /* letsPersonalDataIntoProfile= */ false) 102 .addAction(Intent.ACTION_DIAL) 103 .addAction(Intent.ACTION_VIEW) 104 .addCategory(Intent.CATEGORY_DEFAULT) 105 .addCategory(Intent.CATEGORY_BROWSABLE) 106 .addDataType("vnd.android.cursor.item/phone") 107 .addDataType("vnd.android.cursor.item/phone_v2") 108 .addDataType("vnd.android.cursor.item/person") 109 .addDataType("vnd.android.cursor.dir/calls") 110 .addDataType("vnd.android.cursor.item/calls") 111 .build(); 112 113 /** Dial intent with data scheme can be handled by either managed profile or its parent user. */ 114 private static final DefaultCrossProfileIntentFilter DIAL_DATA = 115 new DefaultCrossProfileIntentFilter.Builder( 116 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 117 ONLY_IF_NO_MATCH_FOUND, 118 /* letsPersonalDataIntoProfile= */ false) 119 .addAction(Intent.ACTION_DIAL) 120 .addAction(Intent.ACTION_VIEW) 121 .addCategory(Intent.CATEGORY_DEFAULT) 122 .addCategory(Intent.CATEGORY_BROWSABLE) 123 .addDataScheme("tel") 124 .addDataScheme("sip") 125 .addDataScheme("voicemail") 126 .build(); 127 128 /** Dial intent with data scheme exclusively handled by managed profile. */ 129 private static final DefaultCrossProfileIntentFilter DIAL_DATA_MANAGED_PROFILE = 130 new DefaultCrossProfileIntentFilter.Builder( 131 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 132 SKIP_CURRENT_PROFILE, 133 /* letsPersonalDataIntoProfile= */ false) 134 .addAction(Intent.ACTION_DIAL) 135 .addAction(Intent.ACTION_VIEW) 136 .addCategory(Intent.CATEGORY_DEFAULT) 137 .addCategory(Intent.CATEGORY_BROWSABLE) 138 .addDataScheme("tel") 139 .addDataScheme("sip") 140 .addDataScheme("voicemail") 141 .build(); 142 143 /** 144 * Dial intent with no data scheme or type can be handled by either managed profile or its 145 * parent user. 146 */ 147 private static final DefaultCrossProfileIntentFilter DIAL_RAW = 148 new DefaultCrossProfileIntentFilter.Builder( 149 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 150 ONLY_IF_NO_MATCH_FOUND, 151 /* letsPersonalDataIntoProfile= */ false) 152 .addAction(Intent.ACTION_DIAL) 153 .addCategory(Intent.CATEGORY_DEFAULT) 154 .addCategory(Intent.CATEGORY_BROWSABLE) 155 .build(); 156 157 /** 158 * Dial intent with no data scheme or type exclusively handled by managed profile. 159 */ 160 private static final DefaultCrossProfileIntentFilter DIAL_RAW_MANAGED_PROFILE = 161 new DefaultCrossProfileIntentFilter.Builder( 162 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 163 SKIP_CURRENT_PROFILE, 164 /* letsPersonalDataIntoProfile= */ false) 165 .addAction(Intent.ACTION_DIAL) 166 .addCategory(Intent.CATEGORY_DEFAULT) 167 .addCategory(Intent.CATEGORY_BROWSABLE) 168 .build(); 169 170 /** Pressing the call button can be handled by either managed profile or its parent user. */ 171 private static final DefaultCrossProfileIntentFilter CALL_BUTTON = 172 new DefaultCrossProfileIntentFilter.Builder( 173 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 174 ONLY_IF_NO_MATCH_FOUND, 175 /* letsPersonalDataIntoProfile= */ false) 176 .addAction(Intent.ACTION_CALL_BUTTON) 177 .addCategory(Intent.CATEGORY_DEFAULT) 178 .build(); 179 180 /** SMS and MMS are exclusively handled by the primary user. */ 181 private static final DefaultCrossProfileIntentFilter SMS_MMS = 182 new DefaultCrossProfileIntentFilter.Builder( 183 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 184 SKIP_CURRENT_PROFILE, 185 /* letsPersonalDataIntoProfile= */ false) 186 .addAction(Intent.ACTION_VIEW) 187 .addAction(Intent.ACTION_SENDTO) 188 .addCategory(Intent.CATEGORY_DEFAULT) 189 .addCategory(Intent.CATEGORY_BROWSABLE) 190 .addDataScheme("sms") 191 .addDataScheme("smsto") 192 .addDataScheme("mms") 193 .addDataScheme("mmsto") 194 .build(); 195 196 /** SMS and MMS intent exclusively handled by the managed profile. */ 197 private static final DefaultCrossProfileIntentFilter SMS_MMS_MANAGED_PROFILE = 198 new DefaultCrossProfileIntentFilter.Builder( 199 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 200 SKIP_CURRENT_PROFILE, 201 /* letsPersonalDataIntoProfile= */ false) 202 .addAction(Intent.ACTION_VIEW) 203 .addAction(Intent.ACTION_SENDTO) 204 .addCategory(Intent.CATEGORY_DEFAULT) 205 .addCategory(Intent.CATEGORY_BROWSABLE) 206 .addDataScheme("sms") 207 .addDataScheme("smsto") 208 .addDataScheme("mms") 209 .addDataScheme("mmsto") 210 .build(); 211 212 /** Mobile network settings is always shown in the primary user. */ 213 private static final DefaultCrossProfileIntentFilter 214 MOBILE_NETWORK_SETTINGS = 215 new DefaultCrossProfileIntentFilter.Builder( 216 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 217 SKIP_CURRENT_PROFILE, 218 /* letsPersonalDataIntoProfile= */ false) 219 .addAction(android.provider.Settings.ACTION_DATA_ROAMING_SETTINGS) 220 .addAction(android.provider.Settings.ACTION_NETWORK_OPERATOR_SETTINGS) 221 .addCategory(Intent.CATEGORY_DEFAULT) 222 .build(); 223 224 /** HOME intent is always resolved by the primary user. */ 225 static final DefaultCrossProfileIntentFilter HOME = 226 new DefaultCrossProfileIntentFilter.Builder( 227 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 228 SKIP_CURRENT_PROFILE, 229 /* letsPersonalDataIntoProfile= */ false) 230 .addAction(Intent.ACTION_MAIN) 231 .addCategory(Intent.CATEGORY_DEFAULT) 232 .addCategory(Intent.CATEGORY_HOME) 233 .build(); 234 235 /** Get content can be forwarded to parent user. */ 236 private static final DefaultCrossProfileIntentFilter GET_CONTENT = 237 new DefaultCrossProfileIntentFilter.Builder( 238 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 239 /* flags= */0, 240 /* letsPersonalDataIntoProfile= */ true) 241 .addAction(Intent.ACTION_GET_CONTENT) 242 .addCategory(Intent.CATEGORY_DEFAULT) 243 .addCategory(Intent.CATEGORY_OPENABLE) 244 .addDataType("*/*") 245 .build(); 246 247 /** Pick images can be forwarded to parent user. */ 248 private static final DefaultCrossProfileIntentFilter ACTION_PICK_IMAGES = 249 new DefaultCrossProfileIntentFilter.Builder( 250 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 251 /* flags= */ 0, 252 /* letsPersonalDataIntoProfile= */ true) 253 .addAction(MediaStore.ACTION_PICK_IMAGES) 254 .addCategory(Intent.CATEGORY_DEFAULT) 255 .build(); 256 /** Pick images can be forwarded to parent user. */ 257 private static final DefaultCrossProfileIntentFilter ACTION_PICK_IMAGES_WITH_DATA_TYPES = 258 new DefaultCrossProfileIntentFilter.Builder( 259 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 260 /* flags= */ 0, 261 /* letsPersonalDataIntoProfile= */ true) 262 .addAction(MediaStore.ACTION_PICK_IMAGES) 263 .addCategory(Intent.CATEGORY_DEFAULT) 264 .addDataType("image/*") 265 .addDataType("video/*") 266 .build(); 267 268 /** Open document intent can be forwarded to parent user. */ 269 private static final DefaultCrossProfileIntentFilter OPEN_DOCUMENT = 270 new DefaultCrossProfileIntentFilter.Builder( 271 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 272 /* flags= */0, 273 /* letsPersonalDataIntoProfile= */ true) 274 .addAction(Intent.ACTION_OPEN_DOCUMENT) 275 .addCategory(Intent.CATEGORY_DEFAULT) 276 .addCategory(Intent.CATEGORY_OPENABLE) 277 .addDataType("*/*") 278 .build(); 279 280 /** Pick for any data type can be forwarded to parent user. */ 281 private static final DefaultCrossProfileIntentFilter ACTION_PICK_DATA = 282 new DefaultCrossProfileIntentFilter.Builder( 283 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 284 /* flags= */0, 285 /* letsPersonalDataIntoProfile= */ true) 286 .addAction(Intent.ACTION_PICK) 287 .addCategory(Intent.CATEGORY_DEFAULT) 288 .addDataType("*/*") 289 .build(); 290 291 /** Pick without data type can be forwarded to parent user. */ 292 private static final DefaultCrossProfileIntentFilter ACTION_PICK_RAW = 293 new DefaultCrossProfileIntentFilter.Builder( 294 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 295 /* flags= */0, 296 /* letsPersonalDataIntoProfile= */ true) 297 .addAction(Intent.ACTION_PICK) 298 .addCategory(Intent.CATEGORY_DEFAULT) 299 .build(); 300 301 /** Speech recognition can be performed by primary user. */ 302 private static final DefaultCrossProfileIntentFilter RECOGNIZE_SPEECH = 303 new DefaultCrossProfileIntentFilter.Builder( 304 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 305 /* flags= */ ONLY_IF_NO_MATCH_FOUND, 306 /* letsPersonalDataIntoProfile= */ false) 307 .addAction(ACTION_RECOGNIZE_SPEECH) 308 .addCategory(Intent.CATEGORY_DEFAULT) 309 .build(); 310 311 /** Media capture can be performed by primary user. */ 312 private static final DefaultCrossProfileIntentFilter MEDIA_CAPTURE = 313 new DefaultCrossProfileIntentFilter.Builder( 314 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 315 /* flags= */ ONLY_IF_NO_MATCH_FOUND, 316 /* letsPersonalDataIntoProfile= */ true) 317 .addAction(MediaStore.ACTION_IMAGE_CAPTURE) 318 .addAction(MediaStore.ACTION_IMAGE_CAPTURE_SECURE) 319 .addAction(MediaStore.ACTION_VIDEO_CAPTURE) 320 .addAction(MediaStore.Audio.Media.RECORD_SOUND_ACTION) 321 .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA) 322 .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE) 323 .addAction(MediaStore.INTENT_ACTION_VIDEO_CAMERA) 324 .addCategory(Intent.CATEGORY_DEFAULT) 325 .build(); 326 327 /** Alarm setting can be performed by primary user. */ 328 private static final DefaultCrossProfileIntentFilter SET_ALARM = 329 new DefaultCrossProfileIntentFilter.Builder( 330 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 331 /* flags= */0, 332 /* letsPersonalDataIntoProfile= */ false) 333 .addAction(AlarmClock.ACTION_SET_ALARM) 334 .addAction(AlarmClock.ACTION_SHOW_ALARMS) 335 .addAction(AlarmClock.ACTION_SET_TIMER) 336 .addCategory(Intent.CATEGORY_DEFAULT) 337 .build(); 338 339 // Intents from parent to profile user 340 341 /** ACTION_SEND can be forwarded to the managed profile on user's choice. */ 342 private static final DefaultCrossProfileIntentFilter ACTION_SEND = 343 new DefaultCrossProfileIntentFilter.Builder( 344 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 345 /* flags= */0, 346 /* letsPersonalDataIntoProfile= */ true) 347 .addAction(Intent.ACTION_SEND) 348 .addAction(Intent.ACTION_SEND_MULTIPLE) 349 .addCategory(Intent.CATEGORY_DEFAULT) 350 .addDataType("*/*") 351 .build(); 352 353 /** USB devices attached can get forwarded to the profile. */ 354 private static final DefaultCrossProfileIntentFilter 355 USB_DEVICE_ATTACHED = 356 new DefaultCrossProfileIntentFilter.Builder( 357 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 358 /* flags= */0, 359 /* letsPersonalDataIntoProfile= */ false) 360 .addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED) 361 .addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED) 362 .addCategory(Intent.CATEGORY_DEFAULT) 363 .build(); 364 365 getDefaultManagedProfileFilters()366 public static List<DefaultCrossProfileIntentFilter> getDefaultManagedProfileFilters() { 367 List<DefaultCrossProfileIntentFilter> filters = 368 new ArrayList<DefaultCrossProfileIntentFilter>(); 369 filters.addAll(Arrays.asList( 370 EMERGENCY_CALL_MIME, 371 EMERGENCY_CALL_DATA, 372 CALL_BUTTON, 373 SET_ALARM, 374 MEDIA_CAPTURE, 375 RECOGNIZE_SPEECH, 376 ACTION_PICK_RAW, 377 ACTION_PICK_DATA, 378 ACTION_PICK_IMAGES, 379 ACTION_PICK_IMAGES_WITH_DATA_TYPES, 380 OPEN_DOCUMENT, 381 GET_CONTENT, 382 USB_DEVICE_ATTACHED, 383 ACTION_SEND, 384 HOME, 385 MOBILE_NETWORK_SETTINGS)); 386 filters.addAll(getDefaultCrossProfileTelephonyIntentFilters(false)); 387 return filters; 388 } 389 390 /** Call intent with tel scheme exclusively handled my managed profile. 391 * Note that work profile telephony relies on this intent filter to redirect intents to 392 * the IntentForwarderActivity. Work profile telephony error handling must be updated in 393 * the Telecomm package CallsManager if this filter is changed. 394 */ 395 private static final DefaultCrossProfileIntentFilter CALL_MANAGED_PROFILE = 396 new DefaultCrossProfileIntentFilter.Builder( 397 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 398 SKIP_CURRENT_PROFILE, 399 /* letsPersonalDataIntoProfile= */ false) 400 .addAction(Intent.ACTION_CALL) 401 .addCategory(Intent.CATEGORY_DEFAULT) 402 .addDataScheme("tel") 403 .build(); 404 405 /** 406 * Returns default telephony related intent filters for managed profile. 407 */ 408 public static List<DefaultCrossProfileIntentFilter> getDefaultCrossProfileTelephonyIntentFilters(boolean telephonyOnlyInManagedProfile)409 getDefaultCrossProfileTelephonyIntentFilters(boolean telephonyOnlyInManagedProfile) { 410 if (telephonyOnlyInManagedProfile) { 411 return Arrays.asList( 412 DIAL_DATA_MANAGED_PROFILE, 413 DIAL_MIME_MANAGED_PROFILE, 414 DIAL_RAW_MANAGED_PROFILE, 415 CALL_MANAGED_PROFILE, 416 SMS_MMS_MANAGED_PROFILE); 417 } else { 418 return Arrays.asList( 419 DIAL_DATA, 420 DIAL_MIME, 421 DIAL_RAW, 422 SMS_MMS); 423 } 424 } 425 426 /** 427 * Clone profile's DefaultCrossProfileIntentFilter 428 */ 429 430 /* 431 Allowing media capture from clone to parent profile as clone profile would not have camera 432 */ 433 private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_MEDIA_CAPTURE = 434 new DefaultCrossProfileIntentFilter.Builder( 435 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 436 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 437 // and FLAG_ALLOW_CHAINED_RESOLUTION set 438 /* letsPersonalDataIntoProfile= */ false) 439 .addAction(MediaStore.ACTION_IMAGE_CAPTURE) 440 .addAction(MediaStore.ACTION_IMAGE_CAPTURE_SECURE) 441 .addAction(MediaStore.ACTION_VIDEO_CAPTURE) 442 .addAction(MediaStore.Audio.Media.RECORD_SOUND_ACTION) 443 .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA) 444 .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE) 445 .addAction(MediaStore.INTENT_ACTION_VIDEO_CAMERA) 446 .addCategory(Intent.CATEGORY_DEFAULT) 447 .build(); 448 449 private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_PHOTOPICKER_SELECTION = 450 new DefaultCrossProfileIntentFilter.Builder( 451 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 452 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 453 // and FLAG_ALLOW_CHAINED_RESOLUTION set 454 /* letsPersonalDataIntoProfile= */ false) 455 .addAction(MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP) 456 .addCategory(Intent.CATEGORY_DEFAULT) 457 .build(); 458 459 /* 460 Allowing send action from clone to parent profile to share content from clone apps to parent 461 apps 462 */ 463 private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_SEND_ACTION = 464 new DefaultCrossProfileIntentFilter.Builder( 465 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 466 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 467 // and FLAG_ALLOW_CHAINED_RESOLUTION set 468 /* letsPersonalDataIntoProfile= */ false) 469 .addAction(Intent.ACTION_SEND) 470 .addAction(Intent.ACTION_SEND_MULTIPLE) 471 .addAction(Intent.ACTION_SENDTO) 472 .addDataType("*/*") 473 .build(); 474 475 /* 476 Allowing send action from parent to clone profile to share content from parent apps to clone 477 apps 478 */ 479 private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_SEND_ACTION = 480 new DefaultCrossProfileIntentFilter.Builder( 481 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 482 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 483 // and FLAG_ALLOW_CHAINED_RESOLUTION set 484 /* letsPersonalDataIntoProfile= */ false) 485 .addAction(Intent.ACTION_SEND) 486 .addAction(Intent.ACTION_SEND_MULTIPLE) 487 .addAction(Intent.ACTION_SENDTO) 488 .addDataType("*/*") 489 .build(); 490 491 /* 492 Allowing view action from clone to parent profile to open any app-links or web links 493 */ 494 private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_WEB_VIEW_ACTION = 495 new DefaultCrossProfileIntentFilter.Builder( 496 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 497 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 498 // and FLAG_ALLOW_CHAINED_RESOLUTION set 499 /* letsPersonalDataIntoProfile= */ false) 500 .addAction(Intent.ACTION_VIEW) 501 .addDataScheme("https") 502 .addDataScheme("http") 503 .build(); 504 505 /* 506 Allowing view action from parent to clone profile to open any app-links or web links 507 */ 508 private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_WEB_VIEW_ACTION = 509 new DefaultCrossProfileIntentFilter.Builder( 510 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 511 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 512 // and FLAG_ALLOW_CHAINED_RESOLUTION set 513 /* letsPersonalDataIntoProfile= */ false) 514 .addAction(Intent.ACTION_VIEW) 515 .addDataScheme("https") 516 .addDataScheme("http") 517 .build(); 518 519 /* 520 Allowing view action from clone to parent profile to any data type e.g. pdf, including custom 521 content providers. 522 */ 523 private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_VIEW_ACTION = 524 new DefaultCrossProfileIntentFilter.Builder( 525 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 526 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 527 // and FLAG_ALLOW_CHAINED_RESOLUTION set 528 /* letsPersonalDataIntoProfile= */ false) 529 .addAction(Intent.ACTION_VIEW) 530 .addDataType("*/*") 531 .build(); 532 533 534 /* 535 Allowing pick,insert and edit action from clone to parent profile to open picker or contacts 536 insert/edit. 537 */ 538 private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_PICK_INSERT_ACTION = 539 new DefaultCrossProfileIntentFilter.Builder( 540 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 541 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 542 // and FLAG_ALLOW_CHAINED_RESOLUTION set 543 /* letsPersonalDataIntoProfile= */ false) 544 .addAction(Intent.ACTION_PICK) 545 .addAction(Intent.ACTION_GET_CONTENT) 546 .addAction(Intent.ACTION_EDIT) 547 .addAction(Intent.ACTION_INSERT) 548 .addAction(Intent.ACTION_INSERT_OR_EDIT) 549 .addAction(Intent.ACTION_OPEN_DOCUMENT) 550 .addDataType("*/*") 551 .addCategory(Intent.CATEGORY_DEFAULT) 552 .addCategory(Intent.CATEGORY_OPENABLE) 553 .build(); 554 555 /* 556 Allowing pick,insert and edit action from parent to clone profile to open picker 557 */ 558 private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_PICK_INSERT_ACTION = 559 new DefaultCrossProfileIntentFilter.Builder( 560 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 561 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 562 // and FLAG_ALLOW_CHAINED_RESOLUTION set 563 /* letsPersonalDataIntoProfile= */ false) 564 .addAction(Intent.ACTION_PICK) 565 .addAction(Intent.ACTION_GET_CONTENT) 566 .addAction(Intent.ACTION_EDIT) 567 .addAction(Intent.ACTION_INSERT) 568 .addAction(Intent.ACTION_INSERT_OR_EDIT) 569 .addAction(Intent.ACTION_OPEN_DOCUMENT) 570 .addDataType("*/*") 571 .addCategory(Intent.CATEGORY_DEFAULT) 572 .addCategory(Intent.CATEGORY_OPENABLE) 573 .build(); 574 575 private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_DIAL_DATA = 576 new DefaultCrossProfileIntentFilter.Builder( 577 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 578 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 579 // and FLAG_ALLOW_CHAINED_RESOLUTION set 580 /* letsPersonalDataIntoProfile= */ false) 581 .addAction(Intent.ACTION_DIAL) 582 .addAction(Intent.ACTION_VIEW) 583 .addCategory(Intent.CATEGORY_DEFAULT) 584 .addCategory(Intent.CATEGORY_BROWSABLE) 585 .addDataScheme("tel") 586 .addDataScheme("sip") 587 .addDataScheme("voicemail") 588 .build(); 589 590 private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_DIAL_DATA = 591 new DefaultCrossProfileIntentFilter.Builder( 592 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 593 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 594 // and FLAG_ALLOW_CHAINED_RESOLUTION set 595 /* letsPersonalDataIntoProfile= */ false) 596 .addAction(Intent.ACTION_DIAL) 597 .addAction(Intent.ACTION_VIEW) 598 .addCategory(Intent.CATEGORY_DEFAULT) 599 .addCategory(Intent.CATEGORY_BROWSABLE) 600 .addDataScheme("tel") 601 .addDataScheme("sip") 602 .addDataScheme("voicemail") 603 .build(); 604 605 private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_SMS_MMS = 606 new DefaultCrossProfileIntentFilter.Builder( 607 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 608 /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER 609 // and FLAG_ALLOW_CHAINED_RESOLUTION set 610 /* letsPersonalDataIntoProfile= */ false) 611 .addAction(Intent.ACTION_VIEW) 612 .addAction(Intent.ACTION_SENDTO) 613 .addCategory(Intent.CATEGORY_DEFAULT) 614 .addCategory(Intent.CATEGORY_BROWSABLE) 615 .addDataScheme("sms") 616 .addDataScheme("smsto") 617 .addDataScheme("mms") 618 .addDataScheme("mmsto") 619 .build(); 620 621 private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_ACTION_PICK_IMAGES = 622 new DefaultCrossProfileIntentFilter.Builder( 623 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 624 /* flags= */ FLAG_IS_PACKAGE_FOR_FILTER | FLAG_ALLOW_CHAINED_RESOLUTION, 625 /* letsPersonalDataIntoProfile= */ false) 626 .addAction(MediaStore.ACTION_PICK_IMAGES) 627 .addCategory(Intent.CATEGORY_DEFAULT) 628 .build(); 629 630 private static final DefaultCrossProfileIntentFilter 631 CLONE_TO_PARENT_ACTION_PICK_IMAGES_WITH_DATA_TYPES = 632 new DefaultCrossProfileIntentFilter.Builder( 633 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 634 /* flags= */ FLAG_IS_PACKAGE_FOR_FILTER | FLAG_ALLOW_CHAINED_RESOLUTION, 635 /* letsPersonalDataIntoProfile= */ false) 636 .addAction(MediaStore.ACTION_PICK_IMAGES) 637 .addCategory(Intent.CATEGORY_DEFAULT) 638 .addDataType("image/*") 639 .addDataType("video/*") 640 .build(); 641 642 /** NFC TAG intent is always resolved by the primary user. */ 643 static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_NFC_TAG_DISCOVERED = 644 new DefaultCrossProfileIntentFilter.Builder( 645 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 646 /* flags= */0, 647 /* letsPersonalDataIntoProfile= */ false) 648 .addAction(NfcAdapter.ACTION_TAG_DISCOVERED) 649 .build(); 650 651 /** NFC TAG intent is always resolved by the primary user. */ 652 static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_NFC_TECH_DISCOVERED = 653 new DefaultCrossProfileIntentFilter.Builder( 654 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 655 /* flags= */0, 656 /* letsPersonalDataIntoProfile= */ false) 657 .addAction(NfcAdapter.ACTION_TECH_DISCOVERED) 658 .build(); 659 660 /** NFC TAG intent is always resolved by the primary user. */ 661 static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_NFC_NDEF_DISCOVERED = 662 new DefaultCrossProfileIntentFilter.Builder( 663 DefaultCrossProfileIntentFilter.Direction.TO_PROFILE, 664 /* flags= */0, 665 /* letsPersonalDataIntoProfile= */ false) 666 .addAction(NfcAdapter.ACTION_NDEF_DISCOVERED) 667 .build(); 668 getDefaultCloneProfileFilters()669 public static List<DefaultCrossProfileIntentFilter> getDefaultCloneProfileFilters() { 670 return Arrays.asList( 671 PARENT_TO_CLONE_SEND_ACTION, 672 PARENT_TO_CLONE_WEB_VIEW_ACTION, 673 PARENT_TO_CLONE_PICK_INSERT_ACTION, 674 PARENT_TO_CLONE_DIAL_DATA, 675 CLONE_TO_PARENT_MEDIA_CAPTURE, 676 CLONE_TO_PARENT_SEND_ACTION, 677 CLONE_TO_PARENT_WEB_VIEW_ACTION, 678 CLONE_TO_PARENT_VIEW_ACTION, 679 CLONE_TO_PARENT_PICK_INSERT_ACTION, 680 CLONE_TO_PARENT_DIAL_DATA, 681 CLONE_TO_PARENT_SMS_MMS, 682 CLONE_TO_PARENT_PHOTOPICKER_SELECTION, 683 CLONE_TO_PARENT_ACTION_PICK_IMAGES, 684 CLONE_TO_PARENT_ACTION_PICK_IMAGES_WITH_DATA_TYPES, 685 PARENT_TO_CLONE_NFC_TAG_DISCOVERED, 686 PARENT_TO_CLONE_NFC_TECH_DISCOVERED, 687 PARENT_TO_CLONE_NFC_NDEF_DISCOVERED 688 ); 689 } 690 691 /** Call intent should be handled by the main user. */ 692 private static final DefaultCrossProfileIntentFilter CALL_PRIVATE_PROFILE = 693 new DefaultCrossProfileIntentFilter.Builder( 694 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 695 SKIP_CURRENT_PROFILE, 696 /* letsPersonalDataIntoProfile= */ false) 697 .addAction(Intent.ACTION_CALL) 698 .addCategory(Intent.CATEGORY_DEFAULT) 699 .addDataScheme("tel") 700 .addDataScheme("sip") 701 .addDataScheme("voicemail") 702 .build(); 703 704 /** Pressing the call button should be handled by the main user. */ 705 private static final DefaultCrossProfileIntentFilter CALL_BUTTON_PRIVATE_PROFILE = 706 new DefaultCrossProfileIntentFilter.Builder( 707 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 708 ONLY_IF_NO_MATCH_FOUND, 709 /* letsPersonalDataIntoProfile= */ false) 710 .addAction(Intent.ACTION_CALL_BUTTON) 711 .addCategory(Intent.CATEGORY_DEFAULT) 712 .build(); 713 714 /** Dial intent with mime type can be handled by either private profile or its parent user. */ 715 private static final DefaultCrossProfileIntentFilter DIAL_MIME_PRIVATE_PROFILE = 716 new DefaultCrossProfileIntentFilter.Builder( 717 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 718 ONLY_IF_NO_MATCH_FOUND, 719 /* letsPersonalDataIntoProfile= */ false) 720 .addAction(Intent.ACTION_DIAL) 721 .addAction(Intent.ACTION_VIEW) 722 .addCategory(Intent.CATEGORY_DEFAULT) 723 .addCategory(Intent.CATEGORY_BROWSABLE) 724 .addDataType("vnd.android.cursor.item/phone") 725 .addDataType("vnd.android.cursor.item/phone_v2") 726 .addDataType("vnd.android.cursor.item/person") 727 .addDataType("vnd.android.cursor.dir/calls") 728 .addDataType("vnd.android.cursor.item/calls") 729 .build(); 730 731 /** Dial intent with data scheme can be handled by either private profile or its parent user. */ 732 private static final DefaultCrossProfileIntentFilter DIAL_DATA_PRIVATE_PROFILE = 733 new DefaultCrossProfileIntentFilter.Builder( 734 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 735 ONLY_IF_NO_MATCH_FOUND, 736 /* letsPersonalDataIntoProfile= */ false) 737 .addAction(Intent.ACTION_DIAL) 738 .addAction(Intent.ACTION_VIEW) 739 .addCategory(Intent.CATEGORY_DEFAULT) 740 .addCategory(Intent.CATEGORY_BROWSABLE) 741 .addDataScheme("tel") 742 .addDataScheme("sip") 743 .addDataScheme("voicemail") 744 .build(); 745 746 /** 747 * Dial intent with no data scheme or type can be handled by either private profile or its 748 * parent user. 749 */ 750 private static final DefaultCrossProfileIntentFilter DIAL_RAW_PRIVATE_PROFILE = 751 new DefaultCrossProfileIntentFilter.Builder( 752 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 753 ONLY_IF_NO_MATCH_FOUND, 754 /* letsPersonalDataIntoProfile= */ false) 755 .addAction(Intent.ACTION_DIAL) 756 .addCategory(Intent.CATEGORY_DEFAULT) 757 .addCategory(Intent.CATEGORY_BROWSABLE) 758 .build(); 759 760 /** SMS and MMS are always handled in the main user. */ 761 private static final DefaultCrossProfileIntentFilter SMS_MMS_PRIVATE_PROFILE = 762 new DefaultCrossProfileIntentFilter.Builder( 763 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 764 SKIP_CURRENT_PROFILE, 765 /* letsPersonalDataIntoProfile= */ false) 766 .addAction(Intent.ACTION_VIEW) 767 .addAction(Intent.ACTION_SENDTO) 768 .addCategory(Intent.CATEGORY_DEFAULT) 769 .addCategory(Intent.CATEGORY_BROWSABLE) 770 .addDataScheme("sms") 771 .addDataScheme("smsto") 772 .addDataScheme("mms") 773 .addDataScheme("mmsto") 774 .build(); 775 getDefaultPrivateProfileFilters()776 public static List<DefaultCrossProfileIntentFilter> getDefaultPrivateProfileFilters() { 777 return Arrays.asList( 778 DIAL_MIME_PRIVATE_PROFILE, 779 DIAL_DATA_PRIVATE_PROFILE, 780 DIAL_RAW_PRIVATE_PROFILE, 781 CALL_PRIVATE_PROFILE, 782 CALL_BUTTON_PRIVATE_PROFILE, 783 EMERGENCY_CALL_DATA, 784 EMERGENCY_CALL_MIME, 785 SMS_MMS_PRIVATE_PROFILE 786 ); 787 } 788 } 789