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

Commit 13d3234e authored by Liefu Liu's avatar Liefu Liu Committed by Android (Google) Code Review
Browse files

Merge "API change to define account attributes and add the get and set methods." into main

parents 4af0a8a5 bf610305
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -38321,13 +38321,24 @@ package android.provider {
  }
  public static final class ContactsContract.Settings implements android.provider.ContactsContract.SettingsColumns {
    method @FlaggedApi("android.provider.new_account_attributes_api_enabled") @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public static long getAccountAttributes(@NonNull android.content.ContentResolver, @Nullable android.accounts.Account, @Nullable String);
    method @Deprecated @FlaggedApi("android.provider.new_default_account_api_enabled") @Nullable public static android.accounts.Account getDefaultAccount(@NonNull android.content.ContentResolver);
    method @FlaggedApi("android.provider.new_account_attributes_api_enabled") @RequiresPermission(android.Manifest.permission.WRITE_CONTACTS) public static void setAccountAttributes(@NonNull android.content.ContentResolver, @Nullable android.accounts.Account, @Nullable String, long);
    field public static final String ACTION_SET_DEFAULT_ACCOUNT = "android.provider.action.SET_DEFAULT_ACCOUNT";
    field public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/setting";
    field public static final String CONTENT_TYPE = "vnd.android.cursor.dir/setting";
    field public static final android.net.Uri CONTENT_URI;
  }
  @FlaggedApi("android.provider.new_account_attributes_api_enabled") public static final class ContactsContract.Settings.AccountAttributes {
    field public static final long ATTRIBUTE_DATA_ORIGIN_CLOUD = 4L; // 0x4L
    field public static final long ATTRIBUTE_DATA_ORIGIN_LOCAL = 1L; // 0x1L
    field public static final long ATTRIBUTE_DATA_ORIGIN_SIM = 2L; // 0x2L
    field public static final long ATTRIBUTE_DATA_TYPE_CUSTOM_DECLARED = 32L; // 0x20L
    field public static final long ATTRIBUTE_SYNC_MODE_DOWN_SYNC = 16L; // 0x10L
    field public static final long ATTRIBUTE_SYNC_MODE_UP_SYNC = 8L; // 0x8L
  }
  protected static interface ContactsContract.SettingsColumns {
    field public static final String ACCOUNT_NAME = "account_name";
    field public static final String ACCOUNT_TYPE = "account_type";
+195 −7
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.provider;
import android.accounts.Account;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -3018,8 +3019,6 @@ public final class ContactsContract {
                    com.android.internal.R.string.config_rawContactsLocalAccountType));
        }



        /**
         * Class containing utility methods around the default account.
         * New raw contacts requested to be inserted without a specified {@link Account} will be
@@ -9252,6 +9251,18 @@ public final class ContactsContract {
         * @hide
         */
        String IS_DEFAULT = "x_is_default";

        /**
         * The attributes of account to which this row belongs.
         * @hide
         */
        String ACCOUNT_ATTRIBUTES = HIDDEN_COLUMN_PREFIX + "account_attributes";

        /**
         * Flag indicating if the account's owner has modifies the account attributes.
         * @hide
         */
        String HAS_OWNER_SET_ATTRIBUTES = HIDDEN_COLUMN_PREFIX + "has_owner_set_attributes";
    }

    /**
@@ -9374,6 +9385,28 @@ public final class ContactsContract {
         */
        public static final String KEY_DEFAULT_ACCOUNT = "key_default_account";

        /**
         * The method to invoke in order to overwrite the account attributes.
         *
         * @hide
         */
        public static final String SET_ACCOUNT_ATTRIBUTES_METHOD =
                "setAccountAttributes";

        /**
         * The method to invoke in order to get the account attributes.
         *
         * @hide
         */
        public static final String GET_ACCOUNT_ATTRIBUTES_METHOD = "getAccountAttributes";

        /**
         * Key in the bundle for the account attributes.
         *
         * @hide
         */
        public static final String KEY_ACCOUNT_ATTRIBUTES = "key_account_attributes";

        /**
         * Get the account that is set as the default account for new contacts, which should be
         * initially selected when creating a new contact on contact management apps.
@@ -9383,7 +9416,6 @@ public final class ContactsContract {
         * @param resolver the ContentResolver to query.
         * @return the default account for new contacts, or null if it's not set or set to NULL
         * account.
         *
         * @deprecated This API is only supported up to Android version
         * * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. On later versions,
         * {@link ContactsContract.RawContacts.DefaultAccount#getDefaultAccountForNewContacts}
@@ -9411,7 +9443,6 @@ public final class ContactsContract {
         * @param resolver the ContentResolver to query.
         * @param account  the account to be set to default.
         * @hide
         *
         * @deprecated This API is only supported up to Android version
         * * {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}. On later versions,
         * {@link ContactsContract.RawContacts.DefaultAccount#setDefaultAccountForNewContacts}
@@ -9431,6 +9462,163 @@ public final class ContactsContract {

            resolver.call(ContactsContract.AUTHORITY_URI, SET_DEFAULT_ACCOUNT_METHOD, null, extras);
        }

        @FlaggedApi(Flags.FLAG_NEW_ACCOUNT_ATTRIBUTES_API_ENABLED)
        public static final class AccountAttributes {
            private AccountAttributes() {}

            /**
             * Indicates that the primary, canonical storage location and authoritative source
             * for contacts associated with this account is the local device. These contacts
             * are not synchronized with any external service.
             * An account can only have one of attributes among {@code ATTRIBUTE_DATA_ORIGIN_LOCAL},
             * {@code ATTRIBUTE_DATA_ORIGIN_SIM} and {@code ATTRIBUTE_DATA_ORIGIN_CLOUD}.
             */
            public static final long ATTRIBUTE_DATA_ORIGIN_LOCAL = 1L;

            /**
             * Indicates that contacts associated with this account are stored directly on the SIM
             * card.
             * * An account can only have one of attributes among
             * {@code ATTRIBUTE_DATA_ORIGIN_LOCAL},
             * * {@code ATTRIBUTE_DATA_ORIGIN_SIM} and {@code ATTRIBUTE_DATA_ORIGIN_CLOUD}.
             */
            public static final long ATTRIBUTE_DATA_ORIGIN_SIM = 1L << 1;

            /**
             * Indicates that the primary, canonical storage location and authoritative source
             * for contacts associated with this account is a cloud service. This applies
             * regardless of whether contacts were initially created on the device and then
             * synchronized to the cloud, or if they were created directly in the cloud and
             * downloaded to the device. The cloud serves as the central hub for persistence
             * and synchronization across devices.
             * An account can only have one of attributes among {@code ATTRIBUTE_DATA_ORIGIN_LOCAL},
             * {@code ATTRIBUTE_DATA_ORIGIN_SIM} and {@code ATTRIBUTE_DATA_ORIGIN_CLOUD}.
             */
            public static final long ATTRIBUTE_DATA_ORIGIN_CLOUD = 1 << 2;

            /**
             * Indicates that contacts associated with this account are synchronized
             * from the device to the cloud. Local changes (creations, edits, deletions)
             * are uploaded to the authoritative source.
             * A two-way sync accounts have both {@code ATTRIBUTE_SYNC_MODE_UP_SYNC} and
             * {@code ATTRIBUTE_SYNC_MODE_DOWN_SYNC} attributes.
             */
            public static final long ATTRIBUTE_SYNC_MODE_UP_SYNC = 1L << 3;

            /**
             * Indicates that contacts associated with this account are
             * synchronized from a cloud account to the device. Local
             * changes (creations, edits, deletions) are generally not uploaded
             * to the cloud via this sync mechanism.
             * A two-way sync account has both {@code ATTRIBUTE_SYNC_MODE_UP_SYNC} and
             * {@code ATTRIBUTE_SYNC_MODE_DOWN_SYNC} attributes.
             */
            public static final long ATTRIBUTE_SYNC_MODE_DOWN_SYNC = 1L << 4;

            /**
             * Indicates that this account has declared custom or non-standard
             * contact data fields (e.g., those defined via custom MIME types in `contacts.xml`
             * or other extensibility mechanisms). This data often provides supplementary
             * information and may not be directly user-editable via the standard Contacts app.
             */
            public static final long ATTRIBUTE_DATA_TYPE_CUSTOM_DECLARED = 1L << 5;

            /**
             * @hide
             */
            @LongDef(flag = true, value = {
                    ATTRIBUTE_DATA_ORIGIN_LOCAL,
                    ATTRIBUTE_DATA_ORIGIN_SIM,
                    ATTRIBUTE_DATA_ORIGIN_CLOUD,
                    ATTRIBUTE_SYNC_MODE_UP_SYNC,
                    ATTRIBUTE_SYNC_MODE_DOWN_SYNC,
                    ATTRIBUTE_DATA_TYPE_CUSTOM_DECLARED
            })
            @Retention(RetentionPolicy.SOURCE)
            public @interface AttributeFlags {
            }
        }

        /**
         * Returns the attributes of a given account as a 64-bit bitmask.
         *
         * <p>A return value of {@code 0L} indicates the account exists but has no specific
         * attributes enabled or set.
         *
         * @param resolver The {@link ContentResolver} to use for the query.
         * @param account  The account to query. If {@code null}, this will query the
         * attributes of the local, device-only account.
         * @param dataSet  The data set specific to the account type, which may be {@code null}.
         * @return A {@code long} representing the attributes bitmask.
         * @throws IllegalStateException if the specified account does not exist or its
         * attributes could not be determined.
         */
        @FlaggedApi(Flags.FLAG_NEW_ACCOUNT_ATTRIBUTES_API_ENABLED)
        @RequiresPermission(android.Manifest.permission.READ_CONTACTS)
        public static @AccountAttributes.AttributeFlags long getAccountAttributes(
                @NonNull ContentResolver resolver,
                @Nullable Account account, @Nullable String dataSet) {
            Bundle extras = new Bundle();
            if (account != null) {
                extras.putString(ACCOUNT_NAME, account.name);
                extras.putString(ACCOUNT_TYPE, account.type);
            }
            if (!TextUtils.isEmpty(dataSet)) {
                extras.putString(DATA_SET, dataSet);
            }

            Bundle response = nullSafeCall(resolver, ContactsContract.AUTHORITY_URI,
                    GET_ACCOUNT_ATTRIBUTES_METHOD, null, extras);
            if (response == null || !response.containsKey(KEY_ACCOUNT_ATTRIBUTES)) {
                throw new IllegalStateException(String.format(
                        "Could not determine attributes for account: %s, data_set: %s", account,
                        dataSet));
            }
            return response.getLong(KEY_ACCOUNT_ATTRIBUTES);
        }

        /**
         * Sets the attributes for a given account with a new set of flags.
         *
         * <p><b>Warning:</b> This is a destructive operation. Any attributes previously
         * set on the account will be cleared and replaced by the provided {@code newAttributes}.
         *
         * <p>The provided bitmask must be valid and free of semantic conflicts (e.g.,
         * containing more than one {@code DATA_ORIGIN} type).
         *
         * <h4>Security</h4>
         * <p> This method requires that the calling application to be the authenticator
         * for the account's type.
         * @see android.accounts.AccountManager#getAuthenticatorTypes()
         *
         * @param resolver        The {@code ContentResolver} to use for the update.
         * @param account         The target account. If {@code null}, this operation applies to the
         *                        local, device-only account.
         * @param dataSet         The data set within the account, which may be {@code null}.
         * @param newAttributes The complete new bitmask of attributes to apply.
         * @throws IllegalArgumentException if {@code newAttributes} contains any undefined
         *                                  bits, has semantic conflicts, or the account is
         *                                  otherwise invalid.
         */
        @FlaggedApi(Flags.FLAG_NEW_ACCOUNT_ATTRIBUTES_API_ENABLED)
        @RequiresPermission(android.Manifest.permission.WRITE_CONTACTS)
        public static void setAccountAttributes(@NonNull ContentResolver resolver,
                @Nullable Account account, @Nullable String dataSet,
                @AccountAttributes.AttributeFlags long newAttributes) {
            Bundle extras = new Bundle();
            if (account != null) {
                extras.putString(ACCOUNT_NAME, account.name);
                extras.putString(ACCOUNT_TYPE, account.type);
            }
            if (!TextUtils.isEmpty(dataSet)) {
                extras.putString(DATA_SET, dataSet);
            }
            extras.putLong(KEY_ACCOUNT_ATTRIBUTES, newAttributes);
            nullSafeCall(resolver, ContactsContract.AUTHORITY_URI,
                    SET_ACCOUNT_ATTRIBUTES_METHOD, null,
                    extras);
        }
    }

    /**
+9 −0
Original line number Diff line number Diff line
@@ -87,3 +87,12 @@ flag {
    description: "Feature flag to expose SYSTEM_UPDATE_SETTINGS as a public API"
    bug: "417458670"
}

# OWNER = liefuliu
flag {
    name: "new_account_attributes_api_enabled"
    is_exported: true
    namespace: "contacts"
    description: "Enable the new Account Attributes APIs for contacts"
    bug: "330326187"
}
 No newline at end of file