1 /* 2 * Copyright 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 android.app.appsearch; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SuppressLint; 24 import android.app.appsearch.annotation.CanIgnoreReturnValue; 25 import android.app.appsearch.safeparcel.AbstractSafeParcelable; 26 import android.app.appsearch.safeparcel.SafeParcelable; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.util.ArrayMap; 30 import android.util.ArraySet; 31 32 import com.android.appsearch.flags.Flags; 33 import com.android.internal.util.Preconditions; 34 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.List; 38 import java.util.Map; 39 import java.util.Objects; 40 import java.util.Set; 41 42 /** The response class of {@link AppSearchSession#getSchema} */ 43 @SafeParcelable.Class(creator = "GetSchemaResponseCreator") 44 // TODO(b/384721898): Switch to JSpecify annotations 45 @SuppressWarnings({"HiddenSuperclass", "JSpecifyNullness"}) 46 public final class GetSchemaResponse extends AbstractSafeParcelable { 47 48 @FlaggedApi(Flags.FLAG_ENABLE_SAFE_PARCELABLE_2) 49 public static final @NonNull Parcelable.Creator<GetSchemaResponse> CREATOR = 50 new GetSchemaResponseCreator(); 51 52 @Field(id = 1, getter = "getVersion") 53 private final int mVersion; 54 55 @Field(id = 2) 56 final List<AppSearchSchema> mSchemas; 57 58 /** 59 * List of VisibilityConfigs for the current schema. May be {@code null} if retrieving the 60 * visibility settings is not possible on the current backend. 61 */ 62 @Field(id = 3) 63 final @Nullable List<InternalVisibilityConfig> mVisibilityConfigs; 64 65 /** 66 * This set contains all schemas most recently successfully provided to {@link 67 * AppSearchSession#setSchema}. We do lazy fetch, the object will be created when you first time 68 * fetch it. 69 */ 70 private @Nullable Set<AppSearchSchema> mSchemasCached; 71 72 /** 73 * This Set contains all schemas that are not displayed by the system. All values in the set are 74 * prefixed with the package-database prefix. We do lazy fetch, the object will be created when 75 * you first time fetch it. 76 */ 77 private @Nullable Set<String> mSchemasNotDisplayedBySystemCached; 78 79 /** 80 * This map contains all schemas and {@link PackageIdentifier} that has access to the schema. 81 * All keys in the map are prefixed with the package-database prefix. We do lazy fetch, the 82 * object will be created when you first time fetch it. 83 */ 84 private @Nullable Map<String, Set<PackageIdentifier>> mSchemasVisibleToPackagesCached; 85 86 /** 87 * This map contains all schemas and Android Permissions combinations that are required to 88 * access the schema. All keys in the map are prefixed with the package-database prefix. We do 89 * lazy fetch, the object will be created when you first time fetch it. The Map is constructed 90 * in ANY-ALL cases. The querier could read the {@link GenericDocument} objects under the {@code 91 * schemaType} if they hold ALL required permissions of ANY combinations. 92 * 93 * @see SetSchemaRequest.Builder#addRequiredPermissionsForSchemaTypeVisibility(String, Set) 94 */ 95 private @Nullable Map<String, Set<Set<Integer>>> mSchemasVisibleToPermissionsCached; 96 97 /** 98 * This map contains all publicly visible schemas and the {@link PackageIdentifier} specifying 99 * the package that the schemas are from. 100 */ 101 private @Nullable Map<String, PackageIdentifier> mPubliclyVisibleSchemasCached; 102 103 /** 104 * This map contains all {@link SchemaVisibilityConfig}s that has access to the schema. All keys 105 * in the map are prefixed with the package-database prefix. We do lazy fetch, the object will 106 * be created when you first time fetch it. 107 */ 108 private @Nullable Map<String, Set<SchemaVisibilityConfig>> mSchemasVisibleToConfigsCached; 109 110 @Constructor GetSchemaResponse( @aramid = 1) int version, @Param(id = 2) @NonNull List<AppSearchSchema> schemas, @Param(id = 3) @Nullable List<InternalVisibilityConfig> visibilityConfigs)111 GetSchemaResponse( 112 @Param(id = 1) int version, 113 @Param(id = 2) @NonNull List<AppSearchSchema> schemas, 114 @Param(id = 3) @Nullable List<InternalVisibilityConfig> visibilityConfigs) { 115 mVersion = version; 116 mSchemas = Objects.requireNonNull(schemas); 117 mVisibilityConfigs = visibilityConfigs; 118 } 119 120 /** 121 * Returns the overall database schema version. 122 * 123 * <p>If the database is empty, 0 will be returned. 124 */ 125 @IntRange(from = 0) getVersion()126 public int getVersion() { 127 return mVersion; 128 } 129 130 /** 131 * Return the schemas most recently successfully provided to {@link AppSearchSession#setSchema}. 132 */ getSchemas()133 public @NonNull Set<AppSearchSchema> getSchemas() { 134 if (mSchemasCached == null) { 135 mSchemasCached = Collections.unmodifiableSet(new ArraySet<>(mSchemas)); 136 } 137 return mSchemasCached; 138 } 139 140 /** 141 * Returns all the schema types that are opted out of being displayed and visible on any system 142 * UI surface. 143 */ getSchemaTypesNotDisplayedBySystem()144 public @NonNull Set<String> getSchemaTypesNotDisplayedBySystem() { 145 List<InternalVisibilityConfig> visibilityConfigs = getVisibilityConfigsOrThrow(); 146 if (mSchemasNotDisplayedBySystemCached == null) { 147 Set<String> copy = new ArraySet<>(); 148 for (int i = 0; i < visibilityConfigs.size(); i++) { 149 if (visibilityConfigs.get(i).isNotDisplayedBySystem()) { 150 copy.add(visibilityConfigs.get(i).getSchemaType()); 151 } 152 } 153 mSchemasNotDisplayedBySystemCached = Collections.unmodifiableSet(copy); 154 } 155 return mSchemasNotDisplayedBySystemCached; 156 } 157 158 /** 159 * Returns a mapping of schema types to the set of packages that have access to that schema 160 * type. 161 */ getSchemaTypesVisibleToPackages()162 public @NonNull Map<String, Set<PackageIdentifier>> getSchemaTypesVisibleToPackages() { 163 List<InternalVisibilityConfig> visibilityConfigs = getVisibilityConfigsOrThrow(); 164 if (mSchemasVisibleToPackagesCached == null) { 165 Map<String, Set<PackageIdentifier>> copy = new ArrayMap<>(); 166 for (int i = 0; i < visibilityConfigs.size(); i++) { 167 InternalVisibilityConfig visibilityConfig = visibilityConfigs.get(i); 168 List<PackageIdentifier> visibleToPackages = 169 visibilityConfig.getVisibilityConfig().getAllowedPackages(); 170 if (!visibleToPackages.isEmpty()) { 171 copy.put( 172 visibilityConfig.getSchemaType(), 173 Collections.unmodifiableSet(new ArraySet<>(visibleToPackages))); 174 } 175 } 176 mSchemasVisibleToPackagesCached = Collections.unmodifiableMap(copy); 177 } 178 return mSchemasVisibleToPackagesCached; 179 } 180 181 /** 182 * Returns a mapping of schema types to the set of {@link android.Manifest.permission} 183 * combination sets that querier must hold to access that schema type. 184 * 185 * <p>The querier could read the {@link GenericDocument} objects under the {@code schemaType} if 186 * they holds ALL required permissions of ANY of the individual value sets. 187 * 188 * <p>For example, if the Map contains {@code {% verbatim %}{{permissionA, PermissionB}, { 189 * PermissionC, PermissionD}, {PermissionE}}{% endverbatim %}}. 190 * 191 * <ul> 192 * <li>A querier holding both PermissionA and PermissionB has access. 193 * <li>A querier holding both PermissionC and PermissionD has access. 194 * <li>A querier holding only PermissionE has access. 195 * <li>A querier holding both PermissionA and PermissionE has access. 196 * <li>A querier holding only PermissionA doesn't have access. 197 * <li>A querier holding only PermissionA and PermissionC doesn't have access. 198 * </ul> 199 * 200 * @return The map contains schema type and all combinations of required permission for querier 201 * to access it. The supported Permission are {@link SetSchemaRequest#READ_SMS}, {@link 202 * SetSchemaRequest#READ_CALENDAR}, {@link SetSchemaRequest#READ_CONTACTS}, {@link 203 * SetSchemaRequest#READ_EXTERNAL_STORAGE}, {@link 204 * SetSchemaRequest#READ_HOME_APP_SEARCH_DATA} and {@link 205 * SetSchemaRequest#READ_ASSISTANT_APP_SEARCH_DATA}. 206 */ 207 // TODO(b/237388235): add enterprise permissions to javadocs after they're unhidden 208 // Annotation is here to suppress lint error. Lint error is erroneous since the method does not 209 // require the caller to hold any permission for the method to function. 210 @SuppressLint("RequiresPermission") getRequiredPermissionsForSchemaTypeVisibility()211 public @NonNull Map<String, Set<Set<Integer>>> getRequiredPermissionsForSchemaTypeVisibility() { 212 List<InternalVisibilityConfig> visibilityConfigs = getVisibilityConfigsOrThrow(); 213 if (mSchemasVisibleToPermissionsCached == null) { 214 Map<String, Set<Set<Integer>>> copy = new ArrayMap<>(); 215 for (int i = 0; i < visibilityConfigs.size(); i++) { 216 InternalVisibilityConfig visibilityConfig = visibilityConfigs.get(i); 217 Set<Set<Integer>> visibleToPermissions = 218 visibilityConfig.getVisibilityConfig().getRequiredPermissions(); 219 if (!visibleToPermissions.isEmpty()) { 220 copy.put( 221 visibilityConfig.getSchemaType(), 222 Collections.unmodifiableSet(visibleToPermissions)); 223 } 224 } 225 mSchemasVisibleToPermissionsCached = Collections.unmodifiableMap(copy); 226 } 227 return mSchemasVisibleToPermissionsCached; 228 } 229 230 /** 231 * Returns a mapping of publicly visible schemas to the {@link PackageIdentifier} specifying the 232 * package the schemas are from. 233 * 234 * <p>If no schemas have been set as publicly visible, an empty set will be returned. 235 */ 236 @FlaggedApi(Flags.FLAG_ENABLE_SET_PUBLICLY_VISIBLE_SCHEMA) getPubliclyVisibleSchemas()237 public @NonNull Map<String, PackageIdentifier> getPubliclyVisibleSchemas() { 238 List<InternalVisibilityConfig> visibilityConfigs = getVisibilityConfigsOrThrow(); 239 if (mPubliclyVisibleSchemasCached == null) { 240 Map<String, PackageIdentifier> copy = new ArrayMap<>(); 241 for (int i = 0; i < visibilityConfigs.size(); i++) { 242 InternalVisibilityConfig visibilityConfig = visibilityConfigs.get(i); 243 PackageIdentifier publiclyVisibleTargetPackage = 244 visibilityConfig.getVisibilityConfig().getPubliclyVisibleTargetPackage(); 245 if (publiclyVisibleTargetPackage != null) { 246 copy.put(visibilityConfig.getSchemaType(), publiclyVisibleTargetPackage); 247 } 248 } 249 mPubliclyVisibleSchemasCached = Collections.unmodifiableMap(copy); 250 } 251 return mPubliclyVisibleSchemasCached; 252 } 253 254 /** 255 * Returns a mapping of schema types to the set of {@link SchemaVisibilityConfig} that have 256 * access to that schema type. 257 * 258 * @see SetSchemaRequest.Builder#addSchemaTypeVisibleToConfig 259 */ 260 @FlaggedApi(Flags.FLAG_ENABLE_SET_SCHEMA_VISIBLE_TO_CONFIGS) getSchemaTypesVisibleToConfigs()261 public @NonNull Map<String, Set<SchemaVisibilityConfig>> getSchemaTypesVisibleToConfigs() { 262 List<InternalVisibilityConfig> visibilityConfigs = getVisibilityConfigsOrThrow(); 263 if (mSchemasVisibleToConfigsCached == null) { 264 Map<String, Set<SchemaVisibilityConfig>> copy = new ArrayMap<>(); 265 for (int i = 0; i < visibilityConfigs.size(); i++) { 266 InternalVisibilityConfig visibilityConfig = visibilityConfigs.get(i); 267 Set<SchemaVisibilityConfig> nestedVisibilityConfigs = 268 visibilityConfig.getVisibleToConfigs(); 269 if (!nestedVisibilityConfigs.isEmpty()) { 270 copy.put( 271 visibilityConfig.getSchemaType(), 272 Collections.unmodifiableSet(nestedVisibilityConfigs)); 273 } 274 } 275 mSchemasVisibleToConfigsCached = Collections.unmodifiableMap(copy); 276 } 277 return mSchemasVisibleToConfigsCached; 278 } 279 getVisibilityConfigsOrThrow()280 private @NonNull List<InternalVisibilityConfig> getVisibilityConfigsOrThrow() { 281 List<InternalVisibilityConfig> visibilityConfigs = mVisibilityConfigs; 282 if (visibilityConfigs == null) { 283 throw new UnsupportedOperationException( 284 "Get visibility setting is not supported with " 285 + "this backend/Android API level combination."); 286 } 287 return visibilityConfigs; 288 } 289 290 @FlaggedApi(Flags.FLAG_ENABLE_SAFE_PARCELABLE_2) 291 @Override writeToParcel(@onNull Parcel dest, int flags)292 public void writeToParcel(@NonNull Parcel dest, int flags) { 293 GetSchemaResponseCreator.writeToParcel(this, dest, flags); 294 } 295 296 /** Builder for {@link GetSchemaResponse} objects. */ 297 public static final class Builder { 298 private int mVersion = 0; 299 private ArrayList<AppSearchSchema> mSchemas = new ArrayList<>(); 300 301 /** 302 * Creates the object when we actually set them. If we never set visibility settings, we 303 * should throw {@link UnsupportedOperationException} in the visibility getters. 304 */ 305 private @Nullable Map<String, InternalVisibilityConfig.Builder> mVisibilityConfigBuilders; 306 307 private boolean mBuilt = false; 308 309 /** Creates a new {@link Builder} */ Builder()310 public Builder() { 311 setVisibilitySettingSupported(true); 312 } 313 314 /** Creates a new {@link Builder} from the given {@link GetSchemaResponse}. */ 315 @FlaggedApi(Flags.FLAG_ENABLE_ADDITIONAL_BUILDER_COPY_CONSTRUCTORS) Builder(@onNull GetSchemaResponse getSchemaResponse)316 public Builder(@NonNull GetSchemaResponse getSchemaResponse) { 317 setVisibilitySettingSupported(true); 318 mVersion = getSchemaResponse.mVersion; 319 mSchemas.addAll(getSchemaResponse.mSchemas); 320 if (getSchemaResponse.mVisibilityConfigs != null) { 321 int count = getSchemaResponse.mVisibilityConfigs.size(); 322 for (int i = 0; i < count; i++) { 323 InternalVisibilityConfig config = getSchemaResponse.mVisibilityConfigs.get(i); 324 mVisibilityConfigBuilders.put( 325 config.getSchemaType(), new InternalVisibilityConfig.Builder(config)); 326 } 327 } 328 } 329 330 /** 331 * Sets the database overall schema version. 332 * 333 * <p>Default version is 0 334 */ 335 @CanIgnoreReturnValue setVersion(@ntRangefrom = 0) int version)336 public @NonNull Builder setVersion(@IntRange(from = 0) int version) { 337 Preconditions.checkArgument(version >= 0, "Version must be a non-negative number."); 338 resetIfBuilt(); 339 mVersion = version; 340 return this; 341 } 342 343 /** Adds one {@link AppSearchSchema} to the schema list. */ 344 @CanIgnoreReturnValue addSchema(@onNull AppSearchSchema schema)345 public @NonNull Builder addSchema(@NonNull AppSearchSchema schema) { 346 Objects.requireNonNull(schema); 347 resetIfBuilt(); 348 mSchemas.add(schema); 349 return this; 350 } 351 352 /** Clears all {@link AppSearchSchema}s from the list of schemas. */ 353 @FlaggedApi(Flags.FLAG_ENABLE_ADDITIONAL_BUILDER_COPY_CONSTRUCTORS) 354 @CanIgnoreReturnValue clearSchemas()355 public @NonNull Builder clearSchemas() { 356 resetIfBuilt(); 357 mSchemas.clear(); 358 return this; 359 } 360 361 /** 362 * Sets whether or not documents from the provided {@code schemaType} will be displayed and 363 * visible on any system UI surface. 364 * 365 * @param schemaType The name of an {@link AppSearchSchema} within the same {@link 366 * GetSchemaResponse}, which won't be displayed by system. 367 */ 368 // Getter getSchemaTypesNotDisplayedBySystem returns plural objects. 369 @CanIgnoreReturnValue 370 @SuppressLint("MissingGetterMatchingBuilder") addSchemaTypeNotDisplayedBySystem(@onNull String schemaType)371 public @NonNull Builder addSchemaTypeNotDisplayedBySystem(@NonNull String schemaType) { 372 Objects.requireNonNull(schemaType); 373 resetIfBuilt(); 374 InternalVisibilityConfig.Builder visibilityConfigBuilder = 375 getOrCreateVisibilityConfigBuilder(schemaType); 376 visibilityConfigBuilder.setNotDisplayedBySystem(true); 377 return this; 378 } 379 380 /** 381 * Clears the visibility setting for the given schema type that prevents the schema from 382 * being displayed and visible on any system UI surface. 383 * 384 * @see Builder#addSchemaTypeNotDisplayedBySystem 385 */ 386 @FlaggedApi(Flags.FLAG_ENABLE_ADDITIONAL_BUILDER_COPY_CONSTRUCTORS) 387 @CanIgnoreReturnValue clearSchemaTypeNotDisplayedBySystem(@onNull String schemaType)388 public @NonNull Builder clearSchemaTypeNotDisplayedBySystem(@NonNull String schemaType) { 389 Objects.requireNonNull(schemaType); 390 resetIfBuilt(); 391 InternalVisibilityConfig.Builder visibilityConfigBuilder = 392 getVisibilityConfigBuilder(schemaType); 393 if (visibilityConfigBuilder != null) { 394 visibilityConfigBuilder.setNotDisplayedBySystem(false); 395 } 396 return this; 397 } 398 399 /** 400 * Sets whether or not documents from the provided {@code schemaType} can be read by the 401 * specified package. 402 * 403 * <p>Each package is represented by a {@link PackageIdentifier}, containing a package name 404 * and a byte array of type {@link android.content.pm.PackageManager#CERT_INPUT_SHA256}. 405 * 406 * <p>To opt into one-way data sharing with another application, the developer will need to 407 * explicitly grant the other application’s package name and certificate Read access to its 408 * data. 409 * 410 * <p>For two-way data sharing, both applications need to explicitly grant Read access to 411 * one another. 412 * 413 * @param schemaType The schema type to set visibility on. 414 * @param packageIdentifiers Represents the package that has access to the given schema 415 * type. 416 */ 417 // Getter getSchemaTypesVisibleToPackages returns a map contains all schema types. 418 @CanIgnoreReturnValue 419 @SuppressLint("MissingGetterMatchingBuilder") setSchemaTypeVisibleToPackages( @onNull String schemaType, @NonNull Set<PackageIdentifier> packageIdentifiers)420 public @NonNull Builder setSchemaTypeVisibleToPackages( 421 @NonNull String schemaType, @NonNull Set<PackageIdentifier> packageIdentifiers) { 422 Objects.requireNonNull(schemaType); 423 Objects.requireNonNull(packageIdentifiers); 424 resetIfBuilt(); 425 InternalVisibilityConfig.Builder visibilityConfigBuilder = 426 getOrCreateVisibilityConfigBuilder(schemaType); 427 for (PackageIdentifier packageIdentifier : packageIdentifiers) { 428 visibilityConfigBuilder.addVisibleToPackage(packageIdentifier); 429 } 430 return this; 431 } 432 433 /** 434 * Clears the set of packages that can read the given schema type. 435 * 436 * @see Builder#setSchemaTypeVisibleToPackages 437 */ 438 @FlaggedApi(Flags.FLAG_ENABLE_ADDITIONAL_BUILDER_COPY_CONSTRUCTORS) 439 @CanIgnoreReturnValue clearSchemaTypeVisibleToPackages(@onNull String schemaType)440 public @NonNull Builder clearSchemaTypeVisibleToPackages(@NonNull String schemaType) { 441 Objects.requireNonNull(schemaType); 442 resetIfBuilt(); 443 InternalVisibilityConfig.Builder visibilityConfigBuilder = 444 getVisibilityConfigBuilder(schemaType); 445 if (visibilityConfigBuilder != null) { 446 visibilityConfigBuilder.clearVisibleToPackages(); 447 } 448 return this; 449 } 450 451 /** 452 * Sets a set of required {@link android.Manifest.permission} combinations to the given 453 * schema type. 454 * 455 * <p>The querier could read the {@link GenericDocument} objects under the {@code 456 * schemaType} if they holds ALL required permissions of ANY of the individual value sets. 457 * 458 * <p>For example, if the Map contains {@code {% verbatim %}{{permissionA, PermissionB}, 459 * {PermissionC, PermissionD}, {PermissionE}}{% endverbatim %}}. 460 * 461 * <ul> 462 * <li>A querier holds both PermissionA and PermissionB has access. 463 * <li>A querier holds both PermissionC and PermissionD has access. 464 * <li>A querier holds only PermissionE has access. 465 * <li>A querier holds both PermissionA and PermissionE has access. 466 * <li>A querier holds only PermissionA doesn't have access. 467 * <li>A querier holds both PermissionA and PermissionC doesn't have access. 468 * </ul> 469 * 470 * @param schemaType The schema type to set visibility on. 471 * @param visibleToPermissionSets The Sets of Android permissions that will be required to 472 * access the given schema. 473 * @see android.Manifest.permission#READ_SMS 474 * @see android.Manifest.permission#READ_CALENDAR 475 * @see android.Manifest.permission#READ_CONTACTS 476 * @see android.Manifest.permission#READ_EXTERNAL_STORAGE 477 * @see android.Manifest.permission#READ_HOME_APP_SEARCH_DATA 478 * @see android.Manifest.permission#READ_ASSISTANT_APP_SEARCH_DATA 479 */ 480 // TODO(b/237388235): add enterprise permissions to javadocs after they're unhidden 481 // Getter getRequiredPermissionsForSchemaTypeVisibility returns a map for all schemaTypes. 482 // To use this API doesn't require permissions. 483 @CanIgnoreReturnValue 484 @SuppressLint({"MissingGetterMatchingBuilder", "RequiresPermission"}) 485 // @SetSchemaRequest is an IntDef annotation applied to Set<Set<Integer>>. 486 @SuppressWarnings("SupportAnnotationUsage") setRequiredPermissionsForSchemaTypeVisibility( @onNull String schemaType, @SetSchemaRequest.AppSearchSupportedPermission @NonNull Set<Set<Integer>> visibleToPermissionSets)487 public @NonNull Builder setRequiredPermissionsForSchemaTypeVisibility( 488 @NonNull String schemaType, 489 @SetSchemaRequest.AppSearchSupportedPermission @NonNull 490 Set<Set<Integer>> visibleToPermissionSets) { 491 Objects.requireNonNull(schemaType); 492 Objects.requireNonNull(visibleToPermissionSets); 493 resetIfBuilt(); 494 InternalVisibilityConfig.Builder visibilityConfigBuilder = 495 getOrCreateVisibilityConfigBuilder(schemaType); 496 for (Set<Integer> visibleToPermissions : visibleToPermissionSets) { 497 visibilityConfigBuilder.addVisibleToPermissions(visibleToPermissions); 498 } 499 return this; 500 } 501 502 /** 503 * Clears the set of required {@link android.Manifest.permission} combinations to read the 504 * given schema type. 505 * 506 * @see Builder#setRequiredPermissionsForSchemaTypeVisibility 507 */ 508 // To use this API doesn't require permissions. 509 510 @SuppressLint("RequiresPermission") 511 @FlaggedApi(Flags.FLAG_ENABLE_ADDITIONAL_BUILDER_COPY_CONSTRUCTORS) 512 @CanIgnoreReturnValue clearRequiredPermissionsForSchemaTypeVisibility( @onNull String schemaType)513 public @NonNull Builder clearRequiredPermissionsForSchemaTypeVisibility( 514 @NonNull String schemaType) { 515 Objects.requireNonNull(schemaType); 516 resetIfBuilt(); 517 InternalVisibilityConfig.Builder visibilityConfigBuilder = 518 getVisibilityConfigBuilder(schemaType); 519 if (visibilityConfigBuilder != null) { 520 visibilityConfigBuilder.clearVisibleToPermissions(); 521 } 522 return this; 523 } 524 525 /** 526 * Specify that the schema should be publicly available, to packages which already have 527 * visibility to {@code packageIdentifier}. 528 * 529 * @param schemaType the schema to make publicly accessible. 530 * @param packageIdentifier the package from which the document schema is from. 531 * @see SetSchemaRequest.Builder#setPubliclyVisibleSchema 532 */ 533 // Merged list available from getPubliclyVisibleSchemas 534 @CanIgnoreReturnValue 535 @SuppressLint("MissingGetterMatchingBuilder") 536 @FlaggedApi(Flags.FLAG_ENABLE_SET_PUBLICLY_VISIBLE_SCHEMA) setPubliclyVisibleSchema( @onNull String schemaType, @NonNull PackageIdentifier packageIdentifier)537 public @NonNull Builder setPubliclyVisibleSchema( 538 @NonNull String schemaType, @NonNull PackageIdentifier packageIdentifier) { 539 Objects.requireNonNull(schemaType); 540 Objects.requireNonNull(packageIdentifier); 541 resetIfBuilt(); 542 InternalVisibilityConfig.Builder visibilityConfigBuilder = 543 getOrCreateVisibilityConfigBuilder(schemaType); 544 visibilityConfigBuilder.setPubliclyVisibleTargetPackage(packageIdentifier); 545 return this; 546 } 547 548 /** 549 * Clears the visibility setting that specifies that the given schema type should be 550 * publicly available to packages which already have visibility to a specified package. 551 * 552 * @see Builder#setPubliclyVisibleSchema 553 */ 554 @FlaggedApi(Flags.FLAG_ENABLE_ADDITIONAL_BUILDER_COPY_CONSTRUCTORS) 555 @CanIgnoreReturnValue clearPubliclyVisibleSchema(@onNull String schemaType)556 public @NonNull Builder clearPubliclyVisibleSchema(@NonNull String schemaType) { 557 Objects.requireNonNull(schemaType); 558 resetIfBuilt(); 559 InternalVisibilityConfig.Builder visibilityConfigBuilder = 560 getVisibilityConfigBuilder(schemaType); 561 if (visibilityConfigBuilder != null) { 562 visibilityConfigBuilder.setPubliclyVisibleTargetPackage(null); 563 } 564 return this; 565 } 566 567 /** 568 * Sets the documents from the provided {@code schemaType} can be read by the caller if they 569 * match the ALL visibility requirements set in {@link SchemaVisibilityConfig}. 570 * 571 * <p>The requirements in a {@link SchemaVisibilityConfig} is "AND" relationship. A caller 572 * must match ALL requirements to access the schema. For example, a caller must hold 573 * required permissions AND it is a specified package. 574 * 575 * <p>The querier could have access if they match ALL requirements in ANY of the given 576 * {@link SchemaVisibilityConfig}s 577 * 578 * <p>For example, if the Set contains {@code {% verbatim %}{{PackageA and Permission1}, 579 * {PackageB and Permission2}}{% endverbatim %}}. 580 * 581 * <ul> 582 * <li>A querier from packageA could read if they holds Permission1. 583 * <li>A querier from packageA could NOT read if they only holds Permission2 instead of 584 * Permission1. 585 * <li>A querier from packageB could read if they holds Permission2. 586 * <li>A querier from packageC could never read. 587 * <li>A querier holds both PermissionA and PermissionE has access. 588 * </ul> 589 * 590 * @param schemaType The schema type to set visibility on. 591 * @param visibleToConfigs The {@link SchemaVisibilityConfig}s hold all requirements that a 592 * call must to match to access the schema. 593 */ 594 // Merged map available from getSchemasVisibleToConfigs 595 @CanIgnoreReturnValue 596 @SuppressLint("MissingGetterMatchingBuilder") 597 @FlaggedApi(Flags.FLAG_ENABLE_SET_SCHEMA_VISIBLE_TO_CONFIGS) setSchemaTypeVisibleToConfigs( @onNull String schemaType, @NonNull Set<SchemaVisibilityConfig> visibleToConfigs)598 public @NonNull Builder setSchemaTypeVisibleToConfigs( 599 @NonNull String schemaType, @NonNull Set<SchemaVisibilityConfig> visibleToConfigs) { 600 Objects.requireNonNull(schemaType); 601 Objects.requireNonNull(visibleToConfigs); 602 resetIfBuilt(); 603 InternalVisibilityConfig.Builder visibilityConfigBuilder = 604 getOrCreateVisibilityConfigBuilder(schemaType); 605 for (SchemaVisibilityConfig visibleToConfig : visibleToConfigs) { 606 visibilityConfigBuilder.addVisibleToConfig(visibleToConfig); 607 } 608 return this; 609 } 610 611 /** 612 * Clears the {@link SchemaVisibilityConfig}s for the given schema type which allow 613 * visibility to the schema if the caller matches ALL visibility requirements of ANY {@link 614 * SchemaVisibilityConfig}. 615 * 616 * @see Builder#setSchemaTypeVisibleToConfigs 617 */ 618 @FlaggedApi(Flags.FLAG_ENABLE_ADDITIONAL_BUILDER_COPY_CONSTRUCTORS) 619 @CanIgnoreReturnValue clearSchemaTypeVisibleToConfigs(@onNull String schemaType)620 public @NonNull Builder clearSchemaTypeVisibleToConfigs(@NonNull String schemaType) { 621 Objects.requireNonNull(schemaType); 622 resetIfBuilt(); 623 InternalVisibilityConfig.Builder visibilityConfigBuilder = 624 getVisibilityConfigBuilder(schemaType); 625 if (visibilityConfigBuilder != null) { 626 visibilityConfigBuilder.clearVisibleToConfig(); 627 } 628 return this; 629 } 630 631 /** 632 * Method to set visibility setting. If this is called with false, {@link 633 * #getRequiredPermissionsForSchemaTypeVisibility()}, {@link 634 * #getSchemaTypesNotDisplayedBySystem()}}, and {@link #getSchemaTypesVisibleToPackages()} 635 * calls will throw an {@link UnsupportedOperationException}. If called with true, 636 * visibility information for all schemas will be cleared. 637 * 638 * @param visibilitySettingSupported whether supported {@link 639 * Features#ADD_PERMISSIONS_AND_GET_VISIBILITY} by this backend/Android API level. 640 * @hide 641 */ 642 // Visibility setting is determined by SDK version, so it won't be needed in framework 643 @CanIgnoreReturnValue 644 @SuppressLint("MissingGetterMatchingBuilder") setVisibilitySettingSupported(boolean visibilitySettingSupported)645 public @NonNull Builder setVisibilitySettingSupported(boolean visibilitySettingSupported) { 646 if (visibilitySettingSupported) { 647 mVisibilityConfigBuilders = new ArrayMap<>(); 648 } else { 649 mVisibilityConfigBuilders = null; 650 } 651 return this; 652 } 653 654 /** Builds a {@link GetSchemaResponse} object. */ build()655 public @NonNull GetSchemaResponse build() { 656 List<InternalVisibilityConfig> visibilityConfigs = null; 657 if (mVisibilityConfigBuilders != null) { 658 visibilityConfigs = new ArrayList<>(); 659 for (InternalVisibilityConfig.Builder builder : 660 mVisibilityConfigBuilders.values()) { 661 visibilityConfigs.add(builder.build()); 662 } 663 } 664 mBuilt = true; 665 return new GetSchemaResponse(mVersion, mSchemas, visibilityConfigs); 666 } 667 getOrCreateVisibilityConfigBuilder( @onNull String schemaType)668 private @NonNull InternalVisibilityConfig.Builder getOrCreateVisibilityConfigBuilder( 669 @NonNull String schemaType) { 670 if (mVisibilityConfigBuilders == null) { 671 throw new IllegalStateException( 672 "GetSchemaResponse is not configured with" + "visibility setting support"); 673 } 674 InternalVisibilityConfig.Builder builder = mVisibilityConfigBuilders.get(schemaType); 675 if (builder == null) { 676 builder = new InternalVisibilityConfig.Builder(schemaType); 677 mVisibilityConfigBuilders.put(schemaType, builder); 678 } 679 return builder; 680 } 681 getVisibilityConfigBuilder( @onNull String schemaType)682 private @Nullable InternalVisibilityConfig.Builder getVisibilityConfigBuilder( 683 @NonNull String schemaType) { 684 if (mVisibilityConfigBuilders == null) { 685 throw new IllegalStateException( 686 "GetSchemaResponse is not configured with" + "visibility setting support"); 687 } 688 return mVisibilityConfigBuilders.get(schemaType); 689 } 690 resetIfBuilt()691 private void resetIfBuilt() { 692 if (mBuilt) { 693 // No need to copy mVisibilityConfigBuilders -- it gets copied during build(). 694 mSchemas = new ArrayList<>(mSchemas); 695 mBuilt = false; 696 } 697 } 698 } 699 } 700