Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1cc2b680 authored by Becca Hughes's avatar Becca Hughes
Browse files

Add settingsActivity API to Credential Manager

This adds a flag guarded API to allow apps
to specify an app to be opened when the
app is tapped on in settings.

Test: CTS
Bug: 300014059
Change-Id: Id3760778e11ba11da2111e145ab60d7e39343418
parent 3f98ccfd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1181,6 +1181,7 @@ package android.credentials {
    method @Nullable public CharSequence getLabel(@NonNull android.content.Context);
    method @Nullable public android.graphics.drawable.Drawable getServiceIcon(@NonNull android.content.Context);
    method @NonNull public android.content.pm.ServiceInfo getServiceInfo();
    method @FlaggedApi("android.credentials.flags.settings_activity_enabled") @Nullable public CharSequence getSettingsActivity();
    method @Nullable public CharSequence getSettingsSubtitle();
    method @NonNull public boolean hasCapability(@NonNull String);
    method public boolean isEnabled();
+33 −4
Original line number Diff line number Diff line
@@ -16,12 +16,14 @@

package android.credentials;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ServiceInfo;
import android.credentials.flags.Flags;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -42,6 +44,7 @@ public final class CredentialProviderInfo implements Parcelable {
    @NonNull private final List<String> mCapabilities = new ArrayList<>();
    @Nullable private final CharSequence mOverrideLabel;
    @Nullable private CharSequence mSettingsSubtitle = null;
    @Nullable private CharSequence mSettingsActivity = null;
    private final boolean mIsSystemProvider;
    private final boolean mIsEnabled;
    private final boolean mIsPrimary;
@@ -59,6 +62,7 @@ public final class CredentialProviderInfo implements Parcelable {
        mIsEnabled = builder.mIsEnabled;
        mIsPrimary = builder.mIsPrimary;
        mOverrideLabel = builder.mOverrideLabel;
        mSettingsActivity = builder.mSettingsActivity;
    }

    /** Returns true if the service supports the given {@code credentialType}, false otherwise. */
@@ -104,10 +108,7 @@ public final class CredentialProviderInfo implements Parcelable {
        return mIsEnabled;
    }

    /**
     * Returns whether the provider is set as primary by the user.
     *
     */
    /** Returns whether the provider is set as primary by the user. */
    public boolean isPrimary() {
        return mIsPrimary;
    }
@@ -118,6 +119,18 @@ public final class CredentialProviderInfo implements Parcelable {
        return mSettingsSubtitle;
    }

    /**
     * Returns the settings activity.
     *
     * @hide
     */
    @Nullable
    @TestApi
    @FlaggedApi(Flags.FLAG_SETTINGS_ACTIVITY_ENABLED)
    public CharSequence getSettingsActivity() {
        return mSettingsActivity;
    }

    /** Returns the component name for the service. */
    @NonNull
    public ComponentName getComponentName() {
@@ -133,6 +146,7 @@ public final class CredentialProviderInfo implements Parcelable {
        dest.writeBoolean(mIsPrimary);
        TextUtils.writeToParcel(mOverrideLabel, dest, flags);
        TextUtils.writeToParcel(mSettingsSubtitle, dest, flags);
        TextUtils.writeToParcel(mSettingsActivity, dest, flags);
    }

    @Override
@@ -161,6 +175,9 @@ public final class CredentialProviderInfo implements Parcelable {
                + "settingsSubtitle="
                + mSettingsSubtitle
                + ", "
                + "settingsActivity="
                + mSettingsActivity
                + ", "
                + "capabilities="
                + String.join(",", mCapabilities)
                + "}";
@@ -174,6 +191,7 @@ public final class CredentialProviderInfo implements Parcelable {
        mIsPrimary = in.readBoolean();
        mOverrideLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
        mSettingsSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
        mSettingsActivity = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
    }

    public static final @NonNull Parcelable.Creator<CredentialProviderInfo> CREATOR =
@@ -196,6 +214,7 @@ public final class CredentialProviderInfo implements Parcelable {
        @NonNull private List<String> mCapabilities = new ArrayList<>();
        private boolean mIsSystemProvider = false;
        @Nullable private CharSequence mSettingsSubtitle = null;
        @Nullable private CharSequence mSettingsActivity = null;
        private boolean mIsEnabled = false;
        private boolean mIsPrimary = false;
        @Nullable private CharSequence mOverrideLabel = null;
@@ -231,6 +250,16 @@ public final class CredentialProviderInfo implements Parcelable {
            return this;
        }

        /**
         * Sets the settings activity.
         *
         * @hide
         */
        public @NonNull Builder setSettingsActivity(@Nullable CharSequence settingsActivity) {
            mSettingsActivity = settingsActivity;
            return this;
        }

        /** Sets a list of capabilities this provider service can support. */
        public @NonNull Builder addCapabilities(@NonNull List<String> capabilities) {
            mCapabilities.addAll(capabilities);
+26 −6
Original line number Diff line number Diff line
@@ -45,8 +45,8 @@ import android.util.AttributeSet;
import android.util.Slog;
import android.util.Xml;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -135,8 +135,8 @@ public final class CredentialProviderInfoFactory {
    }

    /**
     * Constructs an information instance of the credential provider for testing purposes. Does
     * not run any verifications and passes parameters as is.
     * Constructs an information instance of the credential provider for testing purposes. Does not
     * run any verifications and passes parameters as is.
     */
    @VisibleForTesting
    public static CredentialProviderInfo createForTests(
@@ -151,7 +151,6 @@ public final class CredentialProviderInfoFactory {
                .setSystemProvider(isSystemProvider)
                .addCapabilities(capabilities)
                .build();

    }

    private static void verifyProviderPermission(ServiceInfo serviceInfo) throws SecurityException {
@@ -267,15 +266,21 @@ public final class CredentialProviderInfoFactory {
                                    allAttributes,
                                    com.android.internal.R.styleable.CredentialProvider);
                    builder.setSettingsSubtitle(
                            afsAttributes.getString(
                            getAfsAttributeSafe(
                                    afsAttributes,
                                    R.styleable.CredentialProvider_settingsSubtitle));
                    builder.setSettingsActivity(
                            getAfsAttributeSafe(
                                    afsAttributes,
                                    R.styleable.CredentialProvider_settingsActivity));
                } catch (Exception e) {
                    Slog.e(TAG, "Failed to get XML attr", e);
                    Slog.w(TAG, "Failed to get XML attr for metadata", e);
                } finally {
                    if (afsAttributes != null) {
                        afsAttributes.recycle();
                    }
                }

                builder.addCapabilities(parseXmlProviderOuterCapabilities(parser, resources));
            } else {
                Slog.w(TAG, "Meta-data does not start with credential-provider-service tag");
@@ -287,6 +292,21 @@ public final class CredentialProviderInfoFactory {
        return builder;
    }

    private static @Nullable String getAfsAttributeSafe(
            @Nullable TypedArray afsAttributes, int resId) {
        if (afsAttributes == null) {
            return null;
        }

        try {
            return afsAttributes.getString(resId);
        } catch (Exception e) {
            Slog.w(TAG, "Failed to get XML attr from afs attributes", e);
        }

        return null;
    }

    private static List<String> parseXmlProviderOuterCapabilities(
            XmlPullParser parser, Resources resources) throws IOException, XmlPullParserException {
        final List<String> capabilities = new ArrayList<>();
+3 −0
Original line number Diff line number Diff line
@@ -10118,6 +10118,9 @@
             screen that can be used to provide more information about a provider. For
             longer strings it will be truncated. -->
        <attr name="settingsSubtitle" format="string" />
        <!-- Fully qualified class name of an activity that allows the user to modify
             the settings for this service. -->
        <attr name="settingsActivity" />
    </declare-styleable>
    <!-- A list of capabilities that indicates to the OS what kinds of credentials