• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 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.app.appsearch.annotation.CanIgnoreReturnValue;
21 import android.app.appsearch.safeparcel.AbstractSafeParcelable;
22 import android.app.appsearch.safeparcel.SafeParcelable;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.util.ArraySet;
26 
27 import com.android.appsearch.flags.Flags;
28 
29 import org.jspecify.annotations.NonNull;
30 import org.jspecify.annotations.Nullable;
31 
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.Set;
37 
38 /**
39  * An expanded version of {@link SchemaVisibilityConfig} which includes fields for internal use by
40  * AppSearch.
41  *
42  * @hide
43  */
44 @SafeParcelable.Class(creator = "InternalVisibilityConfigCreator")
45 public final class InternalVisibilityConfig extends AbstractSafeParcelable {
46 
47     public static final Parcelable.@NonNull Creator<InternalVisibilityConfig> CREATOR =
48             new InternalVisibilityConfigCreator();
49 
50     /** Build the List of {@link InternalVisibilityConfig}s from given {@link SetSchemaRequest}. */
toInternalVisibilityConfigs( @onNull SetSchemaRequest setSchemaRequest)51     public static @NonNull List<InternalVisibilityConfig> toInternalVisibilityConfigs(
52             @NonNull SetSchemaRequest setSchemaRequest) {
53         Set<AppSearchSchema> searchSchemas = setSchemaRequest.getSchemas();
54         Set<String> schemasNotDisplayedBySystem = setSchemaRequest.getSchemasNotDisplayedBySystem();
55         Map<String, Set<PackageIdentifier>> schemasVisibleToPackages =
56                 setSchemaRequest.getSchemasVisibleToPackages();
57         Map<String, Set<Set<Integer>>> schemasVisibleToPermissions =
58                 setSchemaRequest.getRequiredPermissionsForSchemaTypeVisibility();
59         Map<String, PackageIdentifier> publiclyVisibleSchemas =
60                 setSchemaRequest.getPubliclyVisibleSchemas();
61         Map<String, Set<SchemaVisibilityConfig>> schemasVisibleToConfigs =
62                 setSchemaRequest.getSchemasVisibleToConfigs();
63 
64         List<InternalVisibilityConfig> result = new ArrayList<>(searchSchemas.size());
65         for (AppSearchSchema searchSchema : searchSchemas) {
66             String schemaType = searchSchema.getSchemaType();
67             InternalVisibilityConfig.Builder builder =
68                     new InternalVisibilityConfig.Builder(schemaType)
69                             .setNotDisplayedBySystem(
70                                     schemasNotDisplayedBySystem.contains(schemaType));
71 
72             Set<PackageIdentifier> visibleToPackages = schemasVisibleToPackages.get(schemaType);
73             if (visibleToPackages != null) {
74                 for (PackageIdentifier packageIdentifier : visibleToPackages) {
75                     builder.addVisibleToPackage(packageIdentifier);
76                 }
77             }
78 
79             Set<Set<Integer>> visibleToPermissionSets = schemasVisibleToPermissions.get(schemaType);
80             if (visibleToPermissionSets != null) {
81                 for (Set<Integer> visibleToPermissions : visibleToPermissionSets) {
82                     builder.addVisibleToPermissions(visibleToPermissions);
83                 }
84             }
85 
86             PackageIdentifier publiclyVisibleTargetPackage = publiclyVisibleSchemas.get(schemaType);
87             if (publiclyVisibleTargetPackage != null) {
88                 builder.setPubliclyVisibleTargetPackage(publiclyVisibleTargetPackage);
89             }
90 
91             Set<SchemaVisibilityConfig> visibleToConfigs = schemasVisibleToConfigs.get(schemaType);
92             if (visibleToConfigs != null) {
93                 for (SchemaVisibilityConfig schemaVisibilityConfig : visibleToConfigs) {
94                     builder.addVisibleToConfig(schemaVisibilityConfig);
95                 }
96             }
97 
98             result.add(builder.build());
99         }
100         return result;
101     }
102 
103     /**
104      * Build the List of {@link InternalVisibilityConfig}s from given {@link
105      * SetBlobVisibilityRequest}.
106      */
toInternalVisibilityConfigs( @onNull SetBlobVisibilityRequest setBlobVisibilityRequest)107     public static @NonNull List<InternalVisibilityConfig> toInternalVisibilityConfigs(
108             @NonNull SetBlobVisibilityRequest setBlobVisibilityRequest) {
109 
110         Set<String> blobNamespacesNotDisplayedBySystem =
111                 setBlobVisibilityRequest.getNamespacesNotDisplayedBySystem();
112         Map<String, Set<SchemaVisibilityConfig>> blobNamespacesVisibleToConfigs =
113                 setBlobVisibilityRequest.getNamespacesVisibleToConfigs();
114 
115         Set<String> allBlobNamespaces = new ArraySet<>(blobNamespacesNotDisplayedBySystem);
116         allBlobNamespaces.addAll(blobNamespacesVisibleToConfigs.keySet());
117 
118         List<InternalVisibilityConfig> result = new ArrayList<>();
119         for (String namespace : allBlobNamespaces) {
120             InternalVisibilityConfig.Builder builder =
121                     new InternalVisibilityConfig.Builder(namespace)
122                             .setNotDisplayedBySystem(
123                                     blobNamespacesNotDisplayedBySystem.contains(namespace));
124 
125             Set<SchemaVisibilityConfig> visibleToConfigs =
126                     blobNamespacesVisibleToConfigs.get(namespace);
127             if (visibleToConfigs != null) {
128                 for (SchemaVisibilityConfig schemaVisibilityConfig : visibleToConfigs) {
129                     builder.addVisibleToConfig(schemaVisibilityConfig);
130                 }
131             }
132 
133             result.add(builder.build());
134         }
135         return result;
136     }
137 
138     @Field(id = 1, getter = "getSchemaType")
139     private final @NonNull String mSchemaType;
140 
141     @Field(id = 2, getter = "isNotDisplayedBySystem")
142     private final boolean mIsNotDisplayedBySystem;
143 
144     /** The public visibility settings available in VisibilityConfig. */
145     @Field(id = 3, getter = "getVisibilityConfig")
146     private final @NonNull SchemaVisibilityConfig mVisibilityConfig;
147 
148     /** Extended visibility settings from {@link SetSchemaRequest#getSchemasVisibleToConfigs()} */
149     @Field(id = 4)
150     final @NonNull List<SchemaVisibilityConfig> mVisibleToConfigs;
151 
152     @Constructor
InternalVisibilityConfig( @aramid = 1) @onNull String schemaType, @Param(id = 2) boolean isNotDisplayedBySystem, @Param(id = 3) @NonNull SchemaVisibilityConfig schemaVisibilityConfig, @Param(id = 4) @NonNull List<SchemaVisibilityConfig> visibleToConfigs)153     InternalVisibilityConfig(
154             @Param(id = 1) @NonNull String schemaType,
155             @Param(id = 2) boolean isNotDisplayedBySystem,
156             @Param(id = 3) @NonNull SchemaVisibilityConfig schemaVisibilityConfig,
157             @Param(id = 4) @NonNull List<SchemaVisibilityConfig> visibleToConfigs) {
158         mIsNotDisplayedBySystem = isNotDisplayedBySystem;
159         mSchemaType = Objects.requireNonNull(schemaType);
160         mVisibilityConfig = Objects.requireNonNull(schemaVisibilityConfig);
161         mVisibleToConfigs = Objects.requireNonNull(visibleToConfigs);
162     }
163 
164     /**
165      * Gets the schemaType for this VisibilityConfig.
166      *
167      * <p>This is being used as the document id when we convert a {@link InternalVisibilityConfig}
168      * to a {@link GenericDocument}.
169      */
getSchemaType()170     public @NonNull String getSchemaType() {
171         return mSchemaType;
172     }
173 
174     /** Returns whether this schema is visible to the system. */
isNotDisplayedBySystem()175     public boolean isNotDisplayedBySystem() {
176         return mIsNotDisplayedBySystem;
177     }
178 
179     /**
180      * Returns the visibility settings stored in the public {@link SchemaVisibilityConfig} object.
181      */
getVisibilityConfig()182     public @NonNull SchemaVisibilityConfig getVisibilityConfig() {
183         return mVisibilityConfig;
184     }
185 
186     /**
187      * Returns required {@link SchemaVisibilityConfig} sets for a caller need to match to access the
188      * schema this {@link InternalVisibilityConfig} represents.
189      */
getVisibleToConfigs()190     public @NonNull Set<SchemaVisibilityConfig> getVisibleToConfigs() {
191         return new ArraySet<>(mVisibleToConfigs);
192     }
193 
194     @Override
writeToParcel(@onNull Parcel dest, int flags)195     public void writeToParcel(@NonNull Parcel dest, int flags) {
196         InternalVisibilityConfigCreator.writeToParcel(this, dest, flags);
197     }
198 
199     @Override
equals(@ullable Object o)200     public boolean equals(@Nullable Object o) {
201         if (this == o) {
202             return true;
203         }
204         if (o == null) {
205             return false;
206         }
207         if (!(o instanceof InternalVisibilityConfig)) {
208             return false;
209         }
210         InternalVisibilityConfig that = (InternalVisibilityConfig) o;
211         return mIsNotDisplayedBySystem == that.mIsNotDisplayedBySystem
212                 && Objects.equals(mSchemaType, that.mSchemaType)
213                 && Objects.equals(mVisibilityConfig, that.mVisibilityConfig)
214                 && Objects.equals(mVisibleToConfigs, that.mVisibleToConfigs);
215     }
216 
217     @Override
hashCode()218     public int hashCode() {
219         return Objects.hash(
220                 mIsNotDisplayedBySystem, mSchemaType, mVisibilityConfig, mVisibleToConfigs);
221     }
222 
223     /** The builder class of {@link InternalVisibilityConfig}. */
224     @FlaggedApi(Flags.FLAG_ENABLE_SET_SCHEMA_VISIBLE_TO_CONFIGS)
225     public static final class Builder {
226         private String mSchemaType;
227         private boolean mIsNotDisplayedBySystem;
228         private SchemaVisibilityConfig.Builder mVisibilityConfigBuilder;
229         private List<SchemaVisibilityConfig> mVisibleToConfigs = new ArrayList<>();
230         private boolean mBuilt;
231 
232         /**
233          * Creates a {@link Builder} for a {@link InternalVisibilityConfig}.
234          *
235          * @param schemaType The SchemaType of the {@link AppSearchSchema} that this {@link
236          *     InternalVisibilityConfig} represents. The package and database prefix will be added
237          *     in server side. We are using prefixed schema type to be the final id of this {@link
238          *     InternalVisibilityConfig}. This will be used as as an AppSearch id.
239          * @see GenericDocument#getId
240          */
Builder(@onNull String schemaType)241         public Builder(@NonNull String schemaType) {
242             mSchemaType = Objects.requireNonNull(schemaType);
243             mVisibilityConfigBuilder = new SchemaVisibilityConfig.Builder();
244         }
245 
246         /** Creates a {@link Builder} from an existing {@link InternalVisibilityConfig} */
Builder(@onNull InternalVisibilityConfig internalVisibilityConfig)247         public Builder(@NonNull InternalVisibilityConfig internalVisibilityConfig) {
248             Objects.requireNonNull(internalVisibilityConfig);
249             mSchemaType = internalVisibilityConfig.mSchemaType;
250             mIsNotDisplayedBySystem = internalVisibilityConfig.mIsNotDisplayedBySystem;
251             mVisibilityConfigBuilder =
252                     new SchemaVisibilityConfig.Builder(
253                             internalVisibilityConfig.getVisibilityConfig());
254             mVisibleToConfigs = internalVisibilityConfig.mVisibleToConfigs;
255         }
256 
257         /** Sets schemaType, which will be as the id when converting to {@link GenericDocument}. */
258         @CanIgnoreReturnValue
setSchemaType(@onNull String schemaType)259         public @NonNull Builder setSchemaType(@NonNull String schemaType) {
260             resetIfBuilt();
261             mSchemaType = Objects.requireNonNull(schemaType);
262             return this;
263         }
264 
265         /**
266          * Resets all values contained in the VisibilityConfig with the values from the given
267          * VisibiltiyConfig.
268          */
269         @CanIgnoreReturnValue
setVisibilityConfig( @onNull SchemaVisibilityConfig schemaVisibilityConfig)270         public @NonNull Builder setVisibilityConfig(
271                 @NonNull SchemaVisibilityConfig schemaVisibilityConfig) {
272             resetIfBuilt();
273             mVisibilityConfigBuilder = new SchemaVisibilityConfig.Builder(schemaVisibilityConfig);
274             return this;
275         }
276 
277         /** Sets whether this schema has opted out of platform surfacing. */
278         @CanIgnoreReturnValue
setNotDisplayedBySystem(boolean notDisplayedBySystem)279         public @NonNull Builder setNotDisplayedBySystem(boolean notDisplayedBySystem) {
280             resetIfBuilt();
281             mIsNotDisplayedBySystem = notDisplayedBySystem;
282             return this;
283         }
284 
285         /**
286          * Add {@link PackageIdentifier} of packages which has access to this schema.
287          *
288          * @see SchemaVisibilityConfig.Builder#addAllowedPackage
289          */
290         @CanIgnoreReturnValue
addVisibleToPackage(@onNull PackageIdentifier packageIdentifier)291         public @NonNull Builder addVisibleToPackage(@NonNull PackageIdentifier packageIdentifier) {
292             resetIfBuilt();
293             mVisibilityConfigBuilder.addAllowedPackage(packageIdentifier);
294             return this;
295         }
296 
297         /**
298          * Clears the list of packages which have access to this schema.
299          *
300          * @see SchemaVisibilityConfig.Builder#clearAllowedPackages
301          */
302         @CanIgnoreReturnValue
clearVisibleToPackages()303         public @NonNull Builder clearVisibleToPackages() {
304             resetIfBuilt();
305             mVisibilityConfigBuilder.clearAllowedPackages();
306             return this;
307         }
308 
309         /**
310          * Adds a set of required Android {@link android.Manifest.permission} combination a package
311          * needs to hold to access the schema.
312          *
313          * @see SchemaVisibilityConfig.Builder#addRequiredPermissions
314          */
315         @CanIgnoreReturnValue
addVisibleToPermissions( @onNull Set<Integer> visibleToPermissions)316         public @NonNull Builder addVisibleToPermissions(
317                 @NonNull Set<Integer> visibleToPermissions) {
318             resetIfBuilt();
319             mVisibilityConfigBuilder.addRequiredPermissions(visibleToPermissions);
320             return this;
321         }
322 
323         /**
324          * Clears all required permissions combinations set to this {@link SchemaVisibilityConfig}.
325          *
326          * @see SchemaVisibilityConfig.Builder#clearRequiredPermissions
327          */
328         @CanIgnoreReturnValue
clearVisibleToPermissions()329         public @NonNull Builder clearVisibleToPermissions() {
330             resetIfBuilt();
331             mVisibilityConfigBuilder.clearRequiredPermissions();
332             return this;
333         }
334 
335         /**
336          * Specify that this schema should be publicly available, to the same packages that have
337          * visibility to the package passed as a parameter. This visibility is determined by the
338          * result of {@link android.content.pm.PackageManager#canPackageQuery}.
339          *
340          * @see SchemaVisibilityConfig.Builder#setPubliclyVisibleTargetPackage
341          */
342         @CanIgnoreReturnValue
setPubliclyVisibleTargetPackage( @ullable PackageIdentifier packageIdentifier)343         public @NonNull Builder setPubliclyVisibleTargetPackage(
344                 @Nullable PackageIdentifier packageIdentifier) {
345             resetIfBuilt();
346             mVisibilityConfigBuilder.setPubliclyVisibleTargetPackage(packageIdentifier);
347             return this;
348         }
349 
350         /**
351          * Add the {@link SchemaVisibilityConfig} for a caller need to match to access the schema
352          * this {@link InternalVisibilityConfig} represents.
353          *
354          * <p>You can call this method repeatedly to add multiple {@link SchemaVisibilityConfig},
355          * and the querier will have access if they match ANY of the {@link SchemaVisibilityConfig}.
356          *
357          * @param schemaVisibilityConfig The {@link SchemaVisibilityConfig} hold all requirements
358          *     that a call must match to access the schema.
359          */
360         @CanIgnoreReturnValue
addVisibleToConfig( @onNull SchemaVisibilityConfig schemaVisibilityConfig)361         public @NonNull Builder addVisibleToConfig(
362                 @NonNull SchemaVisibilityConfig schemaVisibilityConfig) {
363             Objects.requireNonNull(schemaVisibilityConfig);
364             resetIfBuilt();
365             mVisibleToConfigs.add(schemaVisibilityConfig);
366             return this;
367         }
368 
369         /** Clears the set of {@link SchemaVisibilityConfig} which have access to this schema. */
370         @CanIgnoreReturnValue
clearVisibleToConfig()371         public @NonNull Builder clearVisibleToConfig() {
372             resetIfBuilt();
373             mVisibleToConfigs.clear();
374             return this;
375         }
376 
resetIfBuilt()377         private void resetIfBuilt() {
378             if (mBuilt) {
379                 mVisibleToConfigs = new ArrayList<>(mVisibleToConfigs);
380                 mBuilt = false;
381             }
382         }
383 
384         /** Build a {@link InternalVisibilityConfig} */
build()385         public @NonNull InternalVisibilityConfig build() {
386             mBuilt = true;
387             return new InternalVisibilityConfig(
388                     mSchemaType,
389                     mIsNotDisplayedBySystem,
390                     mVisibilityConfigBuilder.build(),
391                     mVisibleToConfigs);
392         }
393     }
394 }
395