Merge changes from topic "contactkey_update_by_other_apps" into main
* changes:
Add WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS to Shell.
Add APIs for apps to update Contact keys of other apps.
Add WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS permission.
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index cf6f4f5..e6040f8 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -414,6 +414,7 @@
field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
field public static final String WRITE_SECURITY_LOG = "android.permission.WRITE_SECURITY_LOG";
field public static final String WRITE_SMS = "android.permission.WRITE_SMS";
+ field @FlaggedApi("android.provider.user_keys") public static final String WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS = "android.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS";
}
public static final class Manifest.permission_group {
@@ -11304,6 +11305,12 @@
field public static final int ERROR_UNKNOWN = 0; // 0x0
}
+ @FlaggedApi("android.provider.user_keys") public class ContactKeysManager {
+ method @RequiresPermission(allOf={android.Manifest.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS, android.Manifest.permission.WRITE_CONTACTS}) public boolean updateContactKeyLocalVerificationState(@NonNull String, @NonNull String, @NonNull String, @NonNull String, int);
+ method @RequiresPermission(allOf={android.Manifest.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS, android.Manifest.permission.WRITE_CONTACTS}) public boolean updateContactKeyRemoteVerificationState(@NonNull String, @NonNull String, @NonNull String, @NonNull String, int);
+ method @RequiresPermission(allOf={android.Manifest.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS, android.Manifest.permission.WRITE_CONTACTS}) public boolean updateSelfKeyRemoteVerificationState(@NonNull String, @NonNull String, @NonNull String, int);
+ }
+
@Deprecated public static final class ContactsContract.MetadataSync implements android.provider.BaseColumns android.provider.ContactsContract.MetadataSyncColumns {
field @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata";
field @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata";
diff --git a/core/java/android/provider/ContactKeysManager.java b/core/java/android/provider/ContactKeysManager.java
index ecde699..bef6456 100644
--- a/core/java/android/provider/ContactKeysManager.java
+++ b/core/java/android/provider/ContactKeysManager.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
@@ -247,6 +248,44 @@
}
/**
+ * Updates a contact key entry's local verification state that belongs to the app identified
+ * by ownerPackageName.
+ *
+ * @param lookupKey the value that references the contact
+ * @param deviceId an app-specified identifier for the device
+ * @param accountId an app-specified identifier for the account
+ * @param ownerPackageName the package name of the app that owns the key
+ * @param localVerificationState the new local verification state
+ *
+ * @return true if the entry was updated, false otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS,
+ android.Manifest.permission.WRITE_CONTACTS})
+ public boolean updateContactKeyLocalVerificationState(@NonNull String lookupKey,
+ @NonNull String deviceId,
+ @NonNull String accountId,
+ @NonNull String ownerPackageName,
+ @VerificationState int localVerificationState) {
+ validateVerificationState(localVerificationState);
+
+ final Bundle extras = new Bundle();
+ extras.putString(ContactKeys.LOOKUP_KEY, Objects.requireNonNull(lookupKey));
+ extras.putString(ContactKeys.DEVICE_ID, Objects.requireNonNull(deviceId));
+ extras.putString(ContactKeys.ACCOUNT_ID, Objects.requireNonNull(accountId));
+ extras.putString(ContactKeys.OWNER_PACKAGE_NAME, Objects.requireNonNull(ownerPackageName));
+ extras.putInt(ContactKeys.LOCAL_VERIFICATION_STATE, localVerificationState);
+
+ final Bundle response = nullSafeCall(mContentResolver,
+ ContactKeys.UPDATE_CONTACT_KEY_LOCAL_VERIFICATION_STATE_METHOD, extras);
+
+ return response != null && response.getBoolean(ContactKeys.KEY_UPDATED_ROWS);
+ }
+
+ /**
* Updates a contact key entry's remote verification state that belongs to the caller app.
*
* @param lookupKey the value that references the contact
@@ -275,6 +314,45 @@
return response != null && response.getBoolean(ContactKeys.KEY_UPDATED_ROWS);
}
+ /**
+ * Updates a contact key entry's remote verification state that belongs to the app identified
+ * by ownerPackageName.
+ *
+ * @param lookupKey the value that references the contact
+ * @param deviceId an app-specified identifier for the device
+ * @param accountId an app-specified identifier for the account
+ * @param ownerPackageName the package name of the app that owns the key
+ * @param remoteVerificationState the new remote verification state
+ *
+ * @return true if the entry was updated, false otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS,
+ android.Manifest.permission.WRITE_CONTACTS})
+ public boolean updateContactKeyRemoteVerificationState(@NonNull String lookupKey,
+ @NonNull String deviceId,
+ @NonNull String accountId,
+ @NonNull String ownerPackageName,
+ @VerificationState int remoteVerificationState) {
+ validateVerificationState(remoteVerificationState);
+
+ final Bundle extras = new Bundle();
+ extras.putString(ContactKeys.LOOKUP_KEY, Objects.requireNonNull(lookupKey));
+ extras.putString(ContactKeys.DEVICE_ID, Objects.requireNonNull(deviceId));
+ extras.putString(ContactKeys.ACCOUNT_ID, Objects.requireNonNull(accountId));
+ extras.putString(ContactKeys.OWNER_PACKAGE_NAME, Objects.requireNonNull(ownerPackageName));
+ extras.putInt(ContactKeys.REMOTE_VERIFICATION_STATE, remoteVerificationState);
+
+ final Bundle response = nullSafeCall(mContentResolver,
+ ContactKeys.UPDATE_CONTACT_KEY_REMOTE_VERIFICATION_STATE_METHOD, extras);
+
+ return response != null && response.getBoolean(ContactKeys.KEY_UPDATED_ROWS);
+ }
+
+
private static void validateVerificationState(int verificationState) {
if (verificationState != UNVERIFIED
&& verificationState != VERIFICATION_FAILED
@@ -297,12 +375,12 @@
public boolean removeContactKey(@NonNull String lookupKey,
@NonNull String deviceId,
@NonNull String accountId) {
- Bundle extras = new Bundle();
+ final Bundle extras = new Bundle();
extras.putString(ContactKeys.LOOKUP_KEY, Objects.requireNonNull(lookupKey));
extras.putString(ContactKeys.DEVICE_ID, Objects.requireNonNull(deviceId));
extras.putString(ContactKeys.ACCOUNT_ID, Objects.requireNonNull(accountId));
- Bundle response = nullSafeCall(mContentResolver,
+ final Bundle response = nullSafeCall(mContentResolver,
ContactKeys.REMOVE_CONTACT_KEY_METHOD, extras);
return response != null && response.getBoolean(ContactKeys.KEY_UPDATED_ROWS);
@@ -369,6 +447,41 @@
}
/**
+ * Updates a self key entry's remote verification state that belongs to the app identified
+ * by ownerPackageName.
+ *
+ * @param deviceId an app-specified identifier for the device
+ * @param accountId an app-specified identifier for the account
+ * @param ownerPackageName the package name of the app that owns the key
+ * @param remoteVerificationState the new remote verification state
+ *
+ * @return true if the entry was updated, false otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS,
+ android.Manifest.permission.WRITE_CONTACTS})
+ public boolean updateSelfKeyRemoteVerificationState(@NonNull String deviceId,
+ @NonNull String accountId,
+ @NonNull String ownerPackageName,
+ @VerificationState int remoteVerificationState) {
+ validateVerificationState(remoteVerificationState);
+
+ Bundle extras = new Bundle();
+ extras.putString(ContactKeys.DEVICE_ID, Objects.requireNonNull(deviceId));
+ extras.putString(ContactKeys.ACCOUNT_ID, Objects.requireNonNull(accountId));
+ extras.putString(ContactKeys.OWNER_PACKAGE_NAME, Objects.requireNonNull(ownerPackageName));
+ extras.putInt(ContactKeys.REMOTE_VERIFICATION_STATE, remoteVerificationState);
+
+ Bundle response = nullSafeCall(mContentResolver,
+ ContactKeys.UPDATE_SELF_KEY_REMOTE_VERIFICATION_STATE_METHOD, extras);
+
+ return response != null && response.getBoolean(ContactKeys.KEY_UPDATED_ROWS);
+ }
+
+ /**
* Maximum size of a contact key.
*/
public static int getMaxKeySizeBytes() {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5fad4c6..21d2bf2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -881,6 +881,19 @@
android:description="@string/permdesc_writeContacts"
android:protectionLevel="dangerous" />
+ <!-- Allows an app to update the verification status of E2EE contact keys owned by other apps.
+ <p>This permission is only granted to system apps.
+ <p>Protection level: signature|privileged
+ @SystemApi
+ @hide
+ @FlaggedApi("android.provider.user_keys")
+ -->
+ <permission android:name="android.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_writeVerificationStateE2eeContactKeys"
+ android:description="@string/permdesc_writeVerificationStateE2eeContactKeys"
+ android:protectionLevel="signature|privileged" />
+
<!-- Allows an application to set default account for new contacts.
<p> This permission is only granted to system applications fulfilling the Contacts app role.
<p>Protection level: internal|role
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index be059f1..ec47313 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2227,6 +2227,11 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this.[CHAR_LIMIT=NONE] -->
<string name="permdesc_updatePackagesWithoutUserAction">Allows the holder to update the app it previously installed without user action</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
+ <string name="permlab_writeVerificationStateE2eeContactKeys">update the verification states of E2EE contact keys owned by other apps</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this.[CHAR_LIMIT=NONE] -->
+ <string name="permdesc_writeVerificationStateE2eeContactKeys">Allows the app to update the verification states of E2EE contact keys owned by other apps</string>
+
<!-- Policy administration -->
<!-- Title of policy access to limiting the user's password choices -->
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 2873428..d4c2c2b 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -571,6 +571,8 @@
<!-- Permission required for BinaryTransparencyService shell API and host test -->
<permission name="android.permission.GET_BACKGROUND_INSTALLED_PACKAGES" />
<permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/>
+ <!-- Permissions required for CTS test - CtsContactKeysProviderPrivilegedApp -->
+ <permission name="android.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 95e0e1b..32c7433 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -908,6 +908,9 @@
<!-- Permissions required for CTS test - CtsPermissionUiTestCases -->
<uses-permission android:name="android.permission.MANAGE_ENHANCED_CONFIRMATION_STATES" />
+ <!-- Permissions required for CTS test - CtsContactKeysProviderPrivilegedApp -->
+ <uses-permission android:name="android.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS"/>
+
<application
android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"