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.NonNull; 20 import android.annotation.Nullable; 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 java.util.Arrays; 28 import java.util.Objects; 29 import java.util.Set; 30 31 /** 32 * The config class that holds all required permissions for a caller need to hold to access the 33 * schema which the outer {@link SchemaVisibilityConfig} represents. 34 * 35 * @hide 36 */ 37 @SafeParcelable.Class(creator = "VisibilityPermissionConfigCreator") 38 public final class VisibilityPermissionConfig extends AbstractSafeParcelable { 39 @NonNull 40 public static final Parcelable.Creator<VisibilityPermissionConfig> CREATOR = 41 new VisibilityPermissionConfigCreator(); 42 43 /** 44 * The Schema type for documents that hold AppSearch's metadata, such as visibility settings. 45 */ 46 public static final String SCHEMA_TYPE = "VisibilityPermissionType"; 47 48 /** Property that holds the required permissions to access the schema. */ 49 public static final String ALL_REQUIRED_PERMISSIONS_PROPERTY = "allRequiredPermissions"; 50 51 /** 52 * Schema for the VisibilityStore's documents. 53 * 54 * <p>NOTE: If you update this, also update schema version number in 55 * VisibilityToDocumentConverter 56 */ 57 public static final AppSearchSchema SCHEMA = 58 new AppSearchSchema.Builder(SCHEMA_TYPE) 59 .addProperty( 60 new AppSearchSchema.LongPropertyConfig.Builder( 61 ALL_REQUIRED_PERMISSIONS_PROPERTY) 62 .setCardinality( 63 AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED) 64 .build()) 65 .build(); 66 67 @Nullable 68 @Field(id = 1) 69 final int[] mAllRequiredPermissions; 70 71 @Nullable 72 // We still need to convert this class to a GenericDocument until we completely treat it 73 // differently in AppSearchImpl. 74 // TODO(b/298118943) Remove this once internally we don't use GenericDocument to store 75 // visibility information. 76 private GenericDocument mGenericDocument; 77 78 @Nullable private Integer mHashCode; 79 80 @Constructor VisibilityPermissionConfig(@aramid = 1) @ullable int[] allRequiredPermissions)81 VisibilityPermissionConfig(@Param(id = 1) @Nullable int[] allRequiredPermissions) { 82 mAllRequiredPermissions = allRequiredPermissions; 83 } 84 85 /** 86 * Sets a set of Android Permissions that caller must hold to access the schema that the outer 87 * {@link SchemaVisibilityConfig} represents. 88 */ VisibilityPermissionConfig(@onNull Set<Integer> allRequiredPermissions)89 public VisibilityPermissionConfig(@NonNull Set<Integer> allRequiredPermissions) { 90 mAllRequiredPermissions = toInts(Objects.requireNonNull(allRequiredPermissions)); 91 } 92 93 /** 94 * Returns an array of Android Permissions that caller mush hold to access the schema that the 95 * outer {@link SchemaVisibilityConfig} represents. 96 */ 97 @Nullable getAllRequiredPermissions()98 public Set<Integer> getAllRequiredPermissions() { 99 return toIntegerSet(mAllRequiredPermissions); 100 } 101 102 @NonNull toInts(@onNull Set<Integer> properties)103 private static int[] toInts(@NonNull Set<Integer> properties) { 104 int[] outputs = new int[properties.size()]; 105 int i = 0; 106 for (int property : properties) { 107 outputs[i++] = property; 108 } 109 return outputs; 110 } 111 112 @Nullable toIntegerSet(@ullable int[] properties)113 private static Set<Integer> toIntegerSet(@Nullable int[] properties) { 114 if (properties == null) { 115 return null; 116 } 117 Set<Integer> outputs = new ArraySet<>(properties.length); 118 for (int property : properties) { 119 outputs.add(property); 120 } 121 return outputs; 122 } 123 124 /** 125 * Generates a {@link GenericDocument} from the current class. 126 * 127 * <p>This conversion is needed until we don't treat Visibility related documents as {@link 128 * GenericDocument}s internally. 129 */ 130 @NonNull toGenericDocument()131 public GenericDocument toGenericDocument() { 132 if (mGenericDocument == null) { 133 // This is used as a nested document, we do not need a namespace or id. 134 GenericDocument.Builder<?> builder = 135 new GenericDocument.Builder<>(/* namespace= */ "", /* id= */ "", SCHEMA_TYPE); 136 137 if (mAllRequiredPermissions != null) { 138 // GenericDocument only supports long, so int[] needs to be converted to 139 // long[] here. 140 long[] longs = new long[mAllRequiredPermissions.length]; 141 for (int i = 0; i < mAllRequiredPermissions.length; ++i) { 142 longs[i] = mAllRequiredPermissions[i]; 143 } 144 builder.setPropertyLong(ALL_REQUIRED_PERMISSIONS_PROPERTY, longs); 145 } 146 147 // The creationTimestamp doesn't matter for Visibility documents. 148 // But to make tests pass, we set it 0 so two GenericDocuments generated from 149 // the same VisibilityPermissionConfig can be same. 150 builder.setCreationTimestampMillis(0L); 151 152 mGenericDocument = builder.build(); 153 } 154 return mGenericDocument; 155 } 156 157 @Override hashCode()158 public int hashCode() { 159 if (mHashCode == null) { 160 mHashCode = Arrays.hashCode(mAllRequiredPermissions); 161 } 162 return mHashCode; 163 } 164 165 @Override equals(@ullable Object other)166 public boolean equals(@Nullable Object other) { 167 if (this == other) { 168 return true; 169 } 170 if (!(other instanceof VisibilityPermissionConfig)) { 171 return false; 172 } 173 VisibilityPermissionConfig otherVisibilityPermissionConfig = 174 (VisibilityPermissionConfig) other; 175 return Arrays.equals( 176 mAllRequiredPermissions, otherVisibilityPermissionConfig.mAllRequiredPermissions); 177 } 178 179 @Override writeToParcel(@onNull Parcel dest, int flags)180 public void writeToParcel(@NonNull Parcel dest, int flags) { 181 VisibilityPermissionConfigCreator.writeToParcel(this, dest, flags); 182 } 183 } 184