1 /* 2 * Copyright (C) 2018 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.contentcapture; 18 19 import static android.Manifest.permission.MANAGE_CONTENT_CAPTURE; 20 import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE; 21 import static android.service.contentcapture.ContentCaptureService.ASSIST_CONTENT_ACTIVITY_START_KEY; 22 import static android.service.contentcapture.ContentCaptureService.setClientState; 23 import static android.view.contentcapture.ContentCaptureHelper.toList; 24 import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_DELAY_MS; 25 import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS; 26 import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT; 27 import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE; 28 import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_CONFIG; 29 import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_THRESHOLD; 30 import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_REQUIRED_GROUPS_CONFIG; 31 import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER; 32 import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_ENABLE_ACTIVITY_START_ASSIST_CONTENT; 33 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_FALSE; 34 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_OK; 35 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_SECURITY_EXCEPTION; 36 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_TRUE; 37 import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED; 38 39 import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ACCEPT_DATA_SHARE_REQUEST; 40 import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL; 41 import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CONCURRENT_REQUEST; 42 import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_EMPTY_DATA; 43 import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_IOEXCEPTION; 44 import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_SERVICE_PIPE_FAIL; 45 import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_TIMEOUT_INTERRUPTED; 46 import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_WRITE_FINISHED; 47 import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__REJECT_DATA_SHARE_REQUEST; 48 import static com.android.internal.util.SyncResultReceiver.bundleFor; 49 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT; 50 51 import android.annotation.NonNull; 52 import android.annotation.Nullable; 53 import android.annotation.UserIdInt; 54 import android.app.ActivityManagerInternal; 55 import android.app.ActivityThread; 56 import android.app.admin.DevicePolicyCache; 57 import android.app.assist.ActivityId; 58 import android.app.assist.AssistContent; 59 import android.content.ComponentName; 60 import android.content.ContentCaptureOptions; 61 import android.content.ContentResolver; 62 import android.content.Context; 63 import android.content.Intent; 64 import android.content.pm.ActivityPresentationInfo; 65 import android.content.pm.PackageManager; 66 import android.content.pm.PackageManager.NameNotFoundException; 67 import android.content.pm.ParceledListSlice; 68 import android.content.pm.UserInfo; 69 import android.database.ContentObserver; 70 import android.os.Binder; 71 import android.os.Build; 72 import android.os.Bundle; 73 import android.os.Handler; 74 import android.os.IBinder; 75 import android.os.Looper; 76 import android.os.ParcelFileDescriptor; 77 import android.os.RemoteCallbackList; 78 import android.os.RemoteException; 79 import android.os.ResultReceiver; 80 import android.os.ShellCallback; 81 import android.os.UserHandle; 82 import android.os.UserManager; 83 import android.provider.DeviceConfig; 84 import android.provider.DeviceConfig.Properties; 85 import android.provider.Settings; 86 import android.service.contentcapture.ActivityEvent.ActivityEventType; 87 import android.service.contentcapture.ContentCaptureServiceInfo; 88 import android.service.contentcapture.IDataShareCallback; 89 import android.service.contentcapture.IDataShareReadAdapter; 90 import android.service.voice.VoiceInteractionManagerInternal; 91 import android.util.ArraySet; 92 import android.util.LocalLog; 93 import android.util.Pair; 94 import android.util.Slog; 95 import android.util.SparseArray; 96 import android.util.SparseBooleanArray; 97 import android.view.contentcapture.ContentCaptureCondition; 98 import android.view.contentcapture.ContentCaptureEvent; 99 import android.view.contentcapture.ContentCaptureHelper; 100 import android.view.contentcapture.ContentCaptureManager; 101 import android.view.contentcapture.DataRemovalRequest; 102 import android.view.contentcapture.DataShareRequest; 103 import android.view.contentcapture.IContentCaptureManager; 104 import android.view.contentcapture.IContentCaptureOptionsCallback; 105 import android.view.contentcapture.IDataShareWriteAdapter; 106 107 import com.android.internal.annotations.GuardedBy; 108 import com.android.internal.annotations.VisibleForTesting; 109 import com.android.internal.infra.AbstractRemoteService; 110 import com.android.internal.infra.GlobalWhitelistState; 111 import com.android.internal.os.BackgroundThread; 112 import com.android.internal.os.IResultReceiver; 113 import com.android.internal.util.DumpUtils; 114 import com.android.server.LocalServices; 115 import com.android.server.contentprotection.ContentProtectionAllowlistManager; 116 import com.android.server.contentprotection.ContentProtectionConsentManager; 117 import com.android.server.contentprotection.RemoteContentProtectionService; 118 import com.android.server.infra.AbstractMasterSystemService; 119 import com.android.server.infra.FrameworkResourcesServiceNameResolver; 120 121 import java.io.FileDescriptor; 122 import java.io.IOException; 123 import java.io.InputStream; 124 import java.io.OutputStream; 125 import java.io.PrintWriter; 126 import java.util.ArrayList; 127 import java.util.Arrays; 128 import java.util.Collections; 129 import java.util.HashSet; 130 import java.util.List; 131 import java.util.Objects; 132 import java.util.Set; 133 import java.util.concurrent.Executor; 134 import java.util.concurrent.Executors; 135 import java.util.concurrent.atomic.AtomicBoolean; 136 137 /** 138 * A service used to observe the contents of the screen. 139 * 140 * <p>The data collected by this service can be analyzed on-device and combined 141 * with other sources to provide contextual data in other areas of the system 142 * such as Autofill. 143 */ 144 public class ContentCaptureManagerService extends 145 AbstractMasterSystemService<ContentCaptureManagerService, ContentCapturePerUserService> { 146 147 private static final String TAG = ContentCaptureManagerService.class.getSimpleName(); 148 static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions"; 149 150 private static final int MAX_TEMP_SERVICE_DURATION_MS = 1_000 * 60 * 2; // 2 minutes 151 private static final int MAX_DATA_SHARE_FILE_DESCRIPTORS_TTL_MS = 1_000 * 60 * 5; // 5 minutes 152 private static final int MAX_CONCURRENT_FILE_SHARING_REQUESTS = 10; 153 private static final int DATA_SHARE_BYTE_BUFFER_LENGTH = 1_024; 154 155 private static final String CONTENT_PROTECTION_GROUP_CONFIG_SEPARATOR_GROUP = ";"; 156 private static final String CONTENT_PROTECTION_GROUP_CONFIG_SEPARATOR_VALUE = ","; 157 158 // Needed to pass checkstyle_hook as names are too long for one line. 159 private static final int EVENT__DATA_SHARE_ERROR_CONCURRENT_REQUEST = 160 CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CONCURRENT_REQUEST; 161 private static final int EVENT__DATA_SHARE_ERROR_TIMEOUT_INTERRUPTED = 162 CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_TIMEOUT_INTERRUPTED; 163 private static final int EVENT__DATA_SHARE_WRITE_FINISHED = 164 CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_WRITE_FINISHED; 165 166 private final LocalService mLocalService = new LocalService(); 167 168 private final ContentCaptureManagerServiceStub mContentCaptureManagerServiceStub = 169 new ContentCaptureManagerServiceStub(); 170 171 @Nullable 172 final LocalLog mRequestsHistory; 173 174 @GuardedBy("mLock") 175 private ActivityManagerInternal mAm; 176 177 /** 178 * Users disabled by {@link android.provider.Settings.Secure#CONTENT_CAPTURE_ENABLED} 179 */ 180 @GuardedBy("mLock") 181 @Nullable 182 private SparseBooleanArray mDisabledBySettings; 183 184 /** 185 * Global kill-switch based on value defined by 186 * {@link ContentCaptureManager#DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED}. 187 */ 188 @GuardedBy("mLock") 189 @Nullable 190 private boolean mDisabledByDeviceConfig; 191 192 @GuardedBy("mLock") 193 private boolean activityStartAssistDataEnabled; 194 195 // Device-config settings that are cached and passed back to apps 196 @GuardedBy("mLock") 197 int mDevCfgLoggingLevel; 198 199 @GuardedBy("mLock") 200 int mDevCfgMaxBufferSize; 201 202 @GuardedBy("mLock") 203 int mDevCfgIdleFlushingFrequencyMs; 204 205 @GuardedBy("mLock") 206 int mDevCfgTextChangeFlushingFrequencyMs; 207 208 @GuardedBy("mLock") 209 int mDevCfgLogHistorySize; 210 211 @GuardedBy("mLock") 212 int mDevCfgIdleUnbindTimeoutMs; 213 214 @GuardedBy("mLock") 215 boolean mDevCfgDisableFlushForViewTreeAppearing; 216 217 @GuardedBy("mLock") 218 boolean mDevCfgEnableContentProtectionReceiver; 219 220 @GuardedBy("mLock") 221 int mDevCfgContentProtectionBufferSize; 222 223 @GuardedBy("mLock") 224 @NonNull 225 List<List<String>> mDevCfgContentProtectionRequiredGroups; 226 227 @GuardedBy("mLock") 228 @NonNull 229 List<List<String>> mDevCfgContentProtectionOptionalGroups; 230 231 @GuardedBy("mLock") 232 int mDevCfgContentProtectionOptionalGroupsThreshold; 233 234 @GuardedBy("mLock") 235 long mDevCfgContentProtectionAllowlistDelayMs; 236 237 @GuardedBy("mLock") 238 long mDevCfgContentProtectionAllowlistTimeoutMs; 239 240 @GuardedBy("mLock") 241 long mDevCfgContentProtectionAutoDisconnectTimeoutMs; 242 243 private final Executor mDataShareExecutor = Executors.newCachedThreadPool(); 244 private final Handler mHandler = new Handler(Looper.getMainLooper()); 245 246 @GuardedBy("mLock") 247 private final Set<String> mPackagesWithShareRequests = new HashSet<>(); 248 249 private final RemoteCallbackList<IContentCaptureOptionsCallback> mCallbacks = 250 new RemoteCallbackList<>(); 251 252 final GlobalContentCaptureOptions mGlobalContentCaptureOptions = 253 new GlobalContentCaptureOptions(); 254 255 @GuardedBy("mLock") 256 @Nullable 257 private ComponentName mContentProtectionServiceComponentName; 258 259 @GuardedBy("mLock") 260 @Nullable 261 private ContentProtectionAllowlistManager mContentProtectionAllowlistManager; 262 263 @GuardedBy("mLock") 264 @Nullable 265 private ContentProtectionConsentManager mContentProtectionConsentManager; 266 ContentCaptureManagerService(@onNull Context context)267 public ContentCaptureManagerService(@NonNull Context context) { 268 super(context, new FrameworkResourcesServiceNameResolver(context, 269 com.android.internal.R.string.config_defaultContentCaptureService), 270 UserManager.DISALLOW_CONTENT_CAPTURE, 271 /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_NO_REFRESH); 272 273 mDevCfgContentProtectionRequiredGroups = 274 ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_REQUIRED_GROUPS; 275 mDevCfgContentProtectionOptionalGroups = 276 ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_OPTIONAL_GROUPS; 277 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 278 ActivityThread.currentApplication().getMainExecutor(), 279 (properties) -> onDeviceConfigChange(properties)); 280 setDeviceConfigProperties(); 281 282 if (mDevCfgLogHistorySize > 0) { 283 if (debug) Slog.d(TAG, "log history size: " + mDevCfgLogHistorySize); 284 mRequestsHistory = new LocalLog(mDevCfgLogHistorySize); 285 } else { 286 if (debug) { 287 Slog.d(TAG, "disabled log history because size is " + mDevCfgLogHistorySize); 288 } 289 mRequestsHistory = null; 290 } 291 292 final List<UserInfo> users = getSupportedUsers(); 293 for (int i = 0; i < users.size(); i++) { 294 final int userId = users.get(i).id; 295 final boolean disabled = !isEnabledBySettings(userId); 296 // Sets which services are disabled by settings 297 if (disabled) { 298 Slog.i(TAG, "user " + userId + " disabled by settings"); 299 if (mDisabledBySettings == null) { 300 mDisabledBySettings = new SparseBooleanArray(1); 301 } 302 mDisabledBySettings.put(userId, true); 303 } 304 // Sets the global options for the service. 305 mGlobalContentCaptureOptions.setServiceInfo(userId, 306 mServiceNameResolver.getServiceName(userId), 307 mServiceNameResolver.isTemporary(userId)); 308 } 309 } 310 311 @Override // from AbstractMasterSystemService newServiceLocked(@serIdInt int resolvedUserId, boolean disabled)312 protected ContentCapturePerUserService newServiceLocked(@UserIdInt int resolvedUserId, 313 boolean disabled) { 314 return new ContentCapturePerUserService(this, mLock, disabled, resolvedUserId); 315 } 316 317 @Override // from SystemService isUserSupported(TargetUser user)318 public boolean isUserSupported(TargetUser user) { 319 return user.isFull() || user.isProfile(); 320 } 321 322 @Override // from SystemService onStart()323 public void onStart() { 324 publishBinderService(CONTENT_CAPTURE_MANAGER_SERVICE, mContentCaptureManagerServiceStub); 325 publishLocalService(ContentCaptureManagerInternal.class, mLocalService); 326 } 327 328 @Override // from AbstractMasterSystemService onServiceRemoved(@onNull ContentCapturePerUserService service, @UserIdInt int userId)329 protected void onServiceRemoved(@NonNull ContentCapturePerUserService service, 330 @UserIdInt int userId) { 331 service.destroyLocked(); 332 } 333 334 @Override // from AbstractMasterSystemService onServicePackageUpdatingLocked(int userId)335 protected void onServicePackageUpdatingLocked(int userId) { 336 final ContentCapturePerUserService service = getServiceForUserLocked(userId); 337 if (service != null) { 338 service.onPackageUpdatingLocked(); 339 } 340 } 341 342 @Override // from AbstractMasterSystemService onServicePackageUpdatedLocked(@serIdInt int userId)343 protected void onServicePackageUpdatedLocked(@UserIdInt int userId) { 344 final ContentCapturePerUserService service = getServiceForUserLocked(userId); 345 if (service != null) { 346 service.onPackageUpdatedLocked(); 347 } 348 } 349 350 @Override // from AbstractMasterSystemService onServiceNameChanged(@serIdInt int userId, @NonNull String serviceName, boolean isTemporary)351 protected void onServiceNameChanged(@UserIdInt int userId, @NonNull String serviceName, 352 boolean isTemporary) { 353 mGlobalContentCaptureOptions.setServiceInfo(userId, serviceName, isTemporary); 354 355 super.onServiceNameChanged(userId, serviceName, isTemporary); 356 } 357 358 @Override // from AbstractMasterSystemService enforceCallingPermissionForManagement()359 protected void enforceCallingPermissionForManagement() { 360 getContext().enforceCallingPermission(MANAGE_CONTENT_CAPTURE, TAG); 361 } 362 363 @Override // from AbstractMasterSystemService getMaximumTemporaryServiceDurationMs()364 protected int getMaximumTemporaryServiceDurationMs() { 365 return MAX_TEMP_SERVICE_DURATION_MS; 366 } 367 368 @Override // from AbstractMasterSystemService registerForExtraSettingsChanges(@onNull ContentResolver resolver, @NonNull ContentObserver observer)369 protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver, 370 @NonNull ContentObserver observer) { 371 resolver.registerContentObserver(Settings.Secure.getUriFor( 372 Settings.Secure.CONTENT_CAPTURE_ENABLED), false, observer, 373 UserHandle.USER_ALL); 374 } 375 376 @Override // from AbstractMasterSystemService onSettingsChanged(@serIdInt int userId, @NonNull String property)377 protected void onSettingsChanged(@UserIdInt int userId, @NonNull String property) { 378 switch (property) { 379 case Settings.Secure.CONTENT_CAPTURE_ENABLED: 380 setContentCaptureFeatureEnabledBySettingsForUser(userId, 381 isEnabledBySettings(userId)); 382 return; 383 default: 384 Slog.w(TAG, "Unexpected property (" + property + "); updating cache instead"); 385 } 386 } 387 388 @Override // from AbstractMasterSystemService isDisabledLocked(@serIdInt int userId)389 protected boolean isDisabledLocked(@UserIdInt int userId) { 390 return mDisabledByDeviceConfig || isDisabledBySettingsLocked(userId) 391 || super.isDisabledLocked(userId); 392 } 393 394 @Override assertCalledByPackageOwner(@onNull String packageName)395 protected void assertCalledByPackageOwner(@NonNull String packageName) { 396 try { 397 super.assertCalledByPackageOwner(packageName); 398 } catch (SecurityException e) { 399 final int callingUid = Binder.getCallingUid(); 400 401 VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity 402 hotwordDetectionServiceIdentity = 403 LocalServices.getService(VoiceInteractionManagerInternal.class) 404 .getHotwordDetectionServiceIdentity(); 405 406 if (callingUid != hotwordDetectionServiceIdentity.getIsolatedUid()) { 407 super.assertCalledByPackageOwner(packageName); 408 return; 409 } 410 411 final String[] packages = 412 getContext() 413 .getPackageManager() 414 .getPackagesForUid(hotwordDetectionServiceIdentity.getOwnerUid()); 415 if (packages != null) { 416 for (String candidate : packages) { 417 if (packageName.equals(candidate)) return; // Found it 418 } 419 } 420 421 throw e; 422 } 423 } 424 isDisabledBySettingsLocked(@serIdInt int userId)425 private boolean isDisabledBySettingsLocked(@UserIdInt int userId) { 426 return mDisabledBySettings != null && mDisabledBySettings.get(userId); 427 } 428 isEnabledBySettings(@serIdInt int userId)429 private boolean isEnabledBySettings(@UserIdInt int userId) { 430 final boolean enabled = Settings.Secure.getIntForUser(getContext().getContentResolver(), 431 Settings.Secure.CONTENT_CAPTURE_ENABLED, 1, userId) == 1 ? true : false; 432 return enabled; 433 } 434 onDeviceConfigChange(@onNull Properties properties)435 private void onDeviceConfigChange(@NonNull Properties properties) { 436 for (String key : properties.getKeyset()) { 437 switch (key) { 438 case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED: 439 setDisabledByDeviceConfig(properties.getString(key, null)); 440 return; 441 case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL: 442 setLoggingLevelFromDeviceConfig(); 443 return; 444 case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE: 445 case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY: 446 case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE: 447 case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY: 448 case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT: 449 case ContentCaptureManager 450 .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING: 451 // Content protection below 452 case DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER: 453 case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE: 454 case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_REQUIRED_GROUPS_CONFIG: 455 case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_CONFIG: 456 case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_THRESHOLD: 457 case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_DELAY_MS: 458 case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS: 459 case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT: 460 setFineTuneParamsFromDeviceConfig(); 461 return; 462 case DEVICE_CONFIG_ENABLE_ACTIVITY_START_ASSIST_CONTENT: 463 setActivityStartAssistDataEnabled(); 464 default: 465 Slog.i(TAG, "Ignoring change on " + key); 466 } 467 } 468 } 469 470 /** @hide */ 471 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) setFineTuneParamsFromDeviceConfig()472 protected void setFineTuneParamsFromDeviceConfig() { 473 boolean enableContentProtectionReceiverOld; 474 boolean enableContentProtectionReceiverNew; 475 String contentProtectionRequiredGroupsConfig; 476 String contentProtectionOptionalGroupsConfig; 477 int contentProtectionOptionalGroupsThreshold; 478 long contentProtectionAllowlistDelayMs; 479 long contentProtectionAllowlistTimeoutMs; 480 ContentProtectionAllowlistManager contentProtectionAllowlistManagerOld; 481 482 synchronized (mLock) { 483 mDevCfgMaxBufferSize = 484 DeviceConfig.getInt( 485 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 486 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE, 487 ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE); 488 mDevCfgIdleFlushingFrequencyMs = 489 DeviceConfig.getInt( 490 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 491 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY, 492 ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS); 493 mDevCfgTextChangeFlushingFrequencyMs = 494 DeviceConfig.getInt( 495 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 496 ContentCaptureManager 497 .DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY, 498 ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS); 499 mDevCfgLogHistorySize = 500 DeviceConfig.getInt( 501 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 502 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 503 20); 504 mDevCfgIdleUnbindTimeoutMs = 505 DeviceConfig.getInt( 506 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 507 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT, 508 (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS); 509 mDevCfgDisableFlushForViewTreeAppearing = 510 DeviceConfig.getBoolean( 511 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 512 ContentCaptureManager 513 .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING, 514 false); 515 516 enableContentProtectionReceiverOld = mDevCfgEnableContentProtectionReceiver; 517 enableContentProtectionReceiverNew = getDeviceConfigEnableContentProtectionReceiver(); 518 mDevCfgContentProtectionBufferSize = 519 DeviceConfig.getInt( 520 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 521 DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE, 522 ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE); 523 contentProtectionRequiredGroupsConfig = 524 DeviceConfig.getString( 525 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 526 DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_REQUIRED_GROUPS_CONFIG, 527 ContentCaptureManager 528 .DEFAULT_CONTENT_PROTECTION_REQUIRED_GROUPS_CONFIG); 529 contentProtectionOptionalGroupsConfig = 530 DeviceConfig.getString( 531 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 532 DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_CONFIG, 533 ContentCaptureManager 534 .DEFAULT_CONTENT_PROTECTION_OPTIONAL_GROUPS_CONFIG); 535 contentProtectionOptionalGroupsThreshold = 536 DeviceConfig.getInt( 537 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 538 DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_THRESHOLD, 539 ContentCaptureManager 540 .DEFAULT_CONTENT_PROTECTION_OPTIONAL_GROUPS_THRESHOLD); 541 contentProtectionAllowlistDelayMs = 542 DeviceConfig.getLong( 543 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 544 DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_DELAY_MS, 545 ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_ALLOWLIST_DELAY_MS); 546 contentProtectionAllowlistTimeoutMs = 547 DeviceConfig.getLong( 548 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 549 DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS, 550 ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS); 551 mDevCfgContentProtectionAutoDisconnectTimeoutMs = 552 DeviceConfig.getLong( 553 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 554 DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT, 555 ContentCaptureManager 556 .DEFAULT_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT_MS); 557 contentProtectionAllowlistManagerOld = mContentProtectionAllowlistManager; 558 559 if (verbose) { 560 Slog.v( 561 TAG, 562 "setFineTuneParamsFromDeviceConfig(): " 563 + "bufferSize=" 564 + mDevCfgMaxBufferSize 565 + ", idleFlush=" 566 + mDevCfgIdleFlushingFrequencyMs 567 + ", textFlush=" 568 + mDevCfgTextChangeFlushingFrequencyMs 569 + ", logHistory=" 570 + mDevCfgLogHistorySize 571 + ", idleUnbindTimeoutMs=" 572 + mDevCfgIdleUnbindTimeoutMs 573 + ", disableFlushForViewTreeAppearing=" 574 + mDevCfgDisableFlushForViewTreeAppearing 575 + ", enableContentProtectionReceiver=" 576 + enableContentProtectionReceiverNew 577 + ", contentProtectionBufferSize=" 578 + mDevCfgContentProtectionBufferSize 579 + ", contentProtectionRequiredGroupsConfig=" 580 + contentProtectionRequiredGroupsConfig 581 + ", contentProtectionOptionalGroupsConfig=" 582 + contentProtectionOptionalGroupsConfig 583 + ", contentProtectionOptionalGroupsThreshold=" 584 + contentProtectionOptionalGroupsThreshold 585 + ", contentProtectionAllowlistDelayMs=" 586 + contentProtectionAllowlistDelayMs 587 + ", contentProtectionAllowlistTimeoutMs=" 588 + contentProtectionAllowlistTimeoutMs 589 + ", contentProtectionAutoDisconnectTimeoutMs=" 590 + mDevCfgContentProtectionAutoDisconnectTimeoutMs); 591 } 592 } 593 594 List<List<String>> contentProtectionRequiredGroups = 595 parseContentProtectionGroupsConfig(contentProtectionRequiredGroupsConfig); 596 List<List<String>> contentProtectionOptionalGroups = 597 parseContentProtectionGroupsConfig(contentProtectionOptionalGroupsConfig); 598 ComponentName contentProtectionServiceComponentNameNew = null; 599 ContentProtectionAllowlistManager contentProtectionAllowlistManagerNew = null; 600 ContentProtectionConsentManager contentProtectionConsentManagerNew = null; 601 602 if (contentProtectionAllowlistManagerOld != null && !enableContentProtectionReceiverNew) { 603 contentProtectionAllowlistManagerOld.stop(); 604 } 605 if (!enableContentProtectionReceiverOld && enableContentProtectionReceiverNew) { 606 contentProtectionServiceComponentNameNew = getContentProtectionServiceComponentName(); 607 if (contentProtectionServiceComponentNameNew != null) { 608 contentProtectionAllowlistManagerNew = 609 createContentProtectionAllowlistManager( 610 contentProtectionAllowlistTimeoutMs); 611 contentProtectionAllowlistManagerNew.start(contentProtectionAllowlistDelayMs); 612 contentProtectionConsentManagerNew = createContentProtectionConsentManager(); 613 } 614 } 615 616 synchronized (mLock) { 617 mDevCfgEnableContentProtectionReceiver = enableContentProtectionReceiverNew; 618 mDevCfgContentProtectionRequiredGroups = contentProtectionRequiredGroups; 619 mDevCfgContentProtectionOptionalGroups = contentProtectionOptionalGroups; 620 mDevCfgContentProtectionOptionalGroupsThreshold = 621 contentProtectionOptionalGroupsThreshold; 622 mDevCfgContentProtectionAllowlistDelayMs = contentProtectionAllowlistDelayMs; 623 624 if (enableContentProtectionReceiverOld ^ enableContentProtectionReceiverNew) { 625 mContentProtectionServiceComponentName = contentProtectionServiceComponentNameNew; 626 mContentProtectionAllowlistManager = contentProtectionAllowlistManagerNew; 627 mContentProtectionConsentManager = contentProtectionConsentManagerNew; 628 } 629 } 630 } 631 setLoggingLevelFromDeviceConfig()632 private void setLoggingLevelFromDeviceConfig() { 633 mDevCfgLoggingLevel = DeviceConfig.getInt( 634 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 635 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL, 636 ContentCaptureHelper.getDefaultLoggingLevel()); 637 ContentCaptureHelper.setLoggingLevel(mDevCfgLoggingLevel); 638 verbose = ContentCaptureHelper.sVerbose; 639 debug = ContentCaptureHelper.sDebug; 640 if (verbose) { 641 Slog.v(TAG, "setLoggingLevelFromDeviceConfig(): level=" + mDevCfgLoggingLevel 642 + ", debug=" + debug + ", verbose=" + verbose); 643 } 644 } 645 setDeviceConfigProperties()646 private void setDeviceConfigProperties() { 647 setLoggingLevelFromDeviceConfig(); 648 setFineTuneParamsFromDeviceConfig(); 649 final String enabled = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 650 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED); 651 setDisabledByDeviceConfig(enabled); 652 setActivityStartAssistDataEnabled(); 653 } 654 setActivityStartAssistDataEnabled()655 private void setActivityStartAssistDataEnabled() { 656 synchronized (mLock) { 657 this.activityStartAssistDataEnabled = DeviceConfig.getBoolean( 658 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 659 DEVICE_CONFIG_ENABLE_ACTIVITY_START_ASSIST_CONTENT, false); 660 } 661 } 662 setDisabledByDeviceConfig(@ullable String explicitlyEnabled)663 private void setDisabledByDeviceConfig(@Nullable String explicitlyEnabled) { 664 if (verbose) { 665 Slog.v(TAG, "setDisabledByDeviceConfig(): explicitlyEnabled=" + explicitlyEnabled); 666 } 667 final List<UserInfo> users = getSupportedUsers(); 668 669 final boolean newDisabledValue; 670 671 if (explicitlyEnabled != null && explicitlyEnabled.equalsIgnoreCase("false")) { 672 newDisabledValue = true; 673 } else { 674 newDisabledValue = false; 675 } 676 677 synchronized (mLock) { 678 if (mDisabledByDeviceConfig == newDisabledValue) { 679 if (verbose) { 680 Slog.v(TAG, "setDisabledByDeviceConfig(): already " + newDisabledValue); 681 } 682 return; 683 } 684 mDisabledByDeviceConfig = newDisabledValue; 685 686 Slog.i(TAG, "setDisabledByDeviceConfig(): set to " + mDisabledByDeviceConfig); 687 for (int i = 0; i < users.size(); i++) { 688 final int userId = users.get(i).id; 689 boolean disabled = mDisabledByDeviceConfig || isDisabledBySettingsLocked(userId); 690 Slog.i(TAG, "setDisabledByDeviceConfig(): updating service for user " 691 + userId + " to " + (disabled ? "'disabled'" : "'enabled'")); 692 updateCachedServiceLocked(userId, disabled); 693 } 694 } 695 } 696 setContentCaptureFeatureEnabledBySettingsForUser(@serIdInt int userId, boolean enabled)697 private void setContentCaptureFeatureEnabledBySettingsForUser(@UserIdInt int userId, 698 boolean enabled) { 699 synchronized (mLock) { 700 if (mDisabledBySettings == null) { 701 mDisabledBySettings = new SparseBooleanArray(); 702 } 703 final boolean alreadyEnabled = !mDisabledBySettings.get(userId); 704 if (!(enabled ^ alreadyEnabled)) { 705 if (debug) { 706 Slog.d(TAG, "setContentCaptureFeatureEnabledForUser(): already " + enabled); 707 } 708 return; 709 } 710 if (enabled) { 711 Slog.i(TAG, "setContentCaptureFeatureEnabled(): enabling service for user " 712 + userId); 713 mDisabledBySettings.delete(userId); 714 } else { 715 Slog.i(TAG, "setContentCaptureFeatureEnabled(): disabling service for user " 716 + userId); 717 mDisabledBySettings.put(userId, true); 718 } 719 final boolean disabled = !enabled || mDisabledByDeviceConfig; 720 updateCachedServiceLocked(userId, disabled); 721 } 722 } 723 724 // Called by Shell command. destroySessions(@serIdInt int userId, @NonNull IResultReceiver receiver)725 void destroySessions(@UserIdInt int userId, @NonNull IResultReceiver receiver) { 726 Slog.i(TAG, "destroySessions() for userId " + userId); 727 enforceCallingPermissionForManagement(); 728 729 synchronized (mLock) { 730 if (userId != UserHandle.USER_ALL) { 731 final ContentCapturePerUserService service = peekServiceForUserLocked(userId); 732 if (service != null) { 733 service.destroySessionsLocked(); 734 } 735 } else { 736 visitServicesLocked((s) -> s.destroySessionsLocked()); 737 } 738 } 739 740 try { 741 receiver.send(0, new Bundle()); 742 } catch (RemoteException e) { 743 // Just ignore it... 744 } 745 } 746 747 // Called by Shell command. listSessions(int userId, IResultReceiver receiver)748 void listSessions(int userId, IResultReceiver receiver) { 749 Slog.i(TAG, "listSessions() for userId " + userId); 750 enforceCallingPermissionForManagement(); 751 752 final Bundle resultData = new Bundle(); 753 final ArrayList<String> sessions = new ArrayList<>(); 754 755 synchronized (mLock) { 756 if (userId != UserHandle.USER_ALL) { 757 final ContentCapturePerUserService service = peekServiceForUserLocked(userId); 758 if (service != null) { 759 service.listSessionsLocked(sessions); 760 } 761 } else { 762 visitServicesLocked((s) -> s.listSessionsLocked(sessions)); 763 } 764 } 765 766 resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions); 767 try { 768 receiver.send(0, resultData); 769 } catch (RemoteException e) { 770 // Just ignore it... 771 } 772 } 773 updateOptions(String packageName, ContentCaptureOptions options)774 void updateOptions(String packageName, ContentCaptureOptions options) { 775 mCallbacks.broadcast((callback, pkg) -> { 776 if (pkg.equals(packageName)) { 777 try { 778 callback.setContentCaptureOptions(options); 779 } catch (RemoteException e) { 780 Slog.w(TAG, "Unable to send setContentCaptureOptions(): " + e); 781 } 782 } 783 }); 784 } 785 getAmInternal()786 private ActivityManagerInternal getAmInternal() { 787 synchronized (mLock) { 788 if (mAm == null) { 789 mAm = LocalServices.getService(ActivityManagerInternal.class); 790 } 791 } 792 return mAm; 793 } 794 795 @GuardedBy("mLock") assertCalledByServiceLocked(@onNull String methodName)796 private void assertCalledByServiceLocked(@NonNull String methodName) { 797 if (!isCalledByServiceLocked(methodName)) { 798 throw new SecurityException("caller is not user's ContentCapture service"); 799 } 800 } 801 802 @GuardedBy("mLock") isCalledByServiceLocked(@onNull String methodName)803 private boolean isCalledByServiceLocked(@NonNull String methodName) { 804 final int userId = UserHandle.getCallingUserId(); 805 final int callingUid = Binder.getCallingUid(); 806 final String serviceName = mServiceNameResolver.getServiceName(userId); 807 if (serviceName == null) { 808 Slog.e(TAG, methodName + ": called by UID " + callingUid 809 + ", but there's no service set for user " + userId); 810 return false; 811 } 812 813 final ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName); 814 if (serviceComponent == null) { 815 Slog.w(TAG, methodName + ": invalid service name: " + serviceName); 816 return false; 817 } 818 819 final String servicePackageName = serviceComponent.getPackageName(); 820 821 final PackageManager pm = getContext().getPackageManager(); 822 final int serviceUid; 823 try { 824 serviceUid = pm.getPackageUidAsUser(servicePackageName, UserHandle.getCallingUserId()); 825 } catch (NameNotFoundException e) { 826 Slog.w(TAG, methodName + ": could not verify UID for " + serviceName); 827 return false; 828 } 829 if (callingUid != serviceUid) { 830 Slog.e(TAG, methodName + ": called by UID " + callingUid + ", but service UID is " 831 + serviceUid); 832 return false; 833 } 834 835 return true; 836 } 837 838 /** 839 * Executes the given {@code runnable} and if it throws a {@link SecurityException}, 840 * send it back to the receiver. 841 * 842 * @return whether the exception was thrown or not. 843 */ throwsSecurityException(@onNull IResultReceiver result, @NonNull Runnable runable)844 private boolean throwsSecurityException(@NonNull IResultReceiver result, 845 @NonNull Runnable runable) { 846 try { 847 runable.run(); 848 return false; 849 } catch (SecurityException e) { 850 try { 851 result.send(RESULT_CODE_SECURITY_EXCEPTION, bundleFor(e.getMessage())); 852 } catch (RemoteException e2) { 853 Slog.w(TAG, "Unable to send security exception (" + e + "): ", e2); 854 } 855 } 856 return true; 857 } 858 859 @GuardedBy("mLock") isDefaultServiceLocked(int userId)860 private boolean isDefaultServiceLocked(int userId) { 861 final String defaultServiceName = mServiceNameResolver.getDefaultServiceName(userId); 862 if (defaultServiceName == null) { 863 return false; 864 } 865 866 final String currentServiceName = mServiceNameResolver.getServiceName(userId); 867 return defaultServiceName.equals(currentServiceName); 868 } 869 870 @Override // from AbstractMasterSystemService 871 @GuardedBy("mLock") dumpLocked(String prefix, PrintWriter pw)872 protected void dumpLocked(String prefix, PrintWriter pw) { 873 super.dumpLocked(prefix, pw); 874 875 final String prefix2 = prefix + " "; 876 877 pw.print(prefix); 878 pw.print("Users disabled by Settings: "); 879 pw.println(mDisabledBySettings); 880 pw.print(prefix); 881 pw.println("DeviceConfig Settings: "); 882 pw.print(prefix2); 883 pw.print("disabled: "); 884 pw.println(mDisabledByDeviceConfig); 885 pw.print(prefix2); 886 pw.print("loggingLevel: "); 887 pw.println(mDevCfgLoggingLevel); 888 pw.print(prefix2); 889 pw.print("maxBufferSize: "); 890 pw.println(mDevCfgMaxBufferSize); 891 pw.print(prefix2); 892 pw.print("idleFlushingFrequencyMs: "); 893 pw.println(mDevCfgIdleFlushingFrequencyMs); 894 pw.print(prefix2); 895 pw.print("textChangeFlushingFrequencyMs: "); 896 pw.println(mDevCfgTextChangeFlushingFrequencyMs); 897 pw.print(prefix2); 898 pw.print("logHistorySize: "); 899 pw.println(mDevCfgLogHistorySize); 900 pw.print(prefix2); 901 pw.print("idleUnbindTimeoutMs: "); 902 pw.println(mDevCfgIdleUnbindTimeoutMs); 903 pw.print(prefix2); 904 pw.print("disableFlushForViewTreeAppearing: "); 905 pw.println(mDevCfgDisableFlushForViewTreeAppearing); 906 pw.print(prefix2); 907 pw.print("enableContentProtectionReceiver: "); 908 pw.println(mDevCfgEnableContentProtectionReceiver); 909 pw.print(prefix2); 910 pw.print("contentProtectionBufferSize: "); 911 pw.println(mDevCfgContentProtectionBufferSize); 912 pw.print(prefix2); 913 pw.print("contentProtectionRequiredGroupsSize: "); 914 pw.println(mDevCfgContentProtectionRequiredGroups.size()); 915 pw.print(prefix2); 916 pw.print("contentProtectionOptionalGroupsSize: "); 917 pw.println(mDevCfgContentProtectionOptionalGroups.size()); 918 pw.print(prefix2); 919 pw.print("contentProtectionOptionalGroupsThreshold: "); 920 pw.println(mDevCfgContentProtectionOptionalGroupsThreshold); 921 pw.print(prefix2); 922 pw.print("contentProtectionAllowlistDelayMs: "); 923 pw.println(mDevCfgContentProtectionAllowlistDelayMs); 924 pw.print(prefix2); 925 pw.print("contentProtectionAllowlistTimeoutMs: "); 926 pw.println(mDevCfgContentProtectionAllowlistTimeoutMs); 927 pw.print(prefix2); 928 pw.print("contentProtectionAutoDisconnectTimeoutMs: "); 929 pw.println(mDevCfgContentProtectionAutoDisconnectTimeoutMs); 930 pw.print(prefix2); 931 pw.print("activityStartAssistDataEnabled: "); 932 pw.println(activityStartAssistDataEnabled); 933 pw.print(prefix); 934 pw.println("Global Options:"); 935 mGlobalContentCaptureOptions.dump(prefix2, pw); 936 } 937 938 /** @hide */ 939 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getDeviceConfigEnableContentProtectionReceiver()940 protected boolean getDeviceConfigEnableContentProtectionReceiver() { 941 return DeviceConfig.getBoolean( 942 DeviceConfig.NAMESPACE_CONTENT_CAPTURE, 943 ContentCaptureManager.DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER, 944 ContentCaptureManager.DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER); 945 } 946 947 /** @hide */ 948 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 949 @NonNull createContentProtectionAllowlistManager( long timeoutMs)950 protected ContentProtectionAllowlistManager createContentProtectionAllowlistManager( 951 long timeoutMs) { 952 // Same handler as used by AbstractMasterSystemService 953 return new ContentProtectionAllowlistManager( 954 this, BackgroundThread.getHandler(), timeoutMs); 955 } 956 957 /** @hide */ 958 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 959 @NonNull createContentProtectionConsentManager()960 protected ContentProtectionConsentManager createContentProtectionConsentManager() { 961 // Same handler as used by AbstractMasterSystemService 962 return new ContentProtectionConsentManager( 963 BackgroundThread.getHandler(), 964 getContext().getContentResolver(), 965 DevicePolicyCache.getInstance()); 966 } 967 968 @Nullable getContentProtectionServiceComponentName()969 private ComponentName getContentProtectionServiceComponentName() { 970 String flatComponentName = getContentProtectionServiceFlatComponentName(); 971 if (flatComponentName == null) { 972 return null; 973 } 974 return ComponentName.unflattenFromString(flatComponentName); 975 } 976 977 /** @hide */ 978 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 979 @Nullable getContentProtectionServiceFlatComponentName()980 protected String getContentProtectionServiceFlatComponentName() { 981 return getContext() 982 .getString(com.android.internal.R.string.config_defaultContentProtectionService); 983 } 984 985 /** 986 * Can also throw runtime exceptions such as {@link SecurityException}. 987 * 988 * @hide 989 */ 990 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 991 @NonNull createContentProtectionServiceInfo( @onNull ComponentName componentName)992 protected ContentCaptureServiceInfo createContentProtectionServiceInfo( 993 @NonNull ComponentName componentName) throws PackageManager.NameNotFoundException { 994 return new ContentCaptureServiceInfo( 995 getContext(), componentName, /* isTemp= */ false, UserHandle.getCallingUserId()); 996 } 997 998 /** @hide */ 999 @Nullable createRemoteContentProtectionService()1000 public RemoteContentProtectionService createRemoteContentProtectionService() { 1001 ComponentName componentName; 1002 long autoDisconnectTimeoutMs; 1003 synchronized (mLock) { 1004 if (!mDevCfgEnableContentProtectionReceiver 1005 || mContentProtectionServiceComponentName == null) { 1006 return null; 1007 } 1008 componentName = mContentProtectionServiceComponentName; 1009 autoDisconnectTimeoutMs = mDevCfgContentProtectionAutoDisconnectTimeoutMs; 1010 } 1011 1012 // Check permissions by trying to construct {@link ContentCaptureServiceInfo} 1013 try { 1014 createContentProtectionServiceInfo(componentName); 1015 } catch (Exception ex) { 1016 // Swallow, exception was already logged 1017 return null; 1018 } 1019 1020 return createRemoteContentProtectionService(componentName, autoDisconnectTimeoutMs); 1021 } 1022 1023 /** @hide */ 1024 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1025 @NonNull createRemoteContentProtectionService( @onNull ComponentName componentName, long autoDisconnectTimeoutMs)1026 protected RemoteContentProtectionService createRemoteContentProtectionService( 1027 @NonNull ComponentName componentName, long autoDisconnectTimeoutMs) { 1028 return new RemoteContentProtectionService( 1029 getContext(), 1030 componentName, 1031 UserHandle.getCallingUserId(), 1032 isBindInstantServiceAllowed(), 1033 autoDisconnectTimeoutMs); 1034 } 1035 1036 /** @hide */ 1037 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1038 @NonNull getContentCaptureManagerServiceStub()1039 protected ContentCaptureManagerServiceStub getContentCaptureManagerServiceStub() { 1040 return mContentCaptureManagerServiceStub; 1041 } 1042 1043 /** 1044 * Parses a simple config in format "group;group" where each "group" is itself in the format of 1045 * "string1,string2", eg: 1046 * 1047 * <p>"a" -> [["a"]] 1048 * 1049 * <p>"a,b" -> [["a", "b"]] 1050 * 1051 * <p>"a,b;c;d,e" -> [["a", "b"], ["c"], ["d", "e"]] 1052 * 1053 * @hide 1054 */ 1055 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 1056 @NonNull parseContentProtectionGroupsConfig(@ullable String config)1057 protected List<List<String>> parseContentProtectionGroupsConfig(@Nullable String config) { 1058 if (verbose) { 1059 Slog.v(TAG, "parseContentProtectionGroupsConfig: " + config); 1060 } 1061 if (config == null) { 1062 return Collections.emptyList(); 1063 } 1064 return Arrays.stream(config.split(CONTENT_PROTECTION_GROUP_CONFIG_SEPARATOR_GROUP)) 1065 .map(this::parseContentProtectionGroupConfigValues) 1066 .filter(group -> !group.isEmpty()) 1067 .toList(); 1068 } 1069 parseContentProtectionGroupConfigValues(@onNull String group)1070 private List<String> parseContentProtectionGroupConfigValues(@NonNull String group) { 1071 return Arrays.stream(group.split(CONTENT_PROTECTION_GROUP_CONFIG_SEPARATOR_VALUE)) 1072 .filter(value -> !value.isEmpty()) 1073 .toList(); 1074 } 1075 1076 @GuardedBy("mLock") isContentProtectionEnabledLocked()1077 private boolean isContentProtectionEnabledLocked() { 1078 return mDevCfgEnableContentProtectionReceiver 1079 && mContentProtectionServiceComponentName != null 1080 && mContentProtectionAllowlistManager != null 1081 && mContentProtectionConsentManager != null 1082 && !(mDevCfgContentProtectionRequiredGroups.isEmpty() 1083 && mDevCfgContentProtectionOptionalGroups.isEmpty()); 1084 } 1085 1086 final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub { 1087 1088 @Override startSession(@onNull IBinder activityToken, @NonNull IBinder shareableActivityToken, @NonNull ComponentName componentName, int sessionId, int flags, @NonNull IResultReceiver result)1089 public void startSession(@NonNull IBinder activityToken, 1090 @NonNull IBinder shareableActivityToken, @NonNull ComponentName componentName, 1091 int sessionId, int flags, @NonNull IResultReceiver result) { 1092 Objects.requireNonNull(activityToken); 1093 Objects.requireNonNull(shareableActivityToken); 1094 final int userId = UserHandle.getCallingUserId(); 1095 1096 final ActivityPresentationInfo activityPresentationInfo = getAmInternal() 1097 .getActivityPresentationInfo(activityToken); 1098 1099 synchronized (mLock) { 1100 final ContentCapturePerUserService service = getServiceForUserLocked(userId); 1101 if (!isDefaultServiceLocked(userId) && !isCalledByServiceLocked("startSession()")) { 1102 setClientState(result, STATE_DISABLED, /* binder= */ null); 1103 return; 1104 } 1105 service.startSessionLocked(activityToken, shareableActivityToken, 1106 activityPresentationInfo, sessionId, Binder.getCallingUid(), flags, result); 1107 } 1108 } 1109 1110 @Override finishSession(int sessionId)1111 public void finishSession(int sessionId) { 1112 final int userId = UserHandle.getCallingUserId(); 1113 1114 synchronized (mLock) { 1115 final ContentCapturePerUserService service = getServiceForUserLocked(userId); 1116 service.finishSessionLocked(sessionId); 1117 } 1118 } 1119 1120 @Override getServiceComponentName(@onNull IResultReceiver result)1121 public void getServiceComponentName(@NonNull IResultReceiver result) { 1122 final int userId = UserHandle.getCallingUserId(); 1123 ComponentName connectedServiceComponentName; 1124 synchronized (mLock) { 1125 final ContentCapturePerUserService service = getServiceForUserLocked(userId); 1126 connectedServiceComponentName = service.getServiceComponentName(); 1127 } 1128 try { 1129 result.send(RESULT_CODE_OK, bundleFor(connectedServiceComponentName)); 1130 } catch (RemoteException e) { 1131 Slog.w(TAG, "Unable to send service component name: " + e); 1132 } 1133 } 1134 1135 @Override removeData(@onNull DataRemovalRequest request)1136 public void removeData(@NonNull DataRemovalRequest request) { 1137 Objects.requireNonNull(request); 1138 assertCalledByPackageOwner(request.getPackageName()); 1139 1140 final int userId = UserHandle.getCallingUserId(); 1141 synchronized (mLock) { 1142 final ContentCapturePerUserService service = getServiceForUserLocked(userId); 1143 service.removeDataLocked(request); 1144 } 1145 } 1146 1147 @Override shareData(@onNull DataShareRequest request, @NonNull IDataShareWriteAdapter clientAdapter)1148 public void shareData(@NonNull DataShareRequest request, 1149 @NonNull IDataShareWriteAdapter clientAdapter) { 1150 Objects.requireNonNull(request); 1151 Objects.requireNonNull(clientAdapter); 1152 1153 assertCalledByPackageOwner(request.getPackageName()); 1154 1155 final int userId = UserHandle.getCallingUserId(); 1156 synchronized (mLock) { 1157 final ContentCapturePerUserService service = getServiceForUserLocked(userId); 1158 1159 if (mPackagesWithShareRequests.size() >= MAX_CONCURRENT_FILE_SHARING_REQUESTS 1160 || mPackagesWithShareRequests.contains(request.getPackageName())) { 1161 try { 1162 String serviceName = mServiceNameResolver.getServiceName(userId); 1163 ContentCaptureMetricsLogger.writeServiceEvent( 1164 EVENT__DATA_SHARE_ERROR_CONCURRENT_REQUEST, 1165 serviceName); 1166 clientAdapter.error( 1167 ContentCaptureManager.DATA_SHARE_ERROR_CONCURRENT_REQUEST); 1168 } catch (RemoteException e) { 1169 Slog.e(TAG, "Failed to send error message to client"); 1170 } 1171 return; 1172 } 1173 1174 service.onDataSharedLocked(request, 1175 new DataShareCallbackDelegate(request, clientAdapter, 1176 ContentCaptureManagerService.this)); 1177 } 1178 } 1179 1180 @Override isContentCaptureFeatureEnabled(@onNull IResultReceiver result)1181 public void isContentCaptureFeatureEnabled(@NonNull IResultReceiver result) { 1182 boolean enabled; 1183 synchronized (mLock) { 1184 if (throwsSecurityException(result, 1185 () -> assertCalledByServiceLocked("isContentCaptureFeatureEnabled()"))) { 1186 return; 1187 } 1188 1189 final int userId = UserHandle.getCallingUserId(); 1190 enabled = !mDisabledByDeviceConfig && !isDisabledBySettingsLocked(userId); 1191 } 1192 try { 1193 result.send(enabled ? RESULT_CODE_TRUE : RESULT_CODE_FALSE, /* resultData= */null); 1194 } catch (RemoteException e) { 1195 Slog.w(TAG, "Unable to send isContentCaptureFeatureEnabled(): " + e); 1196 } 1197 } 1198 1199 @Override getServiceSettingsActivity(@onNull IResultReceiver result)1200 public void getServiceSettingsActivity(@NonNull IResultReceiver result) { 1201 if (throwsSecurityException(result, () -> enforceCallingPermissionForManagement())) { 1202 return; 1203 } 1204 1205 final int userId = UserHandle.getCallingUserId(); 1206 final ComponentName componentName; 1207 synchronized (mLock) { 1208 final ContentCapturePerUserService service = getServiceForUserLocked(userId); 1209 if (service == null) return; 1210 componentName = service.getServiceSettingsActivityLocked(); 1211 } 1212 try { 1213 result.send(RESULT_CODE_OK, bundleFor(componentName)); 1214 } catch (RemoteException e) { 1215 Slog.w(TAG, "Unable to send getServiceSettingsIntent(): " + e); 1216 } 1217 } 1218 1219 @Override getContentCaptureConditions(@onNull String packageName, @NonNull IResultReceiver result)1220 public void getContentCaptureConditions(@NonNull String packageName, 1221 @NonNull IResultReceiver result) { 1222 if (throwsSecurityException(result, () -> assertCalledByPackageOwner(packageName))) { 1223 return; 1224 } 1225 1226 final int userId = UserHandle.getCallingUserId(); 1227 final ArrayList<ContentCaptureCondition> conditions; 1228 synchronized (mLock) { 1229 final ContentCapturePerUserService service = getServiceForUserLocked(userId); 1230 conditions = service == null ? null 1231 : toList(service.getContentCaptureConditionsLocked(packageName)); 1232 } 1233 try { 1234 result.send(RESULT_CODE_OK, bundleFor(conditions)); 1235 } catch (RemoteException e) { 1236 Slog.w(TAG, "Unable to send getServiceComponentName(): " + e); 1237 } 1238 } 1239 1240 @Override registerContentCaptureOptionsCallback(@onNull String packageName, IContentCaptureOptionsCallback callback)1241 public void registerContentCaptureOptionsCallback(@NonNull String packageName, 1242 IContentCaptureOptionsCallback callback) { 1243 assertCalledByPackageOwner(packageName); 1244 1245 mCallbacks.register(callback, packageName); 1246 1247 // Set options here in case it was updated before this was registered. 1248 final int userId = UserHandle.getCallingUserId(); 1249 final ContentCaptureOptions options = mGlobalContentCaptureOptions.getOptions(userId, 1250 packageName); 1251 if (options != null) { 1252 try { 1253 callback.setContentCaptureOptions(options); 1254 } catch (RemoteException e) { 1255 Slog.w(TAG, "Unable to send setContentCaptureOptions(): " + e); 1256 } 1257 } 1258 } 1259 1260 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1261 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1262 if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return; 1263 1264 boolean showHistory = true; 1265 if (args != null) { 1266 for (String arg : args) { 1267 switch (arg) { 1268 case "--no-history": 1269 showHistory = false; 1270 break; 1271 case "--help": 1272 pw.println("Usage: dumpsys content_capture [--no-history]"); 1273 return; 1274 default: 1275 Slog.w(TAG, "Ignoring invalid dump arg: " + arg); 1276 } 1277 } 1278 } 1279 1280 synchronized (mLock) { 1281 dumpLocked("", pw); 1282 } 1283 pw.print("Requests history: "); 1284 if (mRequestsHistory == null) { 1285 pw.println("disabled by device config"); 1286 } else if (showHistory) { 1287 pw.println(); 1288 mRequestsHistory.reverseDump(fd, pw, args); 1289 pw.println(); 1290 } else { 1291 pw.println(); 1292 } 1293 } 1294 1295 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)1296 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 1297 String[] args, ShellCallback callback, ResultReceiver resultReceiver) 1298 throws RemoteException { 1299 new ContentCaptureManagerServiceShellCommand(ContentCaptureManagerService.this).exec( 1300 this, in, out, err, args, callback, resultReceiver); 1301 } 1302 1303 @Override resetTemporaryService(@serIdInt int userId)1304 public void resetTemporaryService(@UserIdInt int userId) { 1305 ContentCaptureManagerService.this.resetTemporaryService(userId); 1306 } 1307 1308 @Override setTemporaryService( @serIdInt int userId, @NonNull String serviceName, int duration)1309 public void setTemporaryService( 1310 @UserIdInt int userId, @NonNull String serviceName, int duration) { 1311 ContentCaptureManagerService.this.setTemporaryService( 1312 userId, serviceName, duration); 1313 } 1314 1315 @Override setDefaultServiceEnabled(@serIdInt int userId, boolean enabled)1316 public void setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) { 1317 ContentCaptureManagerService.this.setDefaultServiceEnabled(userId, enabled); 1318 } 1319 1320 @Override onLoginDetected(@onNull ParceledListSlice<ContentCaptureEvent> events)1321 public void onLoginDetected(@NonNull ParceledListSlice<ContentCaptureEvent> events) { 1322 Binder.withCleanCallingIdentity( 1323 () -> { 1324 RemoteContentProtectionService service = 1325 createRemoteContentProtectionService(); 1326 if (service == null) { 1327 return; 1328 } 1329 try { 1330 service.onLoginDetected(events); 1331 } catch (Exception ex) { 1332 Slog.e(TAG, "Failed to call remote service", ex); 1333 } 1334 }); 1335 } 1336 } 1337 1338 private final class LocalService extends ContentCaptureManagerInternal { 1339 1340 @Override isContentCaptureServiceForUser(int uid, @UserIdInt int userId)1341 public boolean isContentCaptureServiceForUser(int uid, @UserIdInt int userId) { 1342 synchronized (mLock) { 1343 final ContentCapturePerUserService service = peekServiceForUserLocked(userId); 1344 if (service != null) { 1345 return service.isContentCaptureServiceForUserLocked(uid); 1346 } 1347 } 1348 return false; 1349 } 1350 1351 @Override 1352 @SuppressWarnings("GuardedBy") sendActivityStartAssistData(@serIdInt int userId, @NonNull IBinder activityToken, @NonNull Intent intentData)1353 public boolean sendActivityStartAssistData(@UserIdInt int userId, 1354 @NonNull IBinder activityToken, 1355 @NonNull Intent intentData) { 1356 synchronized (mLock) { 1357 if (!activityStartAssistDataEnabled) { 1358 return false; 1359 } 1360 Intent intent = new Intent(intentData); 1361 intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION 1362 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)); 1363 Bundle assistContentExtras = new Bundle(); 1364 assistContentExtras.putBoolean(ASSIST_CONTENT_ACTIVITY_START_KEY, true); 1365 AssistContent assistContent = new AssistContent(assistContentExtras); 1366 assistContent.setDefaultIntent(intent); 1367 1368 final Bundle activityAssistData = new Bundle(); 1369 activityAssistData.putParcelable(ASSIST_KEY_CONTENT, assistContent); 1370 final ContentCapturePerUserService service = peekServiceForUserLocked(userId); 1371 if (service != null) { 1372 return service.sendActivityAssistDataLocked(activityToken, activityAssistData); 1373 } 1374 } 1375 return false; 1376 } 1377 1378 @Override sendActivityAssistData(@serIdInt int userId, @NonNull IBinder activityToken, @NonNull Bundle data)1379 public boolean sendActivityAssistData(@UserIdInt int userId, @NonNull IBinder activityToken, 1380 @NonNull Bundle data) { 1381 synchronized (mLock) { 1382 final ContentCapturePerUserService service = peekServiceForUserLocked(userId); 1383 if (service != null) { 1384 return service.sendActivityAssistDataLocked(activityToken, data); 1385 } 1386 } 1387 return false; 1388 } 1389 1390 @Override getOptionsForPackage(int userId, @NonNull String packageName)1391 public ContentCaptureOptions getOptionsForPackage(int userId, @NonNull String packageName) { 1392 return mGlobalContentCaptureOptions.getOptions(userId, packageName); 1393 } 1394 1395 // ErrorProne says ContentCaptureManagerService.this.mLock needs to be guarded by 1396 // 'service.mLock', which is the same as mLock. 1397 @SuppressWarnings("GuardedBy") 1398 @Override notifyActivityEvent(int userId, @NonNull ComponentName activityComponent, @ActivityEventType int eventType, @NonNull ActivityId activityId)1399 public void notifyActivityEvent(int userId, @NonNull ComponentName activityComponent, 1400 @ActivityEventType int eventType, @NonNull ActivityId activityId) { 1401 synchronized (mLock) { 1402 final ContentCapturePerUserService service = peekServiceForUserLocked(userId); 1403 if (service != null) { 1404 service.onActivityEventLocked(activityId, activityComponent, eventType); 1405 } 1406 } 1407 } 1408 } 1409 1410 /** 1411 * Content capture options associated with all services. 1412 * 1413 * <p>This object is defined here instead of on each {@link ContentCapturePerUserService} 1414 * because it cannot hold a lock on the main lock when 1415 * {@link GlobalContentCaptureOptions#getOptions(int, String)} is called by external services. 1416 */ 1417 final class GlobalContentCaptureOptions extends GlobalWhitelistState { 1418 1419 @GuardedBy("mGlobalWhitelistStateLock") 1420 private final SparseArray<String> mServicePackages = new SparseArray<>(); 1421 @GuardedBy("mGlobalWhitelistStateLock") 1422 private final SparseBooleanArray mTemporaryServices = new SparseBooleanArray(); 1423 setServiceInfo(@serIdInt int userId, @Nullable String serviceName, boolean isTemporary)1424 private void setServiceInfo(@UserIdInt int userId, @Nullable String serviceName, 1425 boolean isTemporary) { 1426 synchronized (mGlobalWhitelistStateLock) { 1427 if (isTemporary) { 1428 mTemporaryServices.put(userId, true); 1429 } else { 1430 mTemporaryServices.delete(userId); 1431 } 1432 if (serviceName != null) { 1433 final ComponentName componentName = 1434 ComponentName.unflattenFromString(serviceName); 1435 if (componentName == null) { 1436 Slog.w(TAG, "setServiceInfo(): invalid name: " + serviceName); 1437 mServicePackages.remove(userId); 1438 } else { 1439 mServicePackages.put(userId, componentName.getPackageName()); 1440 } 1441 } else { 1442 mServicePackages.remove(userId); 1443 } 1444 } 1445 } 1446 1447 @Nullable 1448 @GuardedBy("mGlobalWhitelistStateLock") getOptions(@serIdInt int userId, @NonNull String packageName)1449 public ContentCaptureOptions getOptions(@UserIdInt int userId, 1450 @NonNull String packageName) { 1451 boolean isContentCaptureReceiverEnabled; 1452 boolean isContentProtectionReceiverEnabled = 1453 isContentProtectionReceiverEnabled(userId, packageName); 1454 ArraySet<ComponentName> whitelistedComponents = null; 1455 1456 synchronized (mGlobalWhitelistStateLock) { 1457 isContentCaptureReceiverEnabled = 1458 isContentCaptureReceiverEnabled(userId, packageName); 1459 if (!isContentCaptureReceiverEnabled) { 1460 // Full package is not allowlisted: check individual components next 1461 whitelistedComponents = getWhitelistedComponents(userId, packageName); 1462 if (!isContentProtectionReceiverEnabled 1463 && whitelistedComponents == null 1464 && packageName.equals(mServicePackages.get(userId))) { 1465 // No components allowlisted either, but let it go because it's the 1466 // service's own package 1467 if (verbose) Slog.v(TAG, "getOptionsForPackage() lite for " + packageName); 1468 return new ContentCaptureOptions(mDevCfgLoggingLevel); 1469 } 1470 } 1471 } // synchronized 1472 1473 // Restrict what temporary services can allowlist 1474 if (Build.IS_USER && mServiceNameResolver.isTemporary(userId)) { 1475 if (!packageName.equals(mServicePackages.get(userId))) { 1476 Slog.w(TAG, "Ignoring package " + packageName + " while using temporary " 1477 + "service " + mServicePackages.get(userId)); 1478 return null; 1479 } 1480 } 1481 1482 if (!isContentCaptureReceiverEnabled 1483 && !isContentProtectionReceiverEnabled 1484 && whitelistedComponents == null) { 1485 // No can do! 1486 if (verbose) { 1487 Slog.v(TAG, "getOptionsForPackage(" + packageName + "): not whitelisted"); 1488 } 1489 return null; 1490 } 1491 1492 synchronized (mLock) { 1493 final ContentCaptureOptions options = 1494 new ContentCaptureOptions( 1495 mDevCfgLoggingLevel, 1496 mDevCfgMaxBufferSize, 1497 mDevCfgIdleFlushingFrequencyMs, 1498 mDevCfgTextChangeFlushingFrequencyMs, 1499 mDevCfgLogHistorySize, 1500 mDevCfgDisableFlushForViewTreeAppearing, 1501 isContentCaptureReceiverEnabled || whitelistedComponents != null, 1502 new ContentCaptureOptions.ContentProtectionOptions( 1503 isContentProtectionReceiverEnabled, 1504 mDevCfgContentProtectionBufferSize, 1505 mDevCfgContentProtectionRequiredGroups, 1506 mDevCfgContentProtectionOptionalGroups, 1507 mDevCfgContentProtectionOptionalGroupsThreshold), 1508 whitelistedComponents); 1509 if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options); 1510 return options; 1511 } 1512 } 1513 1514 @Override dump(@onNull String prefix, @NonNull PrintWriter pw)1515 public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { 1516 super.dump(prefix, pw); 1517 1518 synchronized (mGlobalWhitelistStateLock) { 1519 if (mServicePackages.size() > 0) { 1520 pw.print(prefix); pw.print("Service packages: "); pw.println(mServicePackages); 1521 } 1522 if (mTemporaryServices.size() > 0) { 1523 pw.print(prefix); pw.print("Temp services: "); pw.println(mTemporaryServices); 1524 } 1525 } 1526 } 1527 1528 @Override // from GlobalWhitelistState isWhitelisted(@serIdInt int userId, @NonNull String packageName)1529 public boolean isWhitelisted(@UserIdInt int userId, @NonNull String packageName) { 1530 return isContentCaptureReceiverEnabled(userId, packageName) 1531 || isContentProtectionReceiverEnabled(userId, packageName); 1532 } 1533 1534 @Override // from GlobalWhitelistState isWhitelisted(@serIdInt int userId, @NonNull ComponentName componentName)1535 public boolean isWhitelisted(@UserIdInt int userId, @NonNull ComponentName componentName) { 1536 return super.isWhitelisted(userId, componentName) 1537 || isContentProtectionReceiverEnabled(userId, componentName.getPackageName()); 1538 } 1539 isContentCaptureReceiverEnabled( @serIdInt int userId, @NonNull String packageName)1540 private boolean isContentCaptureReceiverEnabled( 1541 @UserIdInt int userId, @NonNull String packageName) { 1542 return super.isWhitelisted(userId, packageName); 1543 } 1544 isContentProtectionReceiverEnabled( @serIdInt int userId, @NonNull String packageName)1545 private boolean isContentProtectionReceiverEnabled( 1546 @UserIdInt int userId, @NonNull String packageName) { 1547 ContentProtectionConsentManager consentManager; 1548 ContentProtectionAllowlistManager allowlistManager; 1549 synchronized (mLock) { 1550 if (!isContentProtectionEnabledLocked()) { 1551 return false; 1552 } 1553 consentManager = mContentProtectionConsentManager; 1554 allowlistManager = mContentProtectionAllowlistManager; 1555 } 1556 return consentManager.isConsentGranted(userId) 1557 && allowlistManager.isAllowed(packageName); 1558 } 1559 } 1560 1561 private static class DataShareCallbackDelegate extends IDataShareCallback.Stub { 1562 1563 @NonNull private final DataShareRequest mDataShareRequest; 1564 @NonNull private final IDataShareWriteAdapter mClientAdapter; 1565 @NonNull private final ContentCaptureManagerService mParentService; 1566 @NonNull private final AtomicBoolean mLoggedWriteFinish = new AtomicBoolean(false); 1567 DataShareCallbackDelegate(@onNull DataShareRequest dataShareRequest, @NonNull IDataShareWriteAdapter clientAdapter, ContentCaptureManagerService parentService)1568 DataShareCallbackDelegate(@NonNull DataShareRequest dataShareRequest, 1569 @NonNull IDataShareWriteAdapter clientAdapter, 1570 ContentCaptureManagerService parentService) { 1571 mDataShareRequest = dataShareRequest; 1572 mClientAdapter = clientAdapter; 1573 mParentService = parentService; 1574 } 1575 1576 @Override accept(@onNull IDataShareReadAdapter serviceAdapter)1577 public void accept(@NonNull IDataShareReadAdapter serviceAdapter) { 1578 Slog.i(TAG, "Data share request accepted by Content Capture service"); 1579 logServiceEvent(CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ACCEPT_DATA_SHARE_REQUEST); 1580 1581 Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe(); 1582 if (clientPipe == null) { 1583 logServiceEvent( 1584 CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL); 1585 sendErrorSignal(mClientAdapter, serviceAdapter, 1586 ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN); 1587 return; 1588 } 1589 1590 ParcelFileDescriptor sourceIn = clientPipe.second; 1591 ParcelFileDescriptor sinkIn = clientPipe.first; 1592 1593 Pair<ParcelFileDescriptor, ParcelFileDescriptor> servicePipe = createPipe(); 1594 if (servicePipe == null) { 1595 logServiceEvent( 1596 CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_SERVICE_PIPE_FAIL); 1597 bestEffortCloseFileDescriptors(sourceIn, sinkIn); 1598 1599 sendErrorSignal(mClientAdapter, serviceAdapter, 1600 ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN); 1601 return; 1602 } 1603 1604 ParcelFileDescriptor sourceOut = servicePipe.second; 1605 ParcelFileDescriptor sinkOut = servicePipe.first; 1606 1607 synchronized (mParentService.mLock) { 1608 mParentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName()); 1609 } 1610 1611 if (!setUpSharingPipeline(mClientAdapter, serviceAdapter, sourceIn, sinkOut)) { 1612 sendErrorSignal(mClientAdapter, serviceAdapter, 1613 ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN); 1614 bestEffortCloseFileDescriptors(sourceIn, sinkIn, sourceOut, sinkOut); 1615 synchronized (mParentService.mLock) { 1616 mParentService.mPackagesWithShareRequests 1617 .remove(mDataShareRequest.getPackageName()); 1618 } 1619 return; 1620 } 1621 1622 // File descriptors received by remote apps will be copies of the current one. Close 1623 // the ones that belong to the system server, so there's only 1 open left for the 1624 // current pipe. Therefore when remote parties decide to close them - all descriptors 1625 // pointing to the pipe will be closed. 1626 bestEffortCloseFileDescriptors(sourceIn, sinkOut); 1627 1628 mParentService.mDataShareExecutor.execute(() -> { 1629 boolean receivedData = false; 1630 try (InputStream fis = 1631 new ParcelFileDescriptor.AutoCloseInputStream(sinkIn); 1632 OutputStream fos = 1633 new ParcelFileDescriptor.AutoCloseOutputStream(sourceOut)) { 1634 1635 byte[] byteBuffer = new byte[DATA_SHARE_BYTE_BUFFER_LENGTH]; 1636 while (true) { 1637 int readBytes = fis.read(byteBuffer); 1638 1639 if (readBytes == -1) { 1640 break; 1641 } 1642 1643 fos.write(byteBuffer, 0 /* offset */, readBytes); 1644 1645 receivedData = true; 1646 } 1647 } catch (IOException e) { 1648 Slog.e(TAG, "Failed to pipe client and service streams", e); 1649 logServiceEvent( 1650 CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_IOEXCEPTION); 1651 1652 sendErrorSignal(mClientAdapter, serviceAdapter, 1653 ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN); 1654 } finally { 1655 synchronized (mParentService.mLock) { 1656 mParentService.mPackagesWithShareRequests 1657 .remove(mDataShareRequest.getPackageName()); 1658 } 1659 if (receivedData) { 1660 if (!mLoggedWriteFinish.get()) { 1661 logServiceEvent(EVENT__DATA_SHARE_WRITE_FINISHED); 1662 mLoggedWriteFinish.set(true); 1663 } 1664 try { 1665 mClientAdapter.finish(); 1666 } catch (RemoteException e) { 1667 Slog.e(TAG, "Failed to call finish() the client operation", e); 1668 } 1669 try { 1670 serviceAdapter.finish(); 1671 } catch (RemoteException e) { 1672 Slog.e(TAG, "Failed to call finish() the service operation", e); 1673 } 1674 } else { 1675 // Client or service may have crashed before sending. 1676 logServiceEvent( 1677 CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_EMPTY_DATA); 1678 sendErrorSignal(mClientAdapter, serviceAdapter, 1679 ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN); 1680 } 1681 } 1682 }); 1683 1684 mParentService.mHandler.postDelayed(() -> 1685 enforceDataSharingTtl( 1686 sourceIn, 1687 sinkIn, 1688 sourceOut, 1689 sinkOut, 1690 serviceAdapter), 1691 MAX_DATA_SHARE_FILE_DESCRIPTORS_TTL_MS); 1692 } 1693 1694 @Override reject()1695 public void reject() { 1696 Slog.i(TAG, "Data share request rejected by Content Capture service"); 1697 logServiceEvent(CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__REJECT_DATA_SHARE_REQUEST); 1698 1699 try { 1700 mClientAdapter.rejected(); 1701 } catch (RemoteException e) { 1702 Slog.w(TAG, "Failed to call rejected() the client operation", e); 1703 try { 1704 mClientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN); 1705 } catch (RemoteException e2) { 1706 Slog.w(TAG, "Failed to call error() the client operation", e2); 1707 } 1708 } 1709 } 1710 setUpSharingPipeline( IDataShareWriteAdapter clientAdapter, IDataShareReadAdapter serviceAdapter, ParcelFileDescriptor sourceIn, ParcelFileDescriptor sinkOut)1711 private boolean setUpSharingPipeline( 1712 IDataShareWriteAdapter clientAdapter, 1713 IDataShareReadAdapter serviceAdapter, 1714 ParcelFileDescriptor sourceIn, 1715 ParcelFileDescriptor sinkOut) { 1716 try { 1717 clientAdapter.write(sourceIn); 1718 } catch (RemoteException e) { 1719 Slog.e(TAG, "Failed to call write() the client operation", e); 1720 logServiceEvent( 1721 CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL); 1722 return false; 1723 } 1724 1725 try { 1726 serviceAdapter.start(sinkOut); 1727 } catch (RemoteException e) { 1728 Slog.e(TAG, "Failed to call start() the service operation", e); 1729 logServiceEvent( 1730 CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_SERVICE_PIPE_FAIL); 1731 return false; 1732 } 1733 1734 return true; 1735 } 1736 enforceDataSharingTtl(ParcelFileDescriptor sourceIn, ParcelFileDescriptor sinkIn, ParcelFileDescriptor sourceOut, ParcelFileDescriptor sinkOut, IDataShareReadAdapter serviceAdapter)1737 private void enforceDataSharingTtl(ParcelFileDescriptor sourceIn, 1738 ParcelFileDescriptor sinkIn, 1739 ParcelFileDescriptor sourceOut, 1740 ParcelFileDescriptor sinkOut, 1741 IDataShareReadAdapter serviceAdapter) { 1742 1743 synchronized (mParentService.mLock) { 1744 mParentService.mPackagesWithShareRequests 1745 .remove(mDataShareRequest.getPackageName()); 1746 1747 // Interaction finished successfully <=> all data has been written to Content 1748 // Capture Service. If it hasn't been read successfully, service would be able 1749 // to signal by closing the input stream while not have finished reading. 1750 boolean finishedSuccessfully = !sinkIn.getFileDescriptor().valid() 1751 && !sourceOut.getFileDescriptor().valid(); 1752 1753 if (finishedSuccessfully) { 1754 if (!mLoggedWriteFinish.get()) { 1755 logServiceEvent(EVENT__DATA_SHARE_WRITE_FINISHED); 1756 mLoggedWriteFinish.set(true); 1757 } 1758 Slog.i(TAG, "Content capture data sharing session terminated " 1759 + "successfully for package '" 1760 + mDataShareRequest.getPackageName() 1761 + "'"); 1762 } else { 1763 logServiceEvent(EVENT__DATA_SHARE_ERROR_TIMEOUT_INTERRUPTED); 1764 Slog.i(TAG, "Reached the timeout of Content Capture data sharing session " 1765 + "for package '" 1766 + mDataShareRequest.getPackageName() 1767 + "', terminating the pipe."); 1768 } 1769 1770 // Ensure all the descriptors are closed after the session. 1771 bestEffortCloseFileDescriptors(sourceIn, sinkIn, sourceOut, sinkOut); 1772 1773 if (!finishedSuccessfully) { 1774 sendErrorSignal(mClientAdapter, serviceAdapter, 1775 ContentCaptureManager.DATA_SHARE_ERROR_TIMEOUT_INTERRUPTED); 1776 } 1777 } 1778 } 1779 createPipe()1780 private Pair<ParcelFileDescriptor, ParcelFileDescriptor> createPipe() { 1781 ParcelFileDescriptor[] fileDescriptors; 1782 try { 1783 fileDescriptors = ParcelFileDescriptor.createPipe(); 1784 } catch (IOException e) { 1785 Slog.e(TAG, "Failed to create a content capture data-sharing pipe", e); 1786 return null; 1787 } 1788 1789 if (fileDescriptors.length != 2) { 1790 Slog.e(TAG, "Failed to create a content capture data-sharing pipe, " 1791 + "unexpected number of file descriptors"); 1792 return null; 1793 } 1794 1795 if (!fileDescriptors[0].getFileDescriptor().valid() 1796 || !fileDescriptors[1].getFileDescriptor().valid()) { 1797 Slog.e(TAG, "Failed to create a content capture data-sharing pipe, didn't " 1798 + "receive a pair of valid file descriptors."); 1799 return null; 1800 } 1801 1802 return Pair.create(fileDescriptors[0], fileDescriptors[1]); 1803 } 1804 bestEffortCloseFileDescriptor(ParcelFileDescriptor fd)1805 private void bestEffortCloseFileDescriptor(ParcelFileDescriptor fd) { 1806 try { 1807 fd.close(); 1808 } catch (IOException e) { 1809 Slog.e(TAG, "Failed to close a file descriptor", e); 1810 } 1811 } 1812 bestEffortCloseFileDescriptors(ParcelFileDescriptor... fds)1813 private void bestEffortCloseFileDescriptors(ParcelFileDescriptor... fds) { 1814 for (ParcelFileDescriptor fd : fds) { 1815 bestEffortCloseFileDescriptor(fd); 1816 } 1817 } 1818 sendErrorSignal( IDataShareWriteAdapter clientAdapter, IDataShareReadAdapter serviceAdapter, int errorCode)1819 private static void sendErrorSignal( 1820 IDataShareWriteAdapter clientAdapter, 1821 IDataShareReadAdapter serviceAdapter, 1822 int errorCode) { 1823 try { 1824 clientAdapter.error(errorCode); 1825 } catch (RemoteException e) { 1826 Slog.e(TAG, "Failed to call error() the client operation", e); 1827 } 1828 try { 1829 serviceAdapter.error(errorCode); 1830 } catch (RemoteException e) { 1831 Slog.e(TAG, "Failed to call error() the service operation", e); 1832 } 1833 } 1834 logServiceEvent(int eventType)1835 private void logServiceEvent(int eventType) { 1836 int userId = UserHandle.getCallingUserId(); 1837 String serviceName = mParentService.mServiceNameResolver.getServiceName(userId); 1838 ContentCaptureMetricsLogger.writeServiceEvent(eventType, serviceName); 1839 } 1840 } 1841 } 1842