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 android.content.Intent;
24 import android.hardware.usb.UsbManager;
25 import android.provider.AlarmClock;
26 import android.provider.MediaStore;
27 
28 import java.util.Arrays;
29 import java.util.List;
30 
31 /**
32  * Utility Class for {@link DefaultCrossProfileIntentFilter}.
33  */
34 public class DefaultCrossProfileIntentFiltersUtils {
35 
DefaultCrossProfileIntentFiltersUtils()36     private DefaultCrossProfileIntentFiltersUtils() {
37     }
38 
39     // Intents from profile to parent user
40     /** Emergency call intent with mime type is always resolved by primary user. */
41     private static final DefaultCrossProfileIntentFilter
42             EMERGENCY_CALL_MIME =
43             new DefaultCrossProfileIntentFilter.Builder(
44                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
45                     SKIP_CURRENT_PROFILE,
46                     /* letsPersonalDataIntoProfile= */ false)
47                     .addAction(Intent.ACTION_CALL_EMERGENCY)
48                     .addAction(Intent.ACTION_CALL_PRIVILEGED)
49                     .addCategory(Intent.CATEGORY_DEFAULT)
50                     .addCategory(Intent.CATEGORY_BROWSABLE)
51                     .addDataType("vnd.android.cursor.item/phone")
52                     .addDataType("vnd.android.cursor.item/phone_v2")
53                     .addDataType("vnd.android.cursor.item/person")
54                     .addDataType("vnd.android.cursor.dir/calls")
55                     .addDataType("vnd.android.cursor.item/calls")
56                     .build();
57 
58     /** Emergency call intent with data schemes is always resolved by primary user. */
59     private static final DefaultCrossProfileIntentFilter
60             EMERGENCY_CALL_DATA =
61             new DefaultCrossProfileIntentFilter.Builder(
62                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
63                     SKIP_CURRENT_PROFILE,
64                     /* letsPersonalDataIntoProfile= */ false)
65                     .addAction(Intent.ACTION_CALL_EMERGENCY)
66                     .addAction(Intent.ACTION_CALL_PRIVILEGED)
67                     .addCategory(Intent.CATEGORY_DEFAULT)
68                     .addCategory(Intent.CATEGORY_BROWSABLE)
69                     .addDataScheme("tel")
70                     .addDataScheme("sip")
71                     .addDataScheme("voicemail")
72                     .build();
73 
74     /** Dial intent with mime type can be handled by either managed profile or its parent user. */
75     private static final DefaultCrossProfileIntentFilter DIAL_MIME =
76             new DefaultCrossProfileIntentFilter.Builder(
77                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
78                     ONLY_IF_NO_MATCH_FOUND,
79                     /* letsPersonalDataIntoProfile= */ false)
80                     .addAction(Intent.ACTION_DIAL)
81                     .addAction(Intent.ACTION_VIEW)
82                     .addCategory(Intent.CATEGORY_DEFAULT)
83                     .addCategory(Intent.CATEGORY_BROWSABLE)
84                     .addDataType("vnd.android.cursor.item/phone")
85                     .addDataType("vnd.android.cursor.item/phone_v2")
86                     .addDataType("vnd.android.cursor.item/person")
87                     .addDataType("vnd.android.cursor.dir/calls")
88                     .addDataType("vnd.android.cursor.item/calls")
89                     .build();
90 
91     /** Dial intent with data scheme can be handled by either managed profile or its parent user. */
92     private static final DefaultCrossProfileIntentFilter DIAL_DATA =
93             new DefaultCrossProfileIntentFilter.Builder(
94                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
95                     ONLY_IF_NO_MATCH_FOUND,
96                     /* letsPersonalDataIntoProfile= */ false)
97                     .addAction(Intent.ACTION_DIAL)
98                     .addAction(Intent.ACTION_VIEW)
99                     .addCategory(Intent.CATEGORY_DEFAULT)
100                     .addCategory(Intent.CATEGORY_BROWSABLE)
101                     .addDataScheme("tel")
102                     .addDataScheme("sip")
103                     .addDataScheme("voicemail")
104                     .build();
105 
106     /**
107      * Dial intent with no data scheme or type can be handled by either managed profile or its
108      * parent user.
109      */
110     private static final DefaultCrossProfileIntentFilter DIAL_RAW =
111             new DefaultCrossProfileIntentFilter.Builder(
112                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
113                     ONLY_IF_NO_MATCH_FOUND,
114                     /* letsPersonalDataIntoProfile= */ false)
115                     .addAction(Intent.ACTION_DIAL)
116                     .addCategory(Intent.CATEGORY_DEFAULT)
117                     .addCategory(Intent.CATEGORY_BROWSABLE)
118                     .build();
119 
120     /** Pressing the call button can be handled by either managed profile or its parent user. */
121     private static final DefaultCrossProfileIntentFilter CALL_BUTTON =
122             new DefaultCrossProfileIntentFilter.Builder(
123                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
124                     ONLY_IF_NO_MATCH_FOUND,
125                     /* letsPersonalDataIntoProfile= */ false)
126                     .addAction(Intent.ACTION_CALL_BUTTON)
127                     .addCategory(Intent.CATEGORY_DEFAULT)
128                     .build();
129 
130     /** SMS and MMS are exclusively handled by the primary user. */
131     private static final DefaultCrossProfileIntentFilter SMS_MMS =
132             new DefaultCrossProfileIntentFilter.Builder(
133                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
134                     SKIP_CURRENT_PROFILE,
135                     /* letsPersonalDataIntoProfile= */ false)
136                     .addAction(Intent.ACTION_VIEW)
137                     .addAction(Intent.ACTION_SENDTO)
138                     .addCategory(Intent.CATEGORY_DEFAULT)
139                     .addCategory(Intent.CATEGORY_BROWSABLE)
140                     .addDataScheme("sms")
141                     .addDataScheme("smsto")
142                     .addDataScheme("mms")
143                     .addDataScheme("mmsto")
144                     .build();
145 
146     /** Mobile network settings is always shown in the primary user. */
147     private static final DefaultCrossProfileIntentFilter
148             MOBILE_NETWORK_SETTINGS =
149             new DefaultCrossProfileIntentFilter.Builder(
150                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
151                     SKIP_CURRENT_PROFILE,
152                     /* letsPersonalDataIntoProfile= */ false)
153                     .addAction(android.provider.Settings.ACTION_DATA_ROAMING_SETTINGS)
154                     .addAction(android.provider.Settings.ACTION_NETWORK_OPERATOR_SETTINGS)
155                     .addCategory(Intent.CATEGORY_DEFAULT)
156                     .build();
157 
158     /** HOME intent is always resolved by the primary user. */
159     static final DefaultCrossProfileIntentFilter HOME =
160             new DefaultCrossProfileIntentFilter.Builder(
161                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
162                     SKIP_CURRENT_PROFILE,
163                     /* letsPersonalDataIntoProfile= */ false)
164                     .addAction(Intent.ACTION_MAIN)
165                     .addCategory(Intent.CATEGORY_DEFAULT)
166                     .addCategory(Intent.CATEGORY_HOME)
167                     .build();
168 
169     /** Get content can be forwarded to parent user. */
170     private static final DefaultCrossProfileIntentFilter GET_CONTENT =
171             new DefaultCrossProfileIntentFilter.Builder(
172                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
173                     /* flags= */0,
174                     /* letsPersonalDataIntoProfile= */ true)
175                     .addAction(Intent.ACTION_GET_CONTENT)
176                     .addCategory(Intent.CATEGORY_DEFAULT)
177                     .addCategory(Intent.CATEGORY_OPENABLE)
178                     .addDataType("*/*")
179                     .build();
180 
181     /** Open document intent can be forwarded to parent user. */
182     private static final DefaultCrossProfileIntentFilter OPEN_DOCUMENT =
183             new DefaultCrossProfileIntentFilter.Builder(
184                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
185                     /* flags= */0,
186                     /* letsPersonalDataIntoProfile= */ true)
187                     .addAction(Intent.ACTION_OPEN_DOCUMENT)
188                     .addCategory(Intent.CATEGORY_DEFAULT)
189                     .addCategory(Intent.CATEGORY_OPENABLE)
190                     .addDataType("*/*")
191                     .build();
192 
193     /** Pick for any data type can be forwarded to parent user. */
194     private static final DefaultCrossProfileIntentFilter ACTION_PICK_DATA =
195             new DefaultCrossProfileIntentFilter.Builder(
196                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
197                     /* flags= */0,
198                     /* letsPersonalDataIntoProfile= */ true)
199                     .addAction(Intent.ACTION_PICK)
200                     .addCategory(Intent.CATEGORY_DEFAULT)
201                     .addDataType("*/*")
202                     .build();
203 
204     /** Pick without data type can be forwarded to parent user. */
205     private static final DefaultCrossProfileIntentFilter ACTION_PICK_RAW =
206             new DefaultCrossProfileIntentFilter.Builder(
207                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
208                     /* flags= */0,
209                     /* letsPersonalDataIntoProfile= */ true)
210                     .addAction(Intent.ACTION_PICK)
211                     .addCategory(Intent.CATEGORY_DEFAULT)
212                     .build();
213 
214     /** Speech recognition can be performed by primary user. */
215     private static final DefaultCrossProfileIntentFilter RECOGNIZE_SPEECH =
216             new DefaultCrossProfileIntentFilter.Builder(
217                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
218                     /* flags= */ ONLY_IF_NO_MATCH_FOUND,
219                     /* letsPersonalDataIntoProfile= */ false)
220                     .addAction(ACTION_RECOGNIZE_SPEECH)
221                     .addCategory(Intent.CATEGORY_DEFAULT)
222                     .build();
223 
224     /** Media capture can be performed by primary user. */
225     private static final DefaultCrossProfileIntentFilter MEDIA_CAPTURE =
226             new DefaultCrossProfileIntentFilter.Builder(
227                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
228                     /* flags= */0,
229                     /* letsPersonalDataIntoProfile= */ true)
230                     .addAction(MediaStore.ACTION_IMAGE_CAPTURE)
231                     .addAction(MediaStore.ACTION_IMAGE_CAPTURE_SECURE)
232                     .addAction(MediaStore.ACTION_VIDEO_CAPTURE)
233                     .addAction(MediaStore.Audio.Media.RECORD_SOUND_ACTION)
234                     .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA)
235                     .addAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
236                     .addAction(MediaStore.INTENT_ACTION_VIDEO_CAMERA)
237                     .addCategory(Intent.CATEGORY_DEFAULT)
238                     .build();
239 
240     /** Alarm setting can be performed by primary user. */
241     private static final DefaultCrossProfileIntentFilter SET_ALARM =
242             new DefaultCrossProfileIntentFilter.Builder(
243                     DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
244                     /* flags= */0,
245                     /* letsPersonalDataIntoProfile= */ false)
246                     .addAction(AlarmClock.ACTION_SET_ALARM)
247                     .addAction(AlarmClock.ACTION_SHOW_ALARMS)
248                     .addAction(AlarmClock.ACTION_SET_TIMER)
249                     .addCategory(Intent.CATEGORY_DEFAULT)
250                     .build();
251 
252     // Intents from parent to profile user
253 
254     /** ACTION_SEND can be forwarded to the managed profile on user's choice. */
255     private static final DefaultCrossProfileIntentFilter ACTION_SEND =
256             new DefaultCrossProfileIntentFilter.Builder(
257                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
258                     /* flags= */0,
259                     /* letsPersonalDataIntoProfile= */ true)
260                     .addAction(Intent.ACTION_SEND)
261                     .addAction(Intent.ACTION_SEND_MULTIPLE)
262                     .addCategory(Intent.CATEGORY_DEFAULT)
263                     .addDataType("*/*")
264                     .build();
265 
266     /** USB devices attached can get forwarded to the profile. */
267     private static final DefaultCrossProfileIntentFilter
268             USB_DEVICE_ATTACHED =
269             new DefaultCrossProfileIntentFilter.Builder(
270                     DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
271                     /* flags= */0,
272                     /* letsPersonalDataIntoProfile= */ false)
273                     .addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
274                     .addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)
275                     .addCategory(Intent.CATEGORY_DEFAULT)
276                     .build();
277 
getDefaultManagedProfileFilters()278     public static List<DefaultCrossProfileIntentFilter> getDefaultManagedProfileFilters() {
279         return Arrays.asList(
280                 EMERGENCY_CALL_MIME,
281                 EMERGENCY_CALL_DATA,
282                 DIAL_MIME,
283                 DIAL_DATA,
284                 DIAL_RAW,
285                 CALL_BUTTON,
286                 SMS_MMS,
287                 SET_ALARM,
288                 MEDIA_CAPTURE,
289                 RECOGNIZE_SPEECH,
290                 ACTION_PICK_RAW,
291                 ACTION_PICK_DATA,
292                 OPEN_DOCUMENT,
293                 GET_CONTENT,
294                 USB_DEVICE_ATTACHED,
295                 ACTION_SEND,
296                 HOME,
297                 MOBILE_NETWORK_SETTINGS);
298     }
299 }
300