1 /* 2 * Copyright (C) 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.credentials; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.TestApi; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.pm.ServiceInfo; 25 import android.graphics.drawable.Drawable; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.text.TextUtils; 29 30 import java.util.ArrayList; 31 import java.util.Collections; 32 import java.util.HashSet; 33 import java.util.List; 34 import java.util.Set; 35 36 /** 37 * {@link ServiceInfo} and meta-data about a credential provider. 38 * 39 * @hide 40 */ 41 @TestApi 42 public final class CredentialProviderInfo implements Parcelable { 43 @NonNull private final ServiceInfo mServiceInfo; 44 @NonNull private final Set<String> mCapabilities = new HashSet<>(); 45 @Nullable private final CharSequence mOverrideLabel; 46 @Nullable private CharSequence mSettingsSubtitle = null; 47 private final boolean mIsSystemProvider; 48 private final boolean mIsEnabled; 49 private final boolean mIsPrimary; 50 51 /** 52 * Constructs an information instance of the credential provider. 53 * 54 * @param builder the builder object. 55 */ CredentialProviderInfo(@onNull Builder builder)56 private CredentialProviderInfo(@NonNull Builder builder) { 57 mServiceInfo = builder.mServiceInfo; 58 mCapabilities.addAll(builder.mCapabilities); 59 mIsSystemProvider = builder.mIsSystemProvider; 60 mSettingsSubtitle = builder.mSettingsSubtitle; 61 mIsEnabled = builder.mIsEnabled; 62 mIsPrimary = builder.mIsPrimary; 63 mOverrideLabel = builder.mOverrideLabel; 64 } 65 66 /** Returns true if the service supports the given {@code credentialType}, false otherwise. */ 67 @NonNull hasCapability(@onNull String credentialType)68 public boolean hasCapability(@NonNull String credentialType) { 69 return mCapabilities.contains(credentialType); 70 } 71 72 /** Returns the service info. */ 73 @NonNull getServiceInfo()74 public ServiceInfo getServiceInfo() { 75 return mServiceInfo; 76 } 77 78 /** Returns whether it is a system provider. */ isSystemProvider()79 public boolean isSystemProvider() { 80 return mIsSystemProvider; 81 } 82 83 /** Returns the service icon. */ 84 @Nullable getServiceIcon(@onNull Context context)85 public Drawable getServiceIcon(@NonNull Context context) { 86 return mServiceInfo.loadIcon(context.getPackageManager()); 87 } 88 89 /** Returns the service label. */ 90 @Nullable getLabel(@onNull Context context)91 public CharSequence getLabel(@NonNull Context context) { 92 if (mOverrideLabel != null) { 93 return mOverrideLabel; 94 } 95 return mServiceInfo.loadSafeLabel(context.getPackageManager()); 96 } 97 98 /** Returns a list of capabilities this provider service can support. */ 99 @NonNull getCapabilities()100 public List<String> getCapabilities() { 101 List<String> capabilities = new ArrayList<>(); 102 for (String capability : mCapabilities) { 103 capabilities.add(capability); 104 } 105 return Collections.unmodifiableList(capabilities); 106 } 107 108 /** Returns whether the provider is enabled by the user. */ isEnabled()109 public boolean isEnabled() { 110 return mIsEnabled; 111 } 112 113 /** 114 * Returns whether the provider is set as primary by the user. 115 * 116 */ isPrimary()117 public boolean isPrimary() { 118 return mIsPrimary; 119 } 120 121 /** Returns the settings subtitle. */ 122 @Nullable getSettingsSubtitle()123 public CharSequence getSettingsSubtitle() { 124 return mSettingsSubtitle; 125 } 126 127 /** Returns the component name for the service. */ 128 @NonNull getComponentName()129 public ComponentName getComponentName() { 130 return mServiceInfo.getComponentName(); 131 } 132 133 @Override writeToParcel(@onNull Parcel dest, int flags)134 public void writeToParcel(@NonNull Parcel dest, int flags) { 135 dest.writeTypedObject(mServiceInfo, flags); 136 dest.writeBoolean(mIsSystemProvider); 137 dest.writeBoolean(mIsEnabled); 138 dest.writeBoolean(mIsPrimary); 139 TextUtils.writeToParcel(mOverrideLabel, dest, flags); 140 TextUtils.writeToParcel(mSettingsSubtitle, dest, flags); 141 142 List<String> capabilities = getCapabilities(); 143 dest.writeStringList(capabilities); 144 } 145 146 @Override describeContents()147 public int describeContents() { 148 return 0; 149 } 150 151 @Override toString()152 public String toString() { 153 return "CredentialProviderInfo {" 154 + "serviceInfo=" 155 + mServiceInfo 156 + ", " 157 + "isSystemProvider=" 158 + mIsSystemProvider 159 + ", " 160 + "isEnabled=" 161 + mIsEnabled 162 + ", " 163 + "isPrimary=" 164 + mIsPrimary 165 + ", " 166 + "overrideLabel=" 167 + mOverrideLabel 168 + ", " 169 + "settingsSubtitle=" 170 + mSettingsSubtitle 171 + ", " 172 + "capabilities=" 173 + String.join(",", mCapabilities) 174 + "}"; 175 } 176 CredentialProviderInfo(@onNull Parcel in)177 private CredentialProviderInfo(@NonNull Parcel in) { 178 mServiceInfo = in.readTypedObject(ServiceInfo.CREATOR); 179 mIsSystemProvider = in.readBoolean(); 180 mIsEnabled = in.readBoolean(); 181 mIsPrimary = in.readBoolean(); 182 mOverrideLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 183 mSettingsSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 184 185 List<String> capabilities = new ArrayList<>(); 186 in.readStringList(capabilities); 187 mCapabilities.addAll(capabilities); 188 } 189 190 public static final @NonNull Parcelable.Creator<CredentialProviderInfo> CREATOR = 191 new Parcelable.Creator<CredentialProviderInfo>() { 192 @Override 193 public CredentialProviderInfo[] newArray(int size) { 194 return new CredentialProviderInfo[size]; 195 } 196 197 @Override 198 public CredentialProviderInfo createFromParcel(@NonNull Parcel in) { 199 return new CredentialProviderInfo(in); 200 } 201 }; 202 203 /** A builder for {@link CredentialProviderInfo} objects. */ 204 public static final class Builder { 205 206 @NonNull private ServiceInfo mServiceInfo; 207 @NonNull private Set<String> mCapabilities = new HashSet<>(); 208 private boolean mIsSystemProvider = false; 209 @Nullable private CharSequence mSettingsSubtitle = null; 210 private boolean mIsEnabled = false; 211 private boolean mIsPrimary = false; 212 @Nullable private CharSequence mOverrideLabel = null; 213 214 /** 215 * Creates a new builder. 216 * 217 * @param serviceInfo the service info of the credential provider service. 218 */ Builder(@onNull ServiceInfo serviceInfo)219 public Builder(@NonNull ServiceInfo serviceInfo) { 220 mServiceInfo = serviceInfo; 221 } 222 223 /** Sets whether it is a system provider. */ setSystemProvider(boolean isSystemProvider)224 public @NonNull Builder setSystemProvider(boolean isSystemProvider) { 225 mIsSystemProvider = isSystemProvider; 226 return this; 227 } 228 229 /** 230 * Sets the label to be used instead of getting from the system (for unit tests). 231 * 232 * @hide 233 */ setOverrideLabel(@onNull CharSequence overrideLabel)234 public @NonNull Builder setOverrideLabel(@NonNull CharSequence overrideLabel) { 235 mOverrideLabel = overrideLabel; 236 return this; 237 } 238 239 /** Sets the settings subtitle. */ setSettingsSubtitle(@ullable CharSequence settingsSubtitle)240 public @NonNull Builder setSettingsSubtitle(@Nullable CharSequence settingsSubtitle) { 241 mSettingsSubtitle = settingsSubtitle; 242 return this; 243 } 244 245 /** Sets a list of capabilities this provider service can support. */ addCapabilities(@onNull List<String> capabilities)246 public @NonNull Builder addCapabilities(@NonNull List<String> capabilities) { 247 mCapabilities.addAll(capabilities); 248 return this; 249 } 250 251 /** 252 * Sets a list of capabilities this provider service can support. 253 * 254 * @hide 255 */ addCapabilities(@onNull Set<String> capabilities)256 public @NonNull Builder addCapabilities(@NonNull Set<String> capabilities) { 257 mCapabilities.addAll(capabilities); 258 return this; 259 } 260 261 /** Sets whether it is enabled by the user. */ setEnabled(boolean isEnabled)262 public @NonNull Builder setEnabled(boolean isEnabled) { 263 mIsEnabled = isEnabled; 264 return this; 265 } 266 267 /** 268 * Sets whether it is set as primary by the user. 269 * 270 * <p>Primary provider will be used for saving credentials by default. In most cases, there 271 * should only one primary provider exist. However, if there are multiple credential 272 * providers exist in the same package, all of them will be marked as primary. 273 * 274 * @hide 275 */ setPrimary(boolean isPrimary)276 public @NonNull Builder setPrimary(boolean isPrimary) { 277 mIsPrimary = isPrimary; 278 return this; 279 } 280 281 /** Builds a new {@link CredentialProviderInfo} instance. */ build()282 public @NonNull CredentialProviderInfo build() { 283 return new CredentialProviderInfo(this); 284 } 285 } 286 } 287