• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_MOTION_PHOTO_CAPTURE)
320                     .addAction(MediaStore.ACTION_MOTION_PHOTO_CAPTURE_SECURE)
321                     .addAction(MediaStore.ACTION_VIDEO_CAPTURE)
322                     .addAction(MediaStore.Audio.Media.RECORD_SOUND_ACTION)
323                     .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA)
324                     .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
325                     .addAction(MediaStore.INTENT_ACTION_VIDEO_CAMERA)
326                     .addCategory(Intent.CATEGORY_DEFAULT)
327                     .build();
328 
329     /** Alarm setting can be performed by primary user. */
330     private static final DefaultCrossProfileIntentFilter SET_ALARM =
331             new DefaultCrossProfileIntentFilter.Builder(
332                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
333                     /* flags= */0,
334                     /* letsPersonalDataIntoProfile= */ false)
335                     .addAction(AlarmClock.ACTION_SET_ALARM)
336                     .addAction(AlarmClock.ACTION_SHOW_ALARMS)
337                     .addAction(AlarmClock.ACTION_SET_TIMER)
338                     .addCategory(Intent.CATEGORY_DEFAULT)
339                     .build();
340 
341     // Intents from parent to profile user
342 
343     /** ACTION_SEND can be forwarded to the managed profile on user's choice. */
344     private static final DefaultCrossProfileIntentFilter ACTION_SEND =
345             new DefaultCrossProfileIntentFilter.Builder(
346                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
347                     /* flags= */0,
348                     /* letsPersonalDataIntoProfile= */ true)
349                     .addAction(Intent.ACTION_SEND)
350                     .addAction(Intent.ACTION_SEND_MULTIPLE)
351                     .addCategory(Intent.CATEGORY_DEFAULT)
352                     .addDataType("*/*")
353                     .build();
354 
355     /** USB devices attached can get forwarded to the profile. */
356     private static final DefaultCrossProfileIntentFilter
357             USB_DEVICE_ATTACHED =
358             new DefaultCrossProfileIntentFilter.Builder(
359                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
360                     /* flags= */0,
361                     /* letsPersonalDataIntoProfile= */ false)
362                     .addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
363                     .addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)
364                     .addCategory(Intent.CATEGORY_DEFAULT)
365                     .build();
366 
367 
getDefaultManagedProfileFilters()368     public static List<DefaultCrossProfileIntentFilter> getDefaultManagedProfileFilters() {
369         List<DefaultCrossProfileIntentFilter> filters =
370                 new ArrayList<DefaultCrossProfileIntentFilter>();
371         filters.addAll(Arrays.asList(
372                 EMERGENCY_CALL_MIME,
373                 EMERGENCY_CALL_DATA,
374                 CALL_BUTTON,
375                 SET_ALARM,
376                 MEDIA_CAPTURE,
377                 RECOGNIZE_SPEECH,
378                 ACTION_PICK_RAW,
379                 ACTION_PICK_DATA,
380                 ACTION_PICK_IMAGES,
381                 ACTION_PICK_IMAGES_WITH_DATA_TYPES,
382                 OPEN_DOCUMENT,
383                 GET_CONTENT,
384                 USB_DEVICE_ATTACHED,
385                 ACTION_SEND,
386                 HOME,
387                 MOBILE_NETWORK_SETTINGS));
388         filters.addAll(getDefaultCrossProfileTelephonyIntentFilters(false));
389         return filters;
390     }
391 
392     /** Call intent with tel scheme exclusively handled my managed profile.
393      * Note that work profile telephony relies on this intent filter to redirect intents to
394      * the IntentForwarderActivity. Work profile telephony error handling must be updated in
395      * the Telecomm package CallsManager if this filter is changed.
396      */
397     private static final DefaultCrossProfileIntentFilter CALL_MANAGED_PROFILE =
398             new DefaultCrossProfileIntentFilter.Builder(
399                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
400                     SKIP_CURRENT_PROFILE,
401                     /* letsPersonalDataIntoProfile= */ false)
402                     .addAction(Intent.ACTION_CALL)
403                     .addCategory(Intent.CATEGORY_DEFAULT)
404                     .addDataScheme("tel")
405                     .build();
406 
407     /**
408      * Returns default telephony related intent filters for managed profile.
409      */
410     public static List<DefaultCrossProfileIntentFilter>
getDefaultCrossProfileTelephonyIntentFilters(boolean telephonyOnlyInManagedProfile)411             getDefaultCrossProfileTelephonyIntentFilters(boolean telephonyOnlyInManagedProfile) {
412         if (telephonyOnlyInManagedProfile) {
413             return Arrays.asList(
414                     DIAL_DATA_MANAGED_PROFILE,
415                     DIAL_MIME_MANAGED_PROFILE,
416                     DIAL_RAW_MANAGED_PROFILE,
417                     CALL_MANAGED_PROFILE,
418                     SMS_MMS_MANAGED_PROFILE);
419         } else {
420             return Arrays.asList(
421                     DIAL_DATA,
422                     DIAL_MIME,
423                     DIAL_RAW,
424                     SMS_MMS);
425         }
426     }
427 
428     /**
429      * Clone profile's DefaultCrossProfileIntentFilter
430      */
431 
432     /*
433      Allowing media capture from clone to parent profile as clone profile would not have camera
434      */
435     private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_MEDIA_CAPTURE =
436             new DefaultCrossProfileIntentFilter.Builder(
437                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
438                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
439                                             // and FLAG_ALLOW_CHAINED_RESOLUTION set
440                     /* letsPersonalDataIntoProfile= */ false)
441                     .addAction(MediaStore.ACTION_IMAGE_CAPTURE)
442                     .addAction(MediaStore.ACTION_IMAGE_CAPTURE_SECURE)
443                     .addAction(MediaStore.ACTION_MOTION_PHOTO_CAPTURE)
444                     .addAction(MediaStore.ACTION_MOTION_PHOTO_CAPTURE_SECURE)
445                     .addAction(MediaStore.ACTION_VIDEO_CAPTURE)
446                     .addAction(MediaStore.Audio.Media.RECORD_SOUND_ACTION)
447                     .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA)
448                     .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
449                     .addAction(MediaStore.INTENT_ACTION_VIDEO_CAMERA)
450                     .addCategory(Intent.CATEGORY_DEFAULT)
451                     .build();
452 
453     private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_PHOTOPICKER_SELECTION =
454             new DefaultCrossProfileIntentFilter.Builder(
455                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
456                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
457                     // and FLAG_ALLOW_CHAINED_RESOLUTION set
458                     /* letsPersonalDataIntoProfile= */ false)
459                     .addAction(MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP)
460                     .addCategory(Intent.CATEGORY_DEFAULT)
461                     .build();
462 
463     /*
464      Allowing send action from clone to parent profile to share content from clone apps to parent
465      apps
466      */
467     private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_SEND_ACTION =
468             new DefaultCrossProfileIntentFilter.Builder(
469                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
470                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
471                     // and FLAG_ALLOW_CHAINED_RESOLUTION set
472                     /* letsPersonalDataIntoProfile= */ false)
473                     .addAction(Intent.ACTION_SEND)
474                     .addAction(Intent.ACTION_SEND_MULTIPLE)
475                     .addAction(Intent.ACTION_SENDTO)
476                     .addDataType("*/*")
477                     .build();
478 
479     /*
480      Allowing send action from parent to clone profile to share content from parent apps to clone
481      apps
482      */
483     private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_SEND_ACTION =
484             new DefaultCrossProfileIntentFilter.Builder(
485                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
486                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
487                                             // and FLAG_ALLOW_CHAINED_RESOLUTION set
488                     /* letsPersonalDataIntoProfile= */ false)
489                     .addAction(Intent.ACTION_SEND)
490                     .addAction(Intent.ACTION_SEND_MULTIPLE)
491                     .addAction(Intent.ACTION_SENDTO)
492                     .addDataType("*/*")
493                     .build();
494 
495     /*
496      Allowing view action from clone to parent profile to open any app-links or web links
497      */
498     private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_WEB_VIEW_ACTION =
499             new DefaultCrossProfileIntentFilter.Builder(
500                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
501                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
502                     // and FLAG_ALLOW_CHAINED_RESOLUTION set
503                     /* letsPersonalDataIntoProfile= */ false)
504                     .addAction(Intent.ACTION_VIEW)
505                     .addDataScheme("https")
506                     .addDataScheme("http")
507                     .build();
508 
509     /*
510      Allowing view action from parent to clone profile to open any app-links or web links
511      */
512     private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_WEB_VIEW_ACTION =
513             new DefaultCrossProfileIntentFilter.Builder(
514                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
515                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
516                                             // and FLAG_ALLOW_CHAINED_RESOLUTION set
517                     /* letsPersonalDataIntoProfile= */ false)
518                     .addAction(Intent.ACTION_VIEW)
519                     .addDataScheme("https")
520                     .addDataScheme("http")
521                     .build();
522 
523     /*
524      Allowing view action from clone to parent profile to any data type e.g. pdf, including custom
525      content providers.
526      */
527     private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_VIEW_ACTION =
528             new DefaultCrossProfileIntentFilter.Builder(
529                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
530                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
531                     // and FLAG_ALLOW_CHAINED_RESOLUTION set
532                     /* letsPersonalDataIntoProfile= */ false)
533                     .addAction(Intent.ACTION_VIEW)
534                     .addDataType("*/*")
535                     .build();
536 
537 
538     /*
539      Allowing pick,insert and edit action from clone to parent profile to open picker or contacts
540      insert/edit.
541      */
542     private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_PICK_INSERT_ACTION =
543             new DefaultCrossProfileIntentFilter.Builder(
544                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
545                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
546                                             // and FLAG_ALLOW_CHAINED_RESOLUTION set
547                     /* letsPersonalDataIntoProfile= */ false)
548                     .addAction(Intent.ACTION_PICK)
549                     .addAction(Intent.ACTION_GET_CONTENT)
550                     .addAction(Intent.ACTION_EDIT)
551                     .addAction(Intent.ACTION_INSERT)
552                     .addAction(Intent.ACTION_INSERT_OR_EDIT)
553                     .addAction(Intent.ACTION_OPEN_DOCUMENT)
554                     .addDataType("*/*")
555                     .addCategory(Intent.CATEGORY_DEFAULT)
556                     .addCategory(Intent.CATEGORY_OPENABLE)
557                     .build();
558 
559     /*
560      Allowing pick,insert and edit action from parent to clone profile to open picker
561      */
562     private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_PICK_INSERT_ACTION =
563             new DefaultCrossProfileIntentFilter.Builder(
564                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
565                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
566                                             // and FLAG_ALLOW_CHAINED_RESOLUTION set
567                     /* letsPersonalDataIntoProfile= */ false)
568                     .addAction(Intent.ACTION_PICK)
569                     .addAction(Intent.ACTION_GET_CONTENT)
570                     .addAction(Intent.ACTION_EDIT)
571                     .addAction(Intent.ACTION_INSERT)
572                     .addAction(Intent.ACTION_INSERT_OR_EDIT)
573                     .addAction(Intent.ACTION_OPEN_DOCUMENT)
574                     .addDataType("*/*")
575                     .addCategory(Intent.CATEGORY_DEFAULT)
576                     .addCategory(Intent.CATEGORY_OPENABLE)
577                     .build();
578 
579     private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_DIAL_DATA =
580             new DefaultCrossProfileIntentFilter.Builder(
581                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
582                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
583                     // and FLAG_ALLOW_CHAINED_RESOLUTION set
584                     /* letsPersonalDataIntoProfile= */ false)
585                     .addAction(Intent.ACTION_DIAL)
586                     .addAction(Intent.ACTION_VIEW)
587                     .addCategory(Intent.CATEGORY_DEFAULT)
588                     .addCategory(Intent.CATEGORY_BROWSABLE)
589                     .addDataScheme("tel")
590                     .addDataScheme("sip")
591                     .addDataScheme("voicemail")
592                     .build();
593 
594     private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_DIAL_DATA =
595             new DefaultCrossProfileIntentFilter.Builder(
596                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
597                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
598                     // and FLAG_ALLOW_CHAINED_RESOLUTION set
599                     /* letsPersonalDataIntoProfile= */ false)
600                     .addAction(Intent.ACTION_DIAL)
601                     .addAction(Intent.ACTION_VIEW)
602                     .addCategory(Intent.CATEGORY_DEFAULT)
603                     .addCategory(Intent.CATEGORY_BROWSABLE)
604                     .addDataScheme("tel")
605                     .addDataScheme("sip")
606                     .addDataScheme("voicemail")
607                     .build();
608 
609     private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_SMS_MMS =
610             new DefaultCrossProfileIntentFilter.Builder(
611                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
612                     /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
613                     // and FLAG_ALLOW_CHAINED_RESOLUTION set
614                     /* letsPersonalDataIntoProfile= */ false)
615                     .addAction(Intent.ACTION_VIEW)
616                     .addAction(Intent.ACTION_SENDTO)
617                     .addCategory(Intent.CATEGORY_DEFAULT)
618                     .addCategory(Intent.CATEGORY_BROWSABLE)
619                     .addDataScheme("sms")
620                     .addDataScheme("smsto")
621                     .addDataScheme("mms")
622                     .addDataScheme("mmsto")
623                     .build();
624 
625     private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_ACTION_PICK_IMAGES =
626             new DefaultCrossProfileIntentFilter.Builder(
627                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
628                     /* flags= */ FLAG_IS_PACKAGE_FOR_FILTER | FLAG_ALLOW_CHAINED_RESOLUTION,
629                     /* letsPersonalDataIntoProfile= */ false)
630                     .addAction(MediaStore.ACTION_PICK_IMAGES)
631                     .addCategory(Intent.CATEGORY_DEFAULT)
632                     .build();
633 
634     private static final DefaultCrossProfileIntentFilter
635             CLONE_TO_PARENT_ACTION_PICK_IMAGES_WITH_DATA_TYPES =
636             new DefaultCrossProfileIntentFilter.Builder(
637                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
638                     /* flags= */ FLAG_IS_PACKAGE_FOR_FILTER | FLAG_ALLOW_CHAINED_RESOLUTION,
639                     /* letsPersonalDataIntoProfile= */ false)
640                     .addAction(MediaStore.ACTION_PICK_IMAGES)
641                     .addCategory(Intent.CATEGORY_DEFAULT)
642                     .addDataType("image/*")
643                     .addDataType("video/*")
644                     .build();
645 
646     /** NFC TAG intent is always resolved by the primary user. */
647     static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_NFC_TAG_DISCOVERED =
648             new DefaultCrossProfileIntentFilter.Builder(
649                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
650                     /* flags= */0,
651                     /* letsPersonalDataIntoProfile= */ false)
652                     .addAction(NfcAdapter.ACTION_TAG_DISCOVERED)
653                     .build();
654 
655     /** NFC TAG intent is always resolved by the primary user. */
656     static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_NFC_TECH_DISCOVERED =
657             new DefaultCrossProfileIntentFilter.Builder(
658                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
659                     /* flags= */0,
660                     /* letsPersonalDataIntoProfile= */ false)
661                     .addAction(NfcAdapter.ACTION_TECH_DISCOVERED)
662                     .build();
663 
664     /** NFC TAG intent is always resolved by the primary user. */
665     static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_NFC_NDEF_DISCOVERED =
666             new DefaultCrossProfileIntentFilter.Builder(
667                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
668                     /* flags= */0,
669                     /* letsPersonalDataIntoProfile= */ false)
670                     .addAction(NfcAdapter.ACTION_NDEF_DISCOVERED)
671                     .build();
672 
getDefaultCloneProfileFilters()673     public static List<DefaultCrossProfileIntentFilter> getDefaultCloneProfileFilters() {
674         return Arrays.asList(
675                 PARENT_TO_CLONE_SEND_ACTION,
676                 PARENT_TO_CLONE_WEB_VIEW_ACTION,
677                 PARENT_TO_CLONE_PICK_INSERT_ACTION,
678                 PARENT_TO_CLONE_DIAL_DATA,
679                 CLONE_TO_PARENT_MEDIA_CAPTURE,
680                 CLONE_TO_PARENT_SEND_ACTION,
681                 CLONE_TO_PARENT_WEB_VIEW_ACTION,
682                 CLONE_TO_PARENT_VIEW_ACTION,
683                 CLONE_TO_PARENT_PICK_INSERT_ACTION,
684                 CLONE_TO_PARENT_DIAL_DATA,
685                 CLONE_TO_PARENT_SMS_MMS,
686                 CLONE_TO_PARENT_PHOTOPICKER_SELECTION,
687                 CLONE_TO_PARENT_ACTION_PICK_IMAGES,
688                 CLONE_TO_PARENT_ACTION_PICK_IMAGES_WITH_DATA_TYPES,
689                 PARENT_TO_CLONE_NFC_TAG_DISCOVERED,
690                 PARENT_TO_CLONE_NFC_TECH_DISCOVERED,
691                 PARENT_TO_CLONE_NFC_NDEF_DISCOVERED
692         );
693     }
694 
695     /** Call intent should be handled by the main user. */
696     private static final DefaultCrossProfileIntentFilter CALL_PRIVATE_PROFILE =
697             new DefaultCrossProfileIntentFilter.Builder(
698                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
699                     SKIP_CURRENT_PROFILE,
700                     /* letsPersonalDataIntoProfile= */ false)
701                     .addAction(Intent.ACTION_CALL)
702                     .addCategory(Intent.CATEGORY_DEFAULT)
703                     .addDataScheme("tel")
704                     .addDataScheme("sip")
705                     .addDataScheme("voicemail")
706                     .build();
707 
708     /** Pressing the call button should be handled by the main user. */
709     private static final DefaultCrossProfileIntentFilter CALL_BUTTON_PRIVATE_PROFILE =
710             new DefaultCrossProfileIntentFilter.Builder(
711                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
712                     ONLY_IF_NO_MATCH_FOUND,
713                     /* letsPersonalDataIntoProfile= */ false)
714                     .addAction(Intent.ACTION_CALL_BUTTON)
715                     .addCategory(Intent.CATEGORY_DEFAULT)
716                     .build();
717 
718     /** Dial intent with mime type can be handled by either private profile or its parent user. */
719     private static final DefaultCrossProfileIntentFilter DIAL_MIME_PRIVATE_PROFILE =
720             new DefaultCrossProfileIntentFilter.Builder(
721                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
722                     ONLY_IF_NO_MATCH_FOUND,
723                     /* letsPersonalDataIntoProfile= */ false)
724                     .addAction(Intent.ACTION_DIAL)
725                     .addAction(Intent.ACTION_VIEW)
726                     .addCategory(Intent.CATEGORY_DEFAULT)
727                     .addCategory(Intent.CATEGORY_BROWSABLE)
728                     .addDataType("vnd.android.cursor.item/phone")
729                     .addDataType("vnd.android.cursor.item/phone_v2")
730                     .addDataType("vnd.android.cursor.item/person")
731                     .addDataType("vnd.android.cursor.dir/calls")
732                     .addDataType("vnd.android.cursor.item/calls")
733                     .build();
734 
735     /** Dial intent with data scheme can be handled by either private profile or its parent user. */
736     private static final DefaultCrossProfileIntentFilter DIAL_DATA_PRIVATE_PROFILE =
737             new DefaultCrossProfileIntentFilter.Builder(
738                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
739                     ONLY_IF_NO_MATCH_FOUND,
740                     /* letsPersonalDataIntoProfile= */ false)
741                     .addAction(Intent.ACTION_DIAL)
742                     .addAction(Intent.ACTION_VIEW)
743                     .addCategory(Intent.CATEGORY_DEFAULT)
744                     .addCategory(Intent.CATEGORY_BROWSABLE)
745                     .addDataScheme("tel")
746                     .addDataScheme("sip")
747                     .addDataScheme("voicemail")
748                     .build();
749 
750     /**
751      * Dial intent with no data scheme or type can be handled by either private profile or its
752      * parent user.
753      */
754     private static final DefaultCrossProfileIntentFilter DIAL_RAW_PRIVATE_PROFILE =
755             new DefaultCrossProfileIntentFilter.Builder(
756                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
757                     ONLY_IF_NO_MATCH_FOUND,
758                     /* letsPersonalDataIntoProfile= */ false)
759                     .addAction(Intent.ACTION_DIAL)
760                     .addCategory(Intent.CATEGORY_DEFAULT)
761                     .addCategory(Intent.CATEGORY_BROWSABLE)
762                     .build();
763 
764     /** SMS and MMS are always handled in the main user. */
765     private static final DefaultCrossProfileIntentFilter SMS_MMS_PRIVATE_PROFILE =
766             new DefaultCrossProfileIntentFilter.Builder(
767                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
768                     SKIP_CURRENT_PROFILE,
769                     /* letsPersonalDataIntoProfile= */ false)
770                     .addAction(Intent.ACTION_VIEW)
771                     .addAction(Intent.ACTION_SENDTO)
772                     .addCategory(Intent.CATEGORY_DEFAULT)
773                     .addCategory(Intent.CATEGORY_BROWSABLE)
774                     .addDataScheme("sms")
775                     .addDataScheme("smsto")
776                     .addDataScheme("mms")
777                     .addDataScheme("mmsto")
778                     .build();
779 
getDefaultPrivateProfileFilters()780     public static List<DefaultCrossProfileIntentFilter> getDefaultPrivateProfileFilters() {
781         return Arrays.asList(
782                 DIAL_MIME_PRIVATE_PROFILE,
783                 DIAL_DATA_PRIVATE_PROFILE,
784                 DIAL_RAW_PRIVATE_PROFILE,
785                 CALL_PRIVATE_PROFILE,
786                 CALL_BUTTON_PRIVATE_PROFILE,
787                 EMERGENCY_CALL_DATA,
788                 EMERGENCY_CALL_MIME,
789                 SMS_MMS_PRIVATE_PROFILE
790         );
791     }
792 }
793