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