Add 'E2ee' prefix to class names.
Rename ContactKeysManager to E2eeContactKeysManager, ContactKey to E2eeContactKey and SelfKey to E2eeSelfKey.
Bug: 322979243
Test: atest CtsContactKeysManagerTestCases:E2eeContactKeysManagerTest
Change-Id: I48ec232459d6ca2c706782e66f0ddcd43a1cc903
diff --git a/Android.bp b/Android.bp
index 3cc6bce..ab0fa8f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4,7 +4,7 @@
}
android_app {
- name: "ContactKeysProvider",
+ name: "E2eeContactKeysProvider",
defaults: ["platform_app_defaults"],
// Only compile source java files in this apk.
srcs: [
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index bd6e05c..4d1fa31 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -25,7 +25,7 @@
android:forceQueryable="true"
android:usesCleartextTraffic="false">
- <provider android:name=".ContactKeysProvider"
+ <provider android:name=".E2eeContactKeysProvider"
android:authorities="com.android.contactkeys.contactkeysprovider"
android:syncable="false"
android:multiprocess="false"
diff --git a/src/com/android/providers/contactkeys/ContactKeysDatabaseHelper.java b/src/com/android/providers/contactkeys/ContactKeysDatabaseHelper.java
deleted file mode 100644
index d1a2e66..0000000
--- a/src/com/android/providers/contactkeys/ContactKeysDatabaseHelper.java
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.providers.contactkeys;
-
-import android.annotation.FlaggedApi;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteStatement;
-import android.provider.ContactKeysManager;
-import android.provider.ContactKeysManager.ContactKeys;
-import android.provider.Flags;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Database helper for contact keys.
- */
-@FlaggedApi(Flags.FLAG_USER_KEYS)
-public class ContactKeysDatabaseHelper extends SQLiteOpenHelper {
-
- private static final String TAG = "ContactKeysDbHelper";
-
- private static final String CONTACT_KEYS_TABLE_NAME = "contactkeys";
- private static final String SELF_KEYS_TABLE_NAME = "selfkeys";
- private static final String DATABASE_NAME = "contact_keys_provider.db";
- private static final int DATABASE_VERSION = 1;
-
- ContactKeysDatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- Log.i(TAG, "Bootstrapping database " + DATABASE_NAME + " version: " + DATABASE_VERSION);
- db.execSQL("CREATE TABLE " + CONTACT_KEYS_TABLE_NAME + " ("
- + ContactKeys.LOOKUP_KEY + " TEXT NOT NULL, "
- + ContactKeys.DEVICE_ID + " TEXT NOT NULL, "
- + ContactKeys.ACCOUNT_ID + " TEXT NOT NULL, "
- + ContactKeys.OWNER_PACKAGE_NAME + " TEXT NOT NULL, "
- + ContactKeys.TIME_UPDATED + " INTEGER NOT NULL default 0, "
- + ContactKeys.KEY_VALUE + " BLOB NOT NULL, "
- + ContactKeys.DISPLAY_NAME + " TEXT, "
- + ContactKeys.PHONE_NUMBER + " TEXT, "
- + ContactKeys.EMAIL_ADDRESS + " TEXT, "
- + ContactKeys.LOCAL_VERIFICATION_STATE + " INTEGER NOT NULL default 0, "
- + ContactKeys.REMOTE_VERIFICATION_STATE + " INTEGER NOT NULL default 0, "
- + " PRIMARY KEY ("
- + ContactKeys.LOOKUP_KEY + ", "
- + ContactKeys.DEVICE_ID + ", "
- + ContactKeys.ACCOUNT_ID + ", "
- + ContactKeys.OWNER_PACKAGE_NAME
- + "));");
- db.execSQL("CREATE TABLE " + SELF_KEYS_TABLE_NAME + " ("
- + ContactKeys.DEVICE_ID + " TEXT NOT NULL, "
- + ContactKeys.ACCOUNT_ID + " TEXT NOT NULL, "
- + ContactKeys.OWNER_PACKAGE_NAME + " TEXT NOT NULL, "
- + ContactKeys.TIME_UPDATED + " INTEGER NOT NULL default 0, "
- + ContactKeys.KEY_VALUE + " BLOB NOT NULL, "
- + ContactKeys.REMOTE_VERIFICATION_STATE + " INTEGER NOT NULL default 0,"
- + " PRIMARY KEY ("
- + ContactKeys.DEVICE_ID + ", "
- + ContactKeys.ACCOUNT_ID + ", "
- + ContactKeys.OWNER_PACKAGE_NAME
- + "));");
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // Nothing to do here, still on version 1
- }
-
- /**
- * Gets all contact keys in the contact keys table for a given lookupKey.
- */
- public List<ContactKeysManager.ContactKey> getAllContactKeys(String lookupKey) {
- try (Cursor c = getReadableDatabase().rawQuery(
- "SELECT DISTINCT " + ContactKeys.DEVICE_ID + ","
- + ContactKeys.ACCOUNT_ID + ","
- + ContactKeys.OWNER_PACKAGE_NAME + ","
- + ContactKeys.TIME_UPDATED + ","
- + ContactKeys.KEY_VALUE + ","
- + ContactKeys.DISPLAY_NAME + ","
- + ContactKeys.PHONE_NUMBER + ","
- + ContactKeys.EMAIL_ADDRESS + ","
- + ContactKeys.LOCAL_VERIFICATION_STATE + ","
- + ContactKeys.REMOTE_VERIFICATION_STATE
- + " FROM " + CONTACT_KEYS_TABLE_NAME
- + " WHERE " + ContactKeys.LOOKUP_KEY + " = ?",
- new String[] {lookupKey})) {
- final List<ContactKeysManager.ContactKey> result = new ArrayList<>(c.getCount());
- while (c.moveToNext()) {
- String deviceId = c.getString(c.getColumnIndexOrThrow(ContactKeys.DEVICE_ID));
- String accountId = c.getString(c.getColumnIndexOrThrow(ContactKeys.ACCOUNT_ID));
- String ownerPackageName = c.getString(
- c.getColumnIndexOrThrow(ContactKeys.OWNER_PACKAGE_NAME));
- long timeUpdated = c.getLong(c.getColumnIndexOrThrow(ContactKeys.TIME_UPDATED));
- byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(ContactKeys.KEY_VALUE));
- String displayName = c.getString(c.getColumnIndexOrThrow(
- ContactKeys.DISPLAY_NAME));
- String number = c.getString(c.getColumnIndexOrThrow(ContactKeys.PHONE_NUMBER));
- String emailAddress = c.getString(c.getColumnIndexOrThrow(
- ContactKeys.EMAIL_ADDRESS));
- int localVerificationState = c.getInt(c.getColumnIndexOrThrow(
- ContactKeys.LOCAL_VERIFICATION_STATE));
- int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
- ContactKeys.REMOTE_VERIFICATION_STATE));
- result.add(new ContactKeysManager.ContactKey(deviceId, accountId, ownerPackageName,
- timeUpdated, keyValue, localVerificationState, remoteVerificationState,
- displayName, number, emailAddress));
- }
- return result;
- }
- }
-
- /**
- * Gets all contact keys in the contact keys table for a given lookupKey and ownerPackageName.
- */
- public List<ContactKeysManager.ContactKey> getContactKeysForOwnerPackageName(String lookupKey,
- String ownerPackageName) {
- try (Cursor c = getReadableDatabase().rawQuery(
- "SELECT DISTINCT " + ContactKeys.DEVICE_ID + ","
- + ContactKeys.ACCOUNT_ID + ","
- + ContactKeys.TIME_UPDATED + ","
- + ContactKeys.KEY_VALUE + ","
- + ContactKeys.DISPLAY_NAME + ","
- + ContactKeys.PHONE_NUMBER + ","
- + ContactKeys.EMAIL_ADDRESS + ","
- + ContactKeys.LOCAL_VERIFICATION_STATE + ","
- + ContactKeys.REMOTE_VERIFICATION_STATE
- + " FROM " + CONTACT_KEYS_TABLE_NAME
- + " WHERE " + ContactKeys.LOOKUP_KEY + " = ?"
- + " AND " + ContactKeys.OWNER_PACKAGE_NAME + " = ?",
- new String[] {lookupKey, String.valueOf(ownerPackageName)})) {
- final List<ContactKeysManager.ContactKey> result = new ArrayList<>(c.getCount());
- while (c.moveToNext()) {
- String deviceId = c.getString(c.getColumnIndexOrThrow(ContactKeys.DEVICE_ID));
- String accountId = c.getString(c.getColumnIndexOrThrow(ContactKeys.ACCOUNT_ID));
- long timeUpdated = c.getLong(c.getColumnIndexOrThrow(ContactKeys.TIME_UPDATED));
- byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(ContactKeys.KEY_VALUE));
- String displayName = c.getString(c.getColumnIndexOrThrow(
- ContactKeys.DISPLAY_NAME));
- String number = c.getString(c.getColumnIndexOrThrow(ContactKeys.PHONE_NUMBER));
- String emailAddress = c.getString(c.getColumnIndexOrThrow(
- ContactKeys.EMAIL_ADDRESS));
- int localVerificationState = c.getInt(c.getColumnIndexOrThrow(
- ContactKeys.LOCAL_VERIFICATION_STATE));
- int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
- ContactKeys.REMOTE_VERIFICATION_STATE));
- result.add(new ContactKeysManager.ContactKey(deviceId, accountId, ownerPackageName,
- timeUpdated, keyValue, localVerificationState, remoteVerificationState,
- displayName, number, emailAddress));
- }
- return result;
- }
- }
-
- /**
- * Get a contact key for given parameters.
- */
- public ContactKeysManager.ContactKey getContactKey(String lookupKey, String ownerPackageName,
- String deviceId, String accountId) {
- ContactKeysManager.ContactKey result = null;
- try (Cursor c = getReadableDatabase().rawQuery(
- "SELECT " + ContactKeys.KEY_VALUE + ","
- + ContactKeys.TIME_UPDATED + ","
- + ContactKeys.DISPLAY_NAME + ","
- + ContactKeys.PHONE_NUMBER + ","
- + ContactKeys.EMAIL_ADDRESS + ","
- + ContactKeys.LOCAL_VERIFICATION_STATE + ","
- + ContactKeys.REMOTE_VERIFICATION_STATE + " FROM "
- + CONTACT_KEYS_TABLE_NAME
- + " WHERE " + ContactKeys.LOOKUP_KEY + " = ?"
- + " AND " + ContactKeys.OWNER_PACKAGE_NAME + " = ?"
- + " AND " + ContactKeys.DEVICE_ID + " = ?"
- + " AND " + ContactKeys.ACCOUNT_ID + " = ?",
- new String[] {lookupKey, String.valueOf(ownerPackageName), deviceId, accountId})) {
- if (c.moveToNext()) {
- byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(ContactKeys.KEY_VALUE));
- long timeUpdated = c.getLong(c.getColumnIndexOrThrow(ContactKeys.TIME_UPDATED));
- String displayName = c.getString(c.getColumnIndexOrThrow(
- ContactKeys.DISPLAY_NAME));
- String number = c.getString(c.getColumnIndexOrThrow(ContactKeys.PHONE_NUMBER));
- String emailAddress = c.getString(c.getColumnIndexOrThrow(
- ContactKeys.EMAIL_ADDRESS));
- int localVerificationState = c.getInt(c.getColumnIndexOrThrow(
- ContactKeys.LOCAL_VERIFICATION_STATE));
- int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
- ContactKeys.REMOTE_VERIFICATION_STATE));
- result = new ContactKeysManager.ContactKey(deviceId, accountId, ownerPackageName,
- timeUpdated, keyValue, localVerificationState, remoteVerificationState,
- displayName, number, emailAddress);
- }
- }
-
- return result;
- }
-
- /**
- * Updates the contact key local verification state and returns the number of keys updated
- * (should always be 0 or 1).
- */
- public int updateContactKeyLocalVerificationState(String lookupKey, String ownerPackageName,
- String deviceId, String accountId, int localVerificationState, long timeUpdated) {
- try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
- "UPDATE " + CONTACT_KEYS_TABLE_NAME
- + " SET " + ContactKeys.LOCAL_VERIFICATION_STATE
- + " = ?, "
- + ContactKeys.TIME_UPDATED + " = ?"
- + " WHERE " + ContactKeys.LOOKUP_KEY + " = ?"
- + " AND " + ContactKeys.OWNER_PACKAGE_NAME + " = ?"
- + " AND " + ContactKeys.DEVICE_ID + " = ?"
- + " AND " + ContactKeys.ACCOUNT_ID + " = ?")) {
- updateStatement.bindLong(1, localVerificationState);
- updateStatement.bindLong(2, timeUpdated);
- updateStatement.bindString(3, lookupKey);
- updateStatement.bindString(4, ownerPackageName);
- updateStatement.bindString(5, deviceId);
- updateStatement.bindString(6, accountId);
- return updateStatement.executeUpdateDelete();
- }
- }
-
- /**
- * Updates the contact key remote verification state and returns the number of keys updated
- * (should always be 0 or 1).
- */
- public int updateContactKeyRemoteVerificationState(String lookupKey, String ownerPackageName,
- String deviceId, String accountId, int remoteVerificationState, long timeUpdated) {
- try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
- "UPDATE " + CONTACT_KEYS_TABLE_NAME
- + " SET " + ContactKeys.REMOTE_VERIFICATION_STATE
- + " = ?, "
- + ContactKeys.TIME_UPDATED + " = ?"
- + " WHERE " + ContactKeys.LOOKUP_KEY + " = ?"
- + " AND " + ContactKeys.OWNER_PACKAGE_NAME + " = ?"
- + " AND " + ContactKeys.DEVICE_ID + " = ?"
- + " AND " + ContactKeys.ACCOUNT_ID + " = ?")) {
- updateStatement.bindLong(1, remoteVerificationState);
- updateStatement.bindLong(2, timeUpdated);
- updateStatement.bindString(3, lookupKey);
- updateStatement.bindString(4, ownerPackageName);
- updateStatement.bindString(5, deviceId);
- updateStatement.bindString(6, accountId);
- return updateStatement.executeUpdateDelete();
- }
- }
-
- /**
- * Inserts a new contact key or updates an existing one and returns the number of keys
- * inserted/updated (should always be 0 or 1).
- */
- public int updateOrInsertContactKey(String lookupKey, byte[] keyValue, String deviceId,
- String accountId, String ownerPackageName, long timeUpdated,
- String displayName, String number, String emailAddress) {
- try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
- "INSERT INTO " + CONTACT_KEYS_TABLE_NAME + " ("
- + ContactKeys.LOOKUP_KEY + ", "
- + ContactKeys.DEVICE_ID + ", "
- + ContactKeys.ACCOUNT_ID + ", "
- + ContactKeys.OWNER_PACKAGE_NAME + ", "
- + ContactKeys.KEY_VALUE + ", "
- + ContactKeys.TIME_UPDATED + ", "
- + ContactKeys.DISPLAY_NAME + ", "
- + ContactKeys.PHONE_NUMBER + ", "
- + ContactKeys.EMAIL_ADDRESS
- + ") VALUES "
- + "(?, ?, ?, ?, ?, ?, ?, ?, ?) "
- + "ON CONFLICT ("
- + ContactKeys.LOOKUP_KEY + ", "
- + ContactKeys.DEVICE_ID + ", "
- + ContactKeys.ACCOUNT_ID + ", "
- + ContactKeys.OWNER_PACKAGE_NAME + ") "
- + "DO UPDATE SET " + ContactKeys.KEY_VALUE + " = ?, "
- + ContactKeys.TIME_UPDATED + " = ?, "
- + ContactKeys.DISPLAY_NAME + " = ?, "
- + ContactKeys.PHONE_NUMBER + " = ?, "
- + ContactKeys.EMAIL_ADDRESS + " = ?")) {
- updateStatement.bindString(1, lookupKey);
- updateStatement.bindString(2, deviceId);
- updateStatement.bindString(3, accountId);
- updateStatement.bindString(4, ownerPackageName);
- updateStatement.bindBlob(5, keyValue);
- updateStatement.bindLong(6, timeUpdated);
- if (displayName != null) {
- updateStatement.bindString(7, displayName);
- } else {
- updateStatement.bindNull(7);
- }
- if (number != null) {
- updateStatement.bindString(8, number);
- } else {
- updateStatement.bindNull(8);
- }
- if (emailAddress != null) {
- updateStatement.bindString(9, emailAddress);
- } else {
- updateStatement.bindNull(9);
- }
- updateStatement.bindBlob(10, keyValue);
- updateStatement.bindLong(11, timeUpdated);
- if (displayName != null) {
- updateStatement.bindString(12, displayName);
- } else {
- updateStatement.bindNull(12);
- }
- if (number != null) {
- updateStatement.bindString(13, number);
- } else {
- updateStatement.bindNull(13);
- }
- if (emailAddress != null) {
- updateStatement.bindString(14, emailAddress);
- } else {
- updateStatement.bindNull(14);
- }
- return updateStatement.executeUpdateDelete();
- }
- }
-
- /**
- * Removes the contact key and returns the number of keys removed (should always be 0 or 1).
- */
- public int removeContactKey(String lookupKey, String deviceId, String accountId,
- String ownerPackageName) {
- try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
- "DELETE FROM " + CONTACT_KEYS_TABLE_NAME
- + " WHERE " + ContactKeys.LOOKUP_KEY + " = ?"
- + " AND " + ContactKeys.DEVICE_ID + " = ?"
- + " AND " + ContactKeys.ACCOUNT_ID + " = ?"
- + " AND " + ContactKeys.OWNER_PACKAGE_NAME + " = ?")) {
- updateStatement.bindString(1, lookupKey);
- updateStatement.bindString(2, deviceId);
- updateStatement.bindString(3, accountId);
- updateStatement.bindString(4, ownerPackageName);
- return updateStatement.executeUpdateDelete();
- }
- }
-
- /**
- * Gets a self key for given parameters.
- */
- public ContactKeysManager.SelfKey getSelfKey(String deviceId, String accountId,
- String ownerPackageName) {
- ContactKeysManager.SelfKey result = null;
- try (Cursor c = getReadableDatabase().rawQuery(
- "SELECT " + ContactKeys.KEY_VALUE + ","
- + ContactKeys.TIME_UPDATED + ","
- + ContactKeys.REMOTE_VERIFICATION_STATE + " FROM "
- + SELF_KEYS_TABLE_NAME
- + " WHERE " + ContactKeys.DEVICE_ID + " = ?"
- + " AND " + ContactKeys.ACCOUNT_ID + " = ?"
- + " AND " + ContactKeys.OWNER_PACKAGE_NAME + " = ?",
- new String[] {deviceId, accountId, ownerPackageName})) {
- if (c.moveToNext()) {
- byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(ContactKeys.KEY_VALUE));
- long timeUpdated = c.getLong(c.getColumnIndexOrThrow(ContactKeys.TIME_UPDATED));
- int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
- ContactKeys.REMOTE_VERIFICATION_STATE));
- result = new ContactKeysManager.SelfKey(deviceId, accountId, ownerPackageName,
- timeUpdated, keyValue, remoteVerificationState);
- }
- }
- return result;
- }
-
- /**
- * Gets all self keys in the self keys table.
- */
- public List<ContactKeysManager.SelfKey> getAllSelfKeys() {
- try (Cursor c = getReadableDatabase().rawQuery(
- "SELECT DISTINCT " + ContactKeys.DEVICE_ID + ","
- + ContactKeys.ACCOUNT_ID + ","
- + ContactKeys.OWNER_PACKAGE_NAME + ","
- + ContactKeys.TIME_UPDATED + ","
- + ContactKeys.KEY_VALUE + ","
- + ContactKeys.REMOTE_VERIFICATION_STATE
- + " FROM " + SELF_KEYS_TABLE_NAME,
- new String[] {})) {
- final List<ContactKeysManager.SelfKey> result = new ArrayList<>(c.getCount());
- while (c.moveToNext()) {
- String deviceId = c.getString(c.getColumnIndexOrThrow(ContactKeys.DEVICE_ID));
- String accountId = c.getString(c.getColumnIndexOrThrow(ContactKeys.ACCOUNT_ID));
- String ownerPackageName = c.getString(
- c.getColumnIndexOrThrow(ContactKeys.OWNER_PACKAGE_NAME));
- long timeUpdated = c.getLong(c.getColumnIndexOrThrow(ContactKeys.TIME_UPDATED));
- byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(ContactKeys.KEY_VALUE));
- int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
- ContactKeys.REMOTE_VERIFICATION_STATE));
- result.add(new ContactKeysManager.SelfKey(deviceId, accountId, ownerPackageName,
- timeUpdated, keyValue, remoteVerificationState));
- }
- return result;
- }
- }
-
- /**
- * Gets all self keys in the self keys table for a given ownerPackageName.
- */
- public List<ContactKeysManager.SelfKey> getSelfKeysForOwnerPackageName(
- String ownerPackageName) {
- try (Cursor c = getReadableDatabase().rawQuery(
- "SELECT DISTINCT " + ContactKeys.DEVICE_ID + ","
- + ContactKeys.ACCOUNT_ID + ","
- + ContactKeys.TIME_UPDATED + ","
- + ContactKeys.KEY_VALUE + ","
- + ContactKeys.REMOTE_VERIFICATION_STATE
- + " FROM " + SELF_KEYS_TABLE_NAME
- + " WHERE " + ContactKeys.OWNER_PACKAGE_NAME + " = ?",
- new String[] {ownerPackageName})) {
- final List<ContactKeysManager.SelfKey> result = new ArrayList<>(c.getCount());
- while (c.moveToNext()) {
- String deviceId = c.getString(c.getColumnIndexOrThrow(ContactKeys.DEVICE_ID));
- String accountId = c.getString(c.getColumnIndexOrThrow(ContactKeys.ACCOUNT_ID));
- long timeUpdated = c.getLong(c.getColumnIndexOrThrow(ContactKeys.TIME_UPDATED));
- byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(ContactKeys.KEY_VALUE));
- int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
- ContactKeys.REMOTE_VERIFICATION_STATE));
- result.add(new ContactKeysManager.SelfKey(deviceId, accountId, ownerPackageName,
- timeUpdated, keyValue, remoteVerificationState));
- }
- return result;
- }
- }
-
- /**
- * Inserts a new self key or updates an existing one and returns the number of keys
- * inserted/updated (should always be 0 or 1).
- */
- public int updateOrInsertSelfKey(byte[] keyValue, String deviceId, String accountId,
- String ownerPackageName, long timeUpdated) {
- try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
- "INSERT INTO " + SELF_KEYS_TABLE_NAME + " ("
- + ContactKeys.DEVICE_ID + ", "
- + ContactKeys.ACCOUNT_ID + ", "
- + ContactKeys.OWNER_PACKAGE_NAME + ", "
- + ContactKeys.KEY_VALUE + ", "
- + ContactKeys.TIME_UPDATED
- + ") VALUES "
- + "(?, ?, ?, ?, ?) "
- + "ON CONFLICT ("
- + ContactKeys.DEVICE_ID + ", "
- + ContactKeys.ACCOUNT_ID + ", "
- + ContactKeys.OWNER_PACKAGE_NAME + ") "
- + "DO UPDATE SET " + ContactKeys.KEY_VALUE + " = ?, "
- + ContactKeys.TIME_UPDATED + " = ?")) {
- updateStatement.bindString(1, deviceId);
- updateStatement.bindString(2, accountId);
- updateStatement.bindString(3, ownerPackageName);
- updateStatement.bindBlob(4, keyValue);
- updateStatement.bindLong(5, timeUpdated);
- updateStatement.bindBlob(6, keyValue);
- updateStatement.bindLong(7, timeUpdated);
- return updateStatement.executeUpdateDelete();
- }
- }
-
- /**
- * Updates the self key remote verification state and returns the number of keys updated
- * (should always be 0 or 1).
- */
- public int updateSelfKeyRemoteVerificationState(String ownerPackageName, String deviceId,
- String accountId, int remoteVerificationState, long timeUpdated) {
- try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
- "UPDATE " + SELF_KEYS_TABLE_NAME
- + " SET " + ContactKeys.REMOTE_VERIFICATION_STATE + " = ?, "
- + ContactKeys.TIME_UPDATED + " = ?"
- + " WHERE " + ContactKeys.OWNER_PACKAGE_NAME + " = ?"
- + " AND " + ContactKeys.DEVICE_ID + " = ?"
- + " AND " + ContactKeys.ACCOUNT_ID + " = ?")) {
- updateStatement.bindLong(1, remoteVerificationState);
- updateStatement.bindLong(2, timeUpdated);
- updateStatement.bindString(3, ownerPackageName);
- updateStatement.bindString(4, deviceId);
- updateStatement.bindString(5, accountId);
- return updateStatement.executeUpdateDelete();
- }
- }
-
- /**
- * Removes a self key with given parameters.
- */
- public int removeSelfKey(String deviceId, String accountId, String ownerPackageName) {
- try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
- "DELETE FROM " + SELF_KEYS_TABLE_NAME
- + " WHERE " + ContactKeys.DEVICE_ID + " = ?"
- + " AND " + ContactKeys.ACCOUNT_ID + " = ?"
- + " AND " + ContactKeys.OWNER_PACKAGE_NAME + " = ?")) {
- updateStatement.bindString(1, deviceId);
- updateStatement.bindString(2, accountId);
- updateStatement.bindString(3, ownerPackageName);
- return updateStatement.executeUpdateDelete();
- }
- }
-}
diff --git a/src/com/android/providers/contactkeys/ContactKeysProvider.java b/src/com/android/providers/contactkeys/ContactKeysProvider.java
deleted file mode 100644
index 17dba63..0000000
--- a/src/com/android/providers/contactkeys/ContactKeysProvider.java
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.providers.contactkeys;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
-import android.provider.ContactKeysManager;
-import android.provider.ContactKeysManager.ContactKeys;
-import android.provider.ContactsContract;
-import android.provider.Flags;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.providers.contactkeys.util.ContactKeysPermissions;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Provides access to a database of contact keys.
- */
-@FlaggedApi(Flags.FLAG_USER_KEYS)
-public class ContactKeysProvider extends ContentProvider {
-
- /** The authority for the contact keys provider. */
- public static final String AUTHORITY = "com.android.contactkeys.contactkeysprovider";
-
- private static final String READ_PERMISSION = "android.permission.READ_CONTACTS";
- private static final String WRITE_PERMISSION = "android.permission.WRITE_CONTACTS";
- private static final String UPDATE_VERIFICATION_STATE_PERMISSION =
- "android.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS";
-
- /** Special timeUpdated value used when this data is stripped. */
- private static final long STRIPPED_TIME_UPDATED = -1;
-
- @VisibleForTesting
- ContactKeysDatabaseHelper mDbHelper;
-
- @Override
- public boolean onCreate() {
- mDbHelper = new ContactKeysDatabaseHelper(getContext());
- return true;
- }
-
- @Override
- public Bundle call(@NonNull String method, String arg, Bundle extras) {
- switch (method) {
- case ContactKeys.UPDATE_OR_INSERT_CONTACT_KEY_METHOD -> {
- return updateOrInsertContactKey(extras);
- }
- case ContactKeys.GET_CONTACT_KEY_METHOD -> {
- return getContactKey(extras);
- }
- case ContactKeys.GET_ALL_CONTACT_KEYS_METHOD -> {
- return getAllContactKeys(extras);
- }
- case ContactKeys.GET_OWNER_CONTACT_KEYS_METHOD -> {
- return getOwnerContactKeys(extras);
- }
- case ContactKeys.UPDATE_CONTACT_KEY_LOCAL_VERIFICATION_STATE_METHOD -> {
- return updateContactKeyLocalVerificationState(extras);
- }
- case ContactKeys.UPDATE_CONTACT_KEY_REMOTE_VERIFICATION_STATE_METHOD -> {
- return updateContactKeyRemoteVerificationState(extras);
- }
- case ContactKeys.REMOVE_CONTACT_KEY_METHOD -> {
- return removeContactKey(extras);
- }
- case ContactKeys.UPDATE_OR_INSERT_SELF_KEY_METHOD -> {
- return updateOrInsertSelfKey(extras);
- }
- case ContactKeys.UPDATE_SELF_KEY_REMOTE_VERIFICATION_STATE_METHOD -> {
- return updateSelfKeyRemoteVerificationState(extras);
- }
- case ContactKeys.GET_SELF_KEY_METHOD -> {
- return getSelfKey(extras);
- }
- case ContactKeys.GET_ALL_SELF_KEYS_METHOD -> {
- return getAllSelfKeys();
- }
- case ContactKeys.GET_OWNER_SELF_KEYS_METHOD -> {
- return getOwnerSelfKeys();
- }
- case ContactKeys.REMOVE_SELF_KEY_METHOD -> {
- return removeSelfKey(extras);
- }
- }
- throw new IllegalArgumentException("Unexpected method " + method);
- }
-
- /**
- * Inserts a new entry into the contact keys table or updates one if it already exists.
- *
- * @return Bundle with a {@link ContactKeys.KEY_UPDATED_ROWS} as a key and a
- * boolean value being true if the row was added or updated, false otherwise.
- */
- private Bundle updateOrInsertContactKey(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
-
- final Bundle response = new Bundle();
-
- final String lookupKey = extras.getString(ContactKeys.LOOKUP_KEY);
- final String deviceId = extras.getString(ContactKeys.DEVICE_ID);
- final String accountId = extras.getString(ContactKeys.ACCOUNT_ID);
- final byte[] keyValue = extras.getByteArray(ContactKeys.KEY_VALUE);
-
- Bundle contactInfo = getContactBasicInfoFromCP2(lookupKey);
- String displayName = contactInfo.getString(ContactKeys.DISPLAY_NAME);
- String number = contactInfo.getString(ContactKeys.PHONE_NUMBER);
- String emailAddress = contactInfo.getString(ContactKeys.EMAIL_ADDRESS);
-
- String callerPackageName = getCallingPackage();
- long timeUpdated = System.currentTimeMillis();
-
- int rowsUpdateOrInserted = mDbHelper.updateOrInsertContactKey(lookupKey, keyValue,
- deviceId, accountId, callerPackageName, timeUpdated, displayName, number,
- emailAddress);
-
- response.putBoolean(ContactKeys.KEY_UPDATED_ROWS, rowsUpdateOrInserted > 0);
-
- return response;
- }
-
- /**
- * Retrieves a contact key entry given the lookupKey, deviceId and the inferred package name of
- * the caller.
- *
- * @return Bundle with a {@link ContactKeys.KEY_CONTACT_KEY} as a key and a
- * parcelable {@link ContactKeysManager.ContactKey} as a value
- */
- private Bundle getContactKey(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
-
- final String lookupKey = extras.getString(ContactKeys.LOOKUP_KEY);
- final String deviceId = extras.getString(ContactKeys.DEVICE_ID);
- final String accountId = extras.getString(ContactKeys.ACCOUNT_ID);
- String callerPackageName = getCallingPackage();
-
- ContactKeysManager.ContactKey contactKey = mDbHelper.getContactKey(lookupKey,
- callerPackageName, deviceId, accountId);
-
- final Bundle response = new Bundle();
- response.putParcelable(ContactKeys.KEY_CONTACT_KEY, contactKey);
-
- return response;
- }
-
- /**
- * Retrieves all contact key entries given the lookupKey. All keys that belong to
- * apps visible to the caller will be returned.
- *
- * @return Bundle with a {@link ContactKeys.KEY_CONTACT_KEYS} as a key and
- * a parcelable list of {@link ContactKeysManager.ContactKey} as a value
- */
- private Bundle getAllContactKeys(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
- String lookupKey = extras.getString(ContactKeys.LOOKUP_KEY);
-
- final Bundle response = new Bundle();
-
- List<ContactKeysManager.ContactKey> contactKeys = mDbHelper.getAllContactKeys(lookupKey);
-
- contactKeys = filterVisibleContactKeys(contactKeys);
- contactKeys = getStrippedContactKeys(contactKeys);
-
- response.putParcelableList(ContactKeys.KEY_CONTACT_KEYS, contactKeys);
-
- return response;
- }
-
- /**
- * Retrieves all contact key entries given the lookupKey. All keys that belong to the caller
- * will be returned.
- *
- * @return Bundle with a {@link ContactKeys.KEY_CONTACT_KEYS} as a key and
- * a parcelable list of {@link ContactKeysManager.ContactKey} as a value
- */
- private Bundle getOwnerContactKeys(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
- String lookupKey = extras.getString(ContactKeys.LOOKUP_KEY);
-
- final Bundle response = new Bundle();
-
- String callerPackageName = getCallingPackage();
- List<ContactKeysManager.ContactKey> contactKeys =
- mDbHelper.getContactKeysForOwnerPackageName(lookupKey, callerPackageName);
-
- response.putParcelableList(ContactKeys.KEY_CONTACT_KEYS, contactKeys);
-
- return response;
- }
-
- /**
- * Updates a contact key entry {@link ContactKeys.LOCAL_VERIFICATION_STATE}
- * given the lookupKey, deviceId, accountId and the inferred package name of the caller.
- *
- * @return Bundle with a {@link ContactKeys.KEY_UPDATED_ROWS} as a key and
- * a boolean value being true if the row was updated, false otherwise.
- */
- private Bundle updateContactKeyLocalVerificationState(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
-
- final String lookupKey = extras.getString(ContactKeys.LOOKUP_KEY);
- final String deviceId = extras.getString(ContactKeys.DEVICE_ID);
- final String accountId = extras.getString(ContactKeys.ACCOUNT_ID);
- final int localVerificationState =
- extras.getInt(ContactKeys.LOCAL_VERIFICATION_STATE);
- final long timeUpdated = System.currentTimeMillis();
- final String callerPackageName = getCallingPackage();
-
- int rowsUpdated;
- if (extras.containsKey(ContactKeys.OWNER_PACKAGE_NAME)) {
- final String ownerPackageName = extras.getString(ContactKeys.OWNER_PACKAGE_NAME);
- ContactKeysPermissions.enforceVisibility(getContext(),
- callerPackageName, ownerPackageName);
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(),
- UPDATE_VERIFICATION_STATE_PERMISSION);
- rowsUpdated = mDbHelper.updateContactKeyLocalVerificationState(lookupKey,
- ownerPackageName, deviceId, accountId, localVerificationState, timeUpdated);
- } else {
- rowsUpdated = mDbHelper.updateContactKeyLocalVerificationState(lookupKey,
- callerPackageName, deviceId, accountId, localVerificationState, timeUpdated);
- }
-
- final Bundle response = new Bundle();
- response.putBoolean(ContactKeys.KEY_UPDATED_ROWS, rowsUpdated > 0);
- return response;
- }
-
- /**
- * Updates a contact key entry {@link ContactKeys.REMOTE_VERIFICATION_STATE}
- * given the lookupKey, deviceId, accountId and the inferred package name of the caller.
- *
- * @return Bundle with a {@link ContactKeys.KEY_UPDATED_ROWS} as a key and
- * a boolean value being true if the row was updated, false otherwise.
- */
- private Bundle updateContactKeyRemoteVerificationState(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
-
- final String lookupKey = extras.getString(ContactKeys.LOOKUP_KEY);
- final String deviceId = extras.getString(ContactKeys.DEVICE_ID);
- final String accountId = extras.getString(ContactKeys.ACCOUNT_ID);
- final int remoteVerificationState =
- extras.getInt(ContactKeys.REMOTE_VERIFICATION_STATE);
- final long timeUpdated = System.currentTimeMillis();
- final String callerPackageName = getCallingPackage();
-
- int rowsUpdated;
- if (extras.containsKey(ContactKeys.OWNER_PACKAGE_NAME)) {
- final String ownerPackageName = extras.getString(ContactKeys.OWNER_PACKAGE_NAME);
- ContactKeysPermissions.enforceVisibility(getContext(),
- callerPackageName, ownerPackageName);
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(),
- UPDATE_VERIFICATION_STATE_PERMISSION);
- rowsUpdated = mDbHelper.updateContactKeyRemoteVerificationState(lookupKey,
- ownerPackageName, deviceId, accountId, remoteVerificationState, timeUpdated);
- } else {
- rowsUpdated = mDbHelper.updateContactKeyRemoteVerificationState(lookupKey,
- callerPackageName, deviceId, accountId, remoteVerificationState, timeUpdated);
- }
- final Bundle response = new Bundle();
- response.putBoolean(ContactKeys.KEY_UPDATED_ROWS, rowsUpdated > 0);
- return response;
- }
-
- /**
- * Removes a contact key entry given the lookupKey, deviceId, accountId and
- * the inferred package name of the caller.
- *
- * @return Bundle with a {@link ContactKeys.KEY_UPDATED_ROWS} as a key and
- * a boolean value being true if the row was removed, false otherwise.
- */
- private Bundle removeContactKey(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
-
- final String lookupKey = extras.getString(ContactKeys.LOOKUP_KEY);
- final String deviceId = extras.getString(ContactKeys.DEVICE_ID);
- final String accountId = extras.getString(ContactKeys.ACCOUNT_ID);
- String callerPackageName = getCallingPackage();
-
- int rowsRemoved = mDbHelper.removeContactKey(lookupKey, deviceId, accountId,
- callerPackageName);
-
- final Bundle response = new Bundle();
- response.putBoolean(ContactKeys.KEY_UPDATED_ROWS, rowsRemoved > 0);
- return response;
- }
-
- /**
- * Inserts a new entry into the self keys table or updates one if it already exists.
- *
- * @return Bundle with a {@link ContactKeys.KEY_UPDATED_ROWS} as a key and
- * a boolean value being true if the row was added or updated, false otherwise.
- */
- private Bundle updateOrInsertSelfKey(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
-
- final String deviceId = extras.getString(ContactKeys.DEVICE_ID);
- final String accountId = extras.getString(ContactKeys.ACCOUNT_ID);
- final byte[] keyValue = extras.getByteArray(ContactKeys.KEY_VALUE);
-
- String callerPackageName = getCallingPackage();
- long timeUpdated = System.currentTimeMillis();
-
- int rowsUpdateOrInserted = mDbHelper.updateOrInsertSelfKey(keyValue, deviceId, accountId,
- callerPackageName, timeUpdated);
-
- final Bundle response = new Bundle();
- response.putBoolean(ContactKeys.KEY_UPDATED_ROWS,
- rowsUpdateOrInserted > 0);
- return response;
- }
-
- /**
- * Updates a self key entry {@link ContactKeys.REMOTE_VERIFICATION_STATE}
- * given the deviceId, accountId and the inferred package name of the caller.
- *
- * @return Bundle with a {@link ContactKeys.KEY_UPDATED_ROWS} as a key and
- * a boolean value being true if the row was updated, false otherwise.
- */
- private Bundle updateSelfKeyRemoteVerificationState(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
-
- final String deviceId = extras.getString(ContactKeys.DEVICE_ID);
- final String accountId = extras.getString(ContactKeys.ACCOUNT_ID);
- final int remoteVerificationState =
- extras.getInt(ContactKeys.REMOTE_VERIFICATION_STATE);
- final long timeUpdated = System.currentTimeMillis();
- final String callerPackageName = getCallingPackage();
-
- int rowsUpdated;
- if (extras.containsKey(ContactKeys.OWNER_PACKAGE_NAME)) {
- final String ownerPackageName = extras.getString(ContactKeys.OWNER_PACKAGE_NAME);
- ContactKeysPermissions.enforceVisibility(getContext(),
- callerPackageName, ownerPackageName);
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(),
- UPDATE_VERIFICATION_STATE_PERMISSION);
- rowsUpdated = mDbHelper.updateSelfKeyRemoteVerificationState(ownerPackageName,
- deviceId, accountId, remoteVerificationState, timeUpdated);
- } else {
- rowsUpdated = mDbHelper.updateSelfKeyRemoteVerificationState(callerPackageName,
- deviceId, accountId, remoteVerificationState, timeUpdated);
- }
-
- final Bundle response = new Bundle();
- response.putBoolean(ContactKeys.KEY_UPDATED_ROWS, rowsUpdated > 0);
- return response;
- }
-
- /**
- * Retrieves a self key entry given the deviceId, accountId and the inferred package name
- * of the caller.
- *
- * @return Bundle with a {@link ContactKeys.KEY_CONTACT_KEY} as a key and a
- * parcelable {@link ContactKeysManager.ContactKey} as a value
- */
- private Bundle getSelfKey(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
- final String deviceId = extras.getString(ContactKeys.DEVICE_ID);
- final String accountId = extras.getString(ContactKeys.ACCOUNT_ID);
- String callerPackageName = getCallingPackage();
-
- ContactKeysManager.SelfKey selfKey = mDbHelper.getSelfKey(deviceId, accountId,
- callerPackageName);
-
- final Bundle response = new Bundle();
- response.putParcelable(ContactKeys.KEY_CONTACT_KEY, selfKey);
-
- return response;
- }
-
- /**
- * Retrieves all self key entries that belong to apps visible to the caller.
- *
- * @return Bundle with a {@link ContactKeys.KEY_CONTACT_KEYS} as a key and
- * a parcelable list of {@link ContactKeysManager.SelfKey} as a value
- */
- private Bundle getAllSelfKeys() {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
-
- final Bundle response = new Bundle();
-
- List<ContactKeysManager.SelfKey> selfKeys = mDbHelper.getAllSelfKeys();
-
- selfKeys = filterVisibleSelfKeys(selfKeys);
- selfKeys = getStrippedSelfKeys(selfKeys);
-
- response.putParcelableList(ContactKeys.KEY_CONTACT_KEYS, selfKeys);
-
- return response;
- }
-
- /**
- * Retrieves all self key entries that are owned by the caller.
- *
- * @return Bundle with a {@link ContactKeys.KEY_CONTACT_KEYS} as a key and
- * a parcelable list of {@link ContactKeysManager.ContactKey} as a value
- */
- private Bundle getOwnerSelfKeys() {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
-
- final Bundle response = new Bundle();
-
- String callerPackageName = getCallingPackage();
- List<ContactKeysManager.SelfKey> selfKeys =
- mDbHelper.getSelfKeysForOwnerPackageName(callerPackageName);
-
- response.putParcelableList(ContactKeys.KEY_CONTACT_KEYS, selfKeys);
-
- return response;
- }
-
- /**
- * Removes a self key entry {@link ContactKeys.REMOTE_VERIFICATION_STATE}
- * given the deviceId and the inferred package name of the caller.
- *
- * @return Bundle with a {@link ContactKeys.KEY_UPDATED_ROWS} as a key and a
- * boolean value being true if the row was removed, false otherwise.
- */
- private Bundle removeSelfKey(Bundle extras) {
- ContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
-
- final String deviceId = extras.getString(ContactKeys.DEVICE_ID);
- final String accountId = extras.getString(ContactKeys.ACCOUNT_ID);
- String callerPackageName = getCallingPackage();
-
- int rowsRemoved = mDbHelper.removeSelfKey(deviceId, accountId, callerPackageName);
-
- final Bundle response = new Bundle();
-
- response.putBoolean(ContactKeys.KEY_UPDATED_ROWS, rowsRemoved > 0);
-
- return response;
- }
-
- /**
- * Retrieves contact basic info - given the lookupKey of the contact, returns display name,
- * phone number and email address.
- *
- * @return Bundle with a {@link ContactKeys.DISPLAY_NAME},
- * {@link ContactKeys.PHONE_NUMBER}
- * and {@link ContactKeys.EMAIL_ADDRESS} as keys and their corresponding
- * values.
- */
- private Bundle getContactBasicInfoFromCP2(String lookupKey) {
- Bundle bundle = new Bundle();
- final long identity = Binder.clearCallingIdentity();
- try {
- Bundle nameAndNumberBundle = getDisplayNameAndNumber(lookupKey);
- bundle.putString(ContactKeys.DISPLAY_NAME,
- nameAndNumberBundle.getString(ContactKeys.DISPLAY_NAME));
- bundle.putString(ContactKeys.PHONE_NUMBER,
- nameAndNumberBundle.getString(ContactKeys.PHONE_NUMBER));
- bundle.putString(ContactKeys.EMAIL_ADDRESS, getEmail(lookupKey));
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- return bundle;
- }
-
- /**
- * Returns display name and phone number given the lookupKey of the contact.
- *
- * @return Bundle with a {@link ContactKeys.DISPLAY_NAME}
- * and {@link ContactKeys.PHONE_NUMBER} as keys and their corresponding values.
- */
- private Bundle getDisplayNameAndNumber(String lookupKey) {
- Bundle bundle = new Bundle();
- Cursor c = getContext().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
- new String[] {ContactsContract.Data.DISPLAY_NAME,
- ContactsContract.CommonDataKinds.Phone.NUMBER},
- ContactsContract.Data.LOOKUP_KEY + " = ?",
- new String[] { lookupKey }, null);
- if (c.moveToFirst()) {
- bundle.putString(ContactKeys.DISPLAY_NAME,
- c.getString(c.getColumnIndexOrThrow(ContactsContract.Data.DISPLAY_NAME)));
- bundle.putString(ContactKeys.PHONE_NUMBER,
- c.getString(c.getColumnIndexOrThrow(
- ContactsContract.CommonDataKinds.Phone.NUMBER)));
- }
- c.close();
- return bundle;
- }
-
- /**
- * Returns email address given the lookupKey of the contact.
- *
- * @return Bundle with a {@link ContactKeys.EMAIL_ADDRESS} as key and an
- * email address as a value.
- */
- private String getEmail(String lookupKey) {
- String email = null;
- Cursor c = getContext().getContentResolver().query(
- ContactsContract.CommonDataKinds.Email.CONTENT_URI,
- new String[] { ContactsContract.CommonDataKinds.Email.ADDRESS },
- ContactsContract.Data.LOOKUP_KEY + " = ?",
- new String[] { lookupKey }, null);
- if (c.moveToFirst()) {
- email = c.getString(c.getColumnIndexOrThrow(
- ContactsContract.CommonDataKinds.Email.ADDRESS));
- }
- c.close();
-
- return email;
- }
-
- /**
- * Returns contact keys owned by the packages that are visible to the caller.
- * This is verified by checking that the caller package can query the package owning the key.
- */
- private List<ContactKeysManager.ContactKey> filterVisibleContactKeys(
- List<ContactKeysManager.ContactKey> contactKeys) {
- List<ContactKeysManager.ContactKey> visibleContactKeys =
- new ArrayList<>(contactKeys.size());
- PackageManager packageManager = getContext().getPackageManager();
- String callingPackageName = getCallingPackage();
- for (ContactKeysManager.ContactKey contactKey : contactKeys) {
- try {
- String targetPackageName = contactKey.getOwnerPackageName();
- if (packageManager.canPackageQuery(callingPackageName, targetPackageName)) {
- visibleContactKeys.add(contactKey);
- }
- } catch (PackageManager.NameNotFoundException e) {
- // The caller doesn't have visibility of the owner package
- }
- }
- return visibleContactKeys;
- }
-
- /**
- * Removes deviceId, timeUpdated, and key value data from contact keys.
- */
- private static List<ContactKeysManager.ContactKey> getStrippedContactKeys(
- List<ContactKeysManager.ContactKey> visibleContactKeys) {
- List<ContactKeysManager.ContactKey> strippedContactKeys = new ArrayList<>(
- visibleContactKeys.size());
- for (ContactKeysManager.ContactKey key : visibleContactKeys) {
- ContactKeysManager.ContactKey strippedContactKey =
- new ContactKeysManager.ContactKey(null, key.getAccountId(),
- key.getOwnerPackageName(), STRIPPED_TIME_UPDATED, null,
- key.getLocalVerificationState(), key.getRemoteVerificationState(),
- key.getDisplayName(), key.getPhoneNumber(), key.getEmailAddress());
- strippedContactKeys.add(strippedContactKey);
- }
- return strippedContactKeys;
- }
-
- /**
- * Returns self keys owned by the packages that are visible to the caller.
- * This is verified by checking that the caller package can query the package owning the key.
- */
- private List<ContactKeysManager.SelfKey> filterVisibleSelfKeys(
- List<ContactKeysManager.SelfKey> selfKeys) {
- List<ContactKeysManager.SelfKey> visibleSelfKeys =
- new ArrayList<>(selfKeys.size());
- PackageManager packageManager = getContext().getPackageManager();
- String callingPackageName = getCallingPackage();
- for (ContactKeysManager.SelfKey selfKey : selfKeys) {
- try {
- String targetPackageName = selfKey.getOwnerPackageName();
- if (packageManager.canPackageQuery(callingPackageName, targetPackageName)) {
- visibleSelfKeys.add(selfKey);
- }
- } catch (PackageManager.NameNotFoundException e) {
- // The caller doesn't have visibility of the owner package
- }
- }
- return visibleSelfKeys;
- }
-
-
- /**
- * Removes deviceId, timeUpdated, and key value data from self keys.
- */
- private static List<ContactKeysManager.SelfKey> getStrippedSelfKeys(
- List<ContactKeysManager.SelfKey> visibleSelfKeys) {
- List<ContactKeysManager.SelfKey> strippedSelfKeys = new ArrayList<>(
- visibleSelfKeys.size());
- for (ContactKeysManager.SelfKey key : visibleSelfKeys) {
- ContactKeysManager.SelfKey strippedContactKey =
- new ContactKeysManager.SelfKey(null, key.getAccountId(),
- key.getOwnerPackageName(), STRIPPED_TIME_UPDATED, null,
- key.getRemoteVerificationState());
- strippedSelfKeys.add(strippedContactKey);
- }
- return strippedSelfKeys;
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- // Not implemented
- return null;
- }
-
- @Override
- public String getType(Uri uri) {
- // Not implemented
- return null;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues initialValues) {
- // Not implemented
- return null;
- }
-
- @Override
- public int delete(Uri uri, String where, String[] whereArgs) {
- // Not implemented
- return 0;
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
- // Not implemented
- return 0;
- }
-}
\ No newline at end of file
diff --git a/src/com/android/providers/contactkeys/E2eeContactKeysDatabaseHelper.java b/src/com/android/providers/contactkeys/E2eeContactKeysDatabaseHelper.java
new file mode 100644
index 0000000..1da9ae6
--- /dev/null
+++ b/src/com/android/providers/contactkeys/E2eeContactKeysDatabaseHelper.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.contactkeys;
+
+import android.annotation.FlaggedApi;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteStatement;
+import android.provider.E2eeContactKeysManager;
+import android.provider.E2eeContactKeysManager.E2eeContactKeys;
+import android.provider.Flags;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Database helper for end-to-end encryption contact keys.
+ */
+@FlaggedApi(Flags.FLAG_USER_KEYS)
+public class E2eeContactKeysDatabaseHelper extends SQLiteOpenHelper {
+
+ private static final String TAG = "E2eeContactKeysDatabaseHelper";
+
+ private static final String CONTACT_KEYS_TABLE_NAME = "contactkeys";
+ private static final String SELF_KEYS_TABLE_NAME = "selfkeys";
+ private static final String DATABASE_NAME = "contact_keys_provider.db";
+ private static final int DATABASE_VERSION = 1;
+
+ E2eeContactKeysDatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ Log.i(TAG, "Bootstrapping database " + DATABASE_NAME + " version: " + DATABASE_VERSION);
+ db.execSQL("CREATE TABLE " + CONTACT_KEYS_TABLE_NAME + " ("
+ + E2eeContactKeys.LOOKUP_KEY + " TEXT NOT NULL, "
+ + E2eeContactKeys.DEVICE_ID + " TEXT NOT NULL, "
+ + E2eeContactKeys.ACCOUNT_ID + " TEXT NOT NULL, "
+ + E2eeContactKeys.OWNER_PACKAGE_NAME + " TEXT NOT NULL, "
+ + E2eeContactKeys.TIME_UPDATED + " INTEGER NOT NULL default 0, "
+ + E2eeContactKeys.KEY_VALUE + " BLOB NOT NULL, "
+ + E2eeContactKeys.DISPLAY_NAME + " TEXT, "
+ + E2eeContactKeys.PHONE_NUMBER + " TEXT, "
+ + E2eeContactKeys.EMAIL_ADDRESS + " TEXT, "
+ + E2eeContactKeys.LOCAL_VERIFICATION_STATE + " INTEGER NOT NULL default 0, "
+ + E2eeContactKeys.REMOTE_VERIFICATION_STATE + " INTEGER NOT NULL default 0, "
+ + " PRIMARY KEY ("
+ + E2eeContactKeys.LOOKUP_KEY + ", "
+ + E2eeContactKeys.DEVICE_ID + ", "
+ + E2eeContactKeys.ACCOUNT_ID + ", "
+ + E2eeContactKeys.OWNER_PACKAGE_NAME
+ + "));");
+ db.execSQL("CREATE TABLE " + SELF_KEYS_TABLE_NAME + " ("
+ + E2eeContactKeys.DEVICE_ID + " TEXT NOT NULL, "
+ + E2eeContactKeys.ACCOUNT_ID + " TEXT NOT NULL, "
+ + E2eeContactKeys.OWNER_PACKAGE_NAME + " TEXT NOT NULL, "
+ + E2eeContactKeys.TIME_UPDATED + " INTEGER NOT NULL default 0, "
+ + E2eeContactKeys.KEY_VALUE + " BLOB NOT NULL, "
+ + E2eeContactKeys.REMOTE_VERIFICATION_STATE + " INTEGER NOT NULL default 0,"
+ + " PRIMARY KEY ("
+ + E2eeContactKeys.DEVICE_ID + ", "
+ + E2eeContactKeys.ACCOUNT_ID + ", "
+ + E2eeContactKeys.OWNER_PACKAGE_NAME
+ + "));");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ // Nothing to do here, still on version 1
+ }
+
+ /**
+ * Gets all end-to-end encryption contact keys in the contact keys table for a given lookupKey.
+ */
+ public List<E2eeContactKeysManager.E2eeContactKey> getAllContactKeys(String lookupKey) {
+ try (Cursor c = getReadableDatabase().rawQuery(
+ "SELECT DISTINCT " + E2eeContactKeys.DEVICE_ID + ","
+ + E2eeContactKeys.ACCOUNT_ID + ","
+ + E2eeContactKeys.OWNER_PACKAGE_NAME + ","
+ + E2eeContactKeys.TIME_UPDATED + ","
+ + E2eeContactKeys.KEY_VALUE + ","
+ + E2eeContactKeys.DISPLAY_NAME + ","
+ + E2eeContactKeys.PHONE_NUMBER + ","
+ + E2eeContactKeys.EMAIL_ADDRESS + ","
+ + E2eeContactKeys.LOCAL_VERIFICATION_STATE + ","
+ + E2eeContactKeys.REMOTE_VERIFICATION_STATE
+ + " FROM " + CONTACT_KEYS_TABLE_NAME
+ + " WHERE " + E2eeContactKeys.LOOKUP_KEY + " = ?",
+ new String[] {lookupKey})) {
+ final List<E2eeContactKeysManager.E2eeContactKey> result =
+ new ArrayList<>(c.getCount());
+ while (c.moveToNext()) {
+ String deviceId = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.DEVICE_ID));
+ String accountId = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.ACCOUNT_ID));
+ String ownerPackageName = c.getString(
+ c.getColumnIndexOrThrow(E2eeContactKeys.OWNER_PACKAGE_NAME));
+ long timeUpdated = c.getLong(c.getColumnIndexOrThrow(E2eeContactKeys.TIME_UPDATED));
+ byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(E2eeContactKeys.KEY_VALUE));
+ String displayName = c.getString(c.getColumnIndexOrThrow(
+ E2eeContactKeys.DISPLAY_NAME));
+ String number = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.PHONE_NUMBER));
+ String emailAddress = c.getString(c.getColumnIndexOrThrow(
+ E2eeContactKeys.EMAIL_ADDRESS));
+ int localVerificationState = c.getInt(c.getColumnIndexOrThrow(
+ E2eeContactKeys.LOCAL_VERIFICATION_STATE));
+ int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
+ E2eeContactKeys.REMOTE_VERIFICATION_STATE));
+ result.add(new E2eeContactKeysManager.E2eeContactKey(deviceId, accountId,
+ ownerPackageName, timeUpdated, keyValue, localVerificationState,
+ remoteVerificationState, displayName, number, emailAddress));
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Gets all end-to-end encryption contact keys in the contact keys table for a given lookupKey
+ * and ownerPackageName.
+ */
+ public List<E2eeContactKeysManager.E2eeContactKey> getContactKeysForOwnerPackageName(
+ String lookupKey, String ownerPackageName) {
+ try (Cursor c = getReadableDatabase().rawQuery(
+ "SELECT DISTINCT " + E2eeContactKeys.DEVICE_ID + ","
+ + E2eeContactKeys.ACCOUNT_ID + ","
+ + E2eeContactKeys.TIME_UPDATED + ","
+ + E2eeContactKeys.KEY_VALUE + ","
+ + E2eeContactKeys.DISPLAY_NAME + ","
+ + E2eeContactKeys.PHONE_NUMBER + ","
+ + E2eeContactKeys.EMAIL_ADDRESS + ","
+ + E2eeContactKeys.LOCAL_VERIFICATION_STATE + ","
+ + E2eeContactKeys.REMOTE_VERIFICATION_STATE
+ + " FROM " + CONTACT_KEYS_TABLE_NAME
+ + " WHERE " + E2eeContactKeys.LOOKUP_KEY + " = ?"
+ + " AND " + E2eeContactKeys.OWNER_PACKAGE_NAME + " = ?",
+ new String[] {lookupKey, String.valueOf(ownerPackageName)})) {
+ final List<E2eeContactKeysManager.E2eeContactKey> result =
+ new ArrayList<>(c.getCount());
+ while (c.moveToNext()) {
+ String deviceId = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.DEVICE_ID));
+ String accountId = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.ACCOUNT_ID));
+ long timeUpdated = c.getLong(c.getColumnIndexOrThrow(E2eeContactKeys.TIME_UPDATED));
+ byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(E2eeContactKeys.KEY_VALUE));
+ String displayName = c.getString(c.getColumnIndexOrThrow(
+ E2eeContactKeys.DISPLAY_NAME));
+ String number = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.PHONE_NUMBER));
+ String emailAddress = c.getString(c.getColumnIndexOrThrow(
+ E2eeContactKeys.EMAIL_ADDRESS));
+ int localVerificationState = c.getInt(c.getColumnIndexOrThrow(
+ E2eeContactKeys.LOCAL_VERIFICATION_STATE));
+ int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
+ E2eeContactKeys.REMOTE_VERIFICATION_STATE));
+ result.add(new E2eeContactKeysManager.E2eeContactKey(deviceId, accountId,
+ ownerPackageName, timeUpdated, keyValue, localVerificationState,
+ remoteVerificationState, displayName, number, emailAddress));
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Get a end-to-end encryption contact key for given parameters.
+ */
+ public E2eeContactKeysManager.E2eeContactKey getContactKey(String lookupKey,
+ String ownerPackageName, String deviceId, String accountId) {
+ E2eeContactKeysManager.E2eeContactKey result = null;
+ try (Cursor c = getReadableDatabase().rawQuery(
+ "SELECT " + E2eeContactKeys.KEY_VALUE + ","
+ + E2eeContactKeys.TIME_UPDATED + ","
+ + E2eeContactKeys.DISPLAY_NAME + ","
+ + E2eeContactKeys.PHONE_NUMBER + ","
+ + E2eeContactKeys.EMAIL_ADDRESS + ","
+ + E2eeContactKeys.LOCAL_VERIFICATION_STATE + ","
+ + E2eeContactKeys.REMOTE_VERIFICATION_STATE + " FROM "
+ + CONTACT_KEYS_TABLE_NAME
+ + " WHERE " + E2eeContactKeys.LOOKUP_KEY + " = ?"
+ + " AND " + E2eeContactKeys.OWNER_PACKAGE_NAME + " = ?"
+ + " AND " + E2eeContactKeys.DEVICE_ID + " = ?"
+ + " AND " + E2eeContactKeys.ACCOUNT_ID + " = ?",
+ new String[] {lookupKey, String.valueOf(ownerPackageName), deviceId, accountId})) {
+ if (c.moveToNext()) {
+ byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(E2eeContactKeys.KEY_VALUE));
+ long timeUpdated = c.getLong(c.getColumnIndexOrThrow(E2eeContactKeys.TIME_UPDATED));
+ String displayName = c.getString(c.getColumnIndexOrThrow(
+ E2eeContactKeys.DISPLAY_NAME));
+ String number = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.PHONE_NUMBER));
+ String emailAddress = c.getString(c.getColumnIndexOrThrow(
+ E2eeContactKeys.EMAIL_ADDRESS));
+ int localVerificationState = c.getInt(c.getColumnIndexOrThrow(
+ E2eeContactKeys.LOCAL_VERIFICATION_STATE));
+ int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
+ E2eeContactKeys.REMOTE_VERIFICATION_STATE));
+ result = new E2eeContactKeysManager.E2eeContactKey(deviceId, accountId,
+ ownerPackageName, timeUpdated, keyValue, localVerificationState,
+ remoteVerificationState, displayName, number, emailAddress);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Updates the end-to-end encryption contact key local verification state and returns the
+ * number of keys updated (should always be 0 or 1).
+ */
+ public int updateContactKeyLocalVerificationState(String lookupKey, String ownerPackageName,
+ String deviceId, String accountId, int localVerificationState, long timeUpdated) {
+ try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
+ "UPDATE " + CONTACT_KEYS_TABLE_NAME
+ + " SET " + E2eeContactKeys.LOCAL_VERIFICATION_STATE
+ + " = ?, "
+ + E2eeContactKeys.TIME_UPDATED + " = ?"
+ + " WHERE " + E2eeContactKeys.LOOKUP_KEY + " = ?"
+ + " AND " + E2eeContactKeys.OWNER_PACKAGE_NAME + " = ?"
+ + " AND " + E2eeContactKeys.DEVICE_ID + " = ?"
+ + " AND " + E2eeContactKeys.ACCOUNT_ID + " = ?")) {
+ updateStatement.bindLong(1, localVerificationState);
+ updateStatement.bindLong(2, timeUpdated);
+ updateStatement.bindString(3, lookupKey);
+ updateStatement.bindString(4, ownerPackageName);
+ updateStatement.bindString(5, deviceId);
+ updateStatement.bindString(6, accountId);
+ return updateStatement.executeUpdateDelete();
+ }
+ }
+
+ /**
+ * Updates the end-to-end encryption contact key remote verification state and returns the
+ * number of keys updated (should always be 0 or 1).
+ */
+ public int updateContactKeyRemoteVerificationState(String lookupKey, String ownerPackageName,
+ String deviceId, String accountId, int remoteVerificationState, long timeUpdated) {
+ try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
+ "UPDATE " + CONTACT_KEYS_TABLE_NAME
+ + " SET " + E2eeContactKeys.REMOTE_VERIFICATION_STATE
+ + " = ?, "
+ + E2eeContactKeys.TIME_UPDATED + " = ?"
+ + " WHERE " + E2eeContactKeys.LOOKUP_KEY + " = ?"
+ + " AND " + E2eeContactKeys.OWNER_PACKAGE_NAME + " = ?"
+ + " AND " + E2eeContactKeys.DEVICE_ID + " = ?"
+ + " AND " + E2eeContactKeys.ACCOUNT_ID + " = ?")) {
+ updateStatement.bindLong(1, remoteVerificationState);
+ updateStatement.bindLong(2, timeUpdated);
+ updateStatement.bindString(3, lookupKey);
+ updateStatement.bindString(4, ownerPackageName);
+ updateStatement.bindString(5, deviceId);
+ updateStatement.bindString(6, accountId);
+ return updateStatement.executeUpdateDelete();
+ }
+ }
+
+ /**
+ * Inserts a new end-to-end encryption contact key or updates an existing one and returns the
+ * number of keys inserted/updated (should always be 0 or 1).
+ */
+ public int updateOrInsertContactKey(String lookupKey, byte[] keyValue, String deviceId,
+ String accountId, String ownerPackageName, long timeUpdated,
+ String displayName, String number, String emailAddress) {
+ try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
+ "INSERT INTO " + CONTACT_KEYS_TABLE_NAME + " ("
+ + E2eeContactKeys.LOOKUP_KEY + ", "
+ + E2eeContactKeys.DEVICE_ID + ", "
+ + E2eeContactKeys.ACCOUNT_ID + ", "
+ + E2eeContactKeys.OWNER_PACKAGE_NAME + ", "
+ + E2eeContactKeys.KEY_VALUE + ", "
+ + E2eeContactKeys.TIME_UPDATED + ", "
+ + E2eeContactKeys.DISPLAY_NAME + ", "
+ + E2eeContactKeys.PHONE_NUMBER + ", "
+ + E2eeContactKeys.EMAIL_ADDRESS
+ + ") VALUES "
+ + "(?, ?, ?, ?, ?, ?, ?, ?, ?) "
+ + "ON CONFLICT ("
+ + E2eeContactKeys.LOOKUP_KEY + ", "
+ + E2eeContactKeys.DEVICE_ID + ", "
+ + E2eeContactKeys.ACCOUNT_ID + ", "
+ + E2eeContactKeys.OWNER_PACKAGE_NAME + ") "
+ + "DO UPDATE SET " + E2eeContactKeys.KEY_VALUE + " = ?, "
+ + E2eeContactKeys.TIME_UPDATED + " = ?, "
+ + E2eeContactKeys.DISPLAY_NAME + " = ?, "
+ + E2eeContactKeys.PHONE_NUMBER + " = ?, "
+ + E2eeContactKeys.EMAIL_ADDRESS + " = ?")) {
+ updateStatement.bindString(1, lookupKey);
+ updateStatement.bindString(2, deviceId);
+ updateStatement.bindString(3, accountId);
+ updateStatement.bindString(4, ownerPackageName);
+ updateStatement.bindBlob(5, keyValue);
+ updateStatement.bindLong(6, timeUpdated);
+ if (displayName != null) {
+ updateStatement.bindString(7, displayName);
+ } else {
+ updateStatement.bindNull(7);
+ }
+ if (number != null) {
+ updateStatement.bindString(8, number);
+ } else {
+ updateStatement.bindNull(8);
+ }
+ if (emailAddress != null) {
+ updateStatement.bindString(9, emailAddress);
+ } else {
+ updateStatement.bindNull(9);
+ }
+ updateStatement.bindBlob(10, keyValue);
+ updateStatement.bindLong(11, timeUpdated);
+ if (displayName != null) {
+ updateStatement.bindString(12, displayName);
+ } else {
+ updateStatement.bindNull(12);
+ }
+ if (number != null) {
+ updateStatement.bindString(13, number);
+ } else {
+ updateStatement.bindNull(13);
+ }
+ if (emailAddress != null) {
+ updateStatement.bindString(14, emailAddress);
+ } else {
+ updateStatement.bindNull(14);
+ }
+ return updateStatement.executeUpdateDelete();
+ }
+ }
+
+ /**
+ * Removes the end-to-end encryption contact key and returns the number of keys removed
+ * (should always be 0 or 1).
+ */
+ public int removeContactKey(String lookupKey, String deviceId, String accountId,
+ String ownerPackageName) {
+ try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
+ "DELETE FROM " + CONTACT_KEYS_TABLE_NAME
+ + " WHERE " + E2eeContactKeys.LOOKUP_KEY + " = ?"
+ + " AND " + E2eeContactKeys.DEVICE_ID + " = ?"
+ + " AND " + E2eeContactKeys.ACCOUNT_ID + " = ?"
+ + " AND " + E2eeContactKeys.OWNER_PACKAGE_NAME + " = ?")) {
+ updateStatement.bindString(1, lookupKey);
+ updateStatement.bindString(2, deviceId);
+ updateStatement.bindString(3, accountId);
+ updateStatement.bindString(4, ownerPackageName);
+ return updateStatement.executeUpdateDelete();
+ }
+ }
+
+ /**
+ * Gets an end-to-end encryption self key for given parameters.
+ */
+ public E2eeContactKeysManager.E2eeSelfKey getSelfKey(String deviceId, String accountId,
+ String ownerPackageName) {
+ E2eeContactKeysManager.E2eeSelfKey result = null;
+ try (Cursor c = getReadableDatabase().rawQuery(
+ "SELECT " + E2eeContactKeys.KEY_VALUE + ","
+ + E2eeContactKeys.TIME_UPDATED + ","
+ + E2eeContactKeys.REMOTE_VERIFICATION_STATE + " FROM "
+ + SELF_KEYS_TABLE_NAME
+ + " WHERE " + E2eeContactKeys.DEVICE_ID + " = ?"
+ + " AND " + E2eeContactKeys.ACCOUNT_ID + " = ?"
+ + " AND " + E2eeContactKeys.OWNER_PACKAGE_NAME + " = ?",
+ new String[] {deviceId, accountId, ownerPackageName})) {
+ if (c.moveToNext()) {
+ byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(E2eeContactKeys.KEY_VALUE));
+ long timeUpdated = c.getLong(c.getColumnIndexOrThrow(E2eeContactKeys.TIME_UPDATED));
+ int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
+ E2eeContactKeys.REMOTE_VERIFICATION_STATE));
+ result = new E2eeContactKeysManager.E2eeSelfKey(deviceId, accountId,
+ ownerPackageName, timeUpdated, keyValue, remoteVerificationState);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Gets all end-to-end encryption self keys in the self keys table.
+ */
+ public List<E2eeContactKeysManager.E2eeSelfKey> getAllSelfKeys() {
+ try (Cursor c = getReadableDatabase().rawQuery(
+ "SELECT DISTINCT " + E2eeContactKeys.DEVICE_ID + ","
+ + E2eeContactKeys.ACCOUNT_ID + ","
+ + E2eeContactKeys.OWNER_PACKAGE_NAME + ","
+ + E2eeContactKeys.TIME_UPDATED + ","
+ + E2eeContactKeys.KEY_VALUE + ","
+ + E2eeContactKeys.REMOTE_VERIFICATION_STATE
+ + " FROM " + SELF_KEYS_TABLE_NAME,
+ new String[] {})) {
+ final List<E2eeContactKeysManager.E2eeSelfKey> result = new ArrayList<>(c.getCount());
+ while (c.moveToNext()) {
+ String deviceId = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.DEVICE_ID));
+ String accountId = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.ACCOUNT_ID));
+ String ownerPackageName = c.getString(
+ c.getColumnIndexOrThrow(E2eeContactKeys.OWNER_PACKAGE_NAME));
+ long timeUpdated = c.getLong(c.getColumnIndexOrThrow(E2eeContactKeys.TIME_UPDATED));
+ byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(E2eeContactKeys.KEY_VALUE));
+ int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
+ E2eeContactKeys.REMOTE_VERIFICATION_STATE));
+ result.add(new E2eeContactKeysManager.E2eeSelfKey(deviceId, accountId,
+ ownerPackageName, timeUpdated, keyValue, remoteVerificationState));
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Gets all end-to-end encryption self keys in the self keys table for a given ownerPackageName.
+ */
+ public List<E2eeContactKeysManager.E2eeSelfKey> getSelfKeysForOwnerPackageName(
+ String ownerPackageName) {
+ try (Cursor c = getReadableDatabase().rawQuery(
+ "SELECT DISTINCT " + E2eeContactKeys.DEVICE_ID + ","
+ + E2eeContactKeys.ACCOUNT_ID + ","
+ + E2eeContactKeys.TIME_UPDATED + ","
+ + E2eeContactKeys.KEY_VALUE + ","
+ + E2eeContactKeys.REMOTE_VERIFICATION_STATE
+ + " FROM " + SELF_KEYS_TABLE_NAME
+ + " WHERE " + E2eeContactKeys.OWNER_PACKAGE_NAME + " = ?",
+ new String[] {ownerPackageName})) {
+ final List<E2eeContactKeysManager.E2eeSelfKey> result = new ArrayList<>(c.getCount());
+ while (c.moveToNext()) {
+ String deviceId = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.DEVICE_ID));
+ String accountId = c.getString(c.getColumnIndexOrThrow(E2eeContactKeys.ACCOUNT_ID));
+ long timeUpdated = c.getLong(c.getColumnIndexOrThrow(E2eeContactKeys.TIME_UPDATED));
+ byte[] keyValue = c.getBlob(c.getColumnIndexOrThrow(E2eeContactKeys.KEY_VALUE));
+ int remoteVerificationState = c.getInt(c.getColumnIndexOrThrow(
+ E2eeContactKeys.REMOTE_VERIFICATION_STATE));
+ result.add(new E2eeContactKeysManager.E2eeSelfKey(deviceId, accountId,
+ ownerPackageName, timeUpdated, keyValue, remoteVerificationState));
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Inserts a new end-to-end encryption self key or updates an existing one and returns the
+ * number of keys inserted/updated (should always be 0 or 1).
+ */
+ public int updateOrInsertSelfKey(byte[] keyValue, String deviceId, String accountId,
+ String ownerPackageName, long timeUpdated) {
+ try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
+ "INSERT INTO " + SELF_KEYS_TABLE_NAME + " ("
+ + E2eeContactKeys.DEVICE_ID + ", "
+ + E2eeContactKeys.ACCOUNT_ID + ", "
+ + E2eeContactKeys.OWNER_PACKAGE_NAME + ", "
+ + E2eeContactKeys.KEY_VALUE + ", "
+ + E2eeContactKeys.TIME_UPDATED
+ + ") VALUES "
+ + "(?, ?, ?, ?, ?) "
+ + "ON CONFLICT ("
+ + E2eeContactKeys.DEVICE_ID + ", "
+ + E2eeContactKeys.ACCOUNT_ID + ", "
+ + E2eeContactKeys.OWNER_PACKAGE_NAME + ") "
+ + "DO UPDATE SET " + E2eeContactKeys.KEY_VALUE + " = ?, "
+ + E2eeContactKeys.TIME_UPDATED + " = ?")) {
+ updateStatement.bindString(1, deviceId);
+ updateStatement.bindString(2, accountId);
+ updateStatement.bindString(3, ownerPackageName);
+ updateStatement.bindBlob(4, keyValue);
+ updateStatement.bindLong(5, timeUpdated);
+ updateStatement.bindBlob(6, keyValue);
+ updateStatement.bindLong(7, timeUpdated);
+ return updateStatement.executeUpdateDelete();
+ }
+ }
+
+ /**
+ * Updates the end-to-end encryption self key remote verification state and returns the number
+ * of keys updated (should always be 0 or 1).
+ */
+ public int updateSelfKeyRemoteVerificationState(String ownerPackageName, String deviceId,
+ String accountId, int remoteVerificationState, long timeUpdated) {
+ try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
+ "UPDATE " + SELF_KEYS_TABLE_NAME
+ + " SET " + E2eeContactKeys.REMOTE_VERIFICATION_STATE + " = ?, "
+ + E2eeContactKeys.TIME_UPDATED + " = ?"
+ + " WHERE " + E2eeContactKeys.OWNER_PACKAGE_NAME + " = ?"
+ + " AND " + E2eeContactKeys.DEVICE_ID + " = ?"
+ + " AND " + E2eeContactKeys.ACCOUNT_ID + " = ?")) {
+ updateStatement.bindLong(1, remoteVerificationState);
+ updateStatement.bindLong(2, timeUpdated);
+ updateStatement.bindString(3, ownerPackageName);
+ updateStatement.bindString(4, deviceId);
+ updateStatement.bindString(5, accountId);
+ return updateStatement.executeUpdateDelete();
+ }
+ }
+
+ /**
+ * Removes a end-to-end encryption self key with given parameters.
+ */
+ public int removeSelfKey(String deviceId, String accountId, String ownerPackageName) {
+ try (SQLiteStatement updateStatement = getWritableDatabase().compileStatement(
+ "DELETE FROM " + SELF_KEYS_TABLE_NAME
+ + " WHERE " + E2eeContactKeys.DEVICE_ID + " = ?"
+ + " AND " + E2eeContactKeys.ACCOUNT_ID + " = ?"
+ + " AND " + E2eeContactKeys.OWNER_PACKAGE_NAME + " = ?")) {
+ updateStatement.bindString(1, deviceId);
+ updateStatement.bindString(2, accountId);
+ updateStatement.bindString(3, ownerPackageName);
+ return updateStatement.executeUpdateDelete();
+ }
+ }
+}
diff --git a/src/com/android/providers/contactkeys/E2eeContactKeysProvider.java b/src/com/android/providers/contactkeys/E2eeContactKeysProvider.java
new file mode 100644
index 0000000..a9bb85e
--- /dev/null
+++ b/src/com/android/providers/contactkeys/E2eeContactKeysProvider.java
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.contactkeys;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.provider.E2eeContactKeysManager;
+import android.provider.E2eeContactKeysManager.E2eeContactKeys;
+import android.provider.ContactsContract;
+import android.provider.Flags;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.providers.contactkeys.util.E2eeContactKeysPermissions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides access to a database of end-to-end encryption contact keys.
+ */
+@FlaggedApi(Flags.FLAG_USER_KEYS)
+public class E2eeContactKeysProvider extends ContentProvider {
+
+ /** The authority for the end-to-end encryption contact keys provider. */
+ public static final String AUTHORITY = "com.android.contactkeys.contactkeysprovider";
+
+ private static final String READ_PERMISSION = "android.permission.READ_CONTACTS";
+ private static final String WRITE_PERMISSION = "android.permission.WRITE_CONTACTS";
+ private static final String UPDATE_VERIFICATION_STATE_PERMISSION =
+ "android.permission.WRITE_VERIFICATION_STATE_E2EE_CONTACT_KEYS";
+
+ /** Special timeUpdated value used when this data is stripped. */
+ private static final long STRIPPED_TIME_UPDATED = -1;
+
+ @VisibleForTesting
+ E2eeContactKeysDatabaseHelper mDbHelper;
+
+ @Override
+ public boolean onCreate() {
+ mDbHelper = new E2eeContactKeysDatabaseHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public Bundle call(@NonNull String method, String arg, Bundle extras) {
+ switch (method) {
+ case E2eeContactKeys.UPDATE_OR_INSERT_CONTACT_KEY_METHOD -> {
+ return updateOrInsertE2eeContactKey(extras);
+ }
+ case E2eeContactKeys.GET_CONTACT_KEY_METHOD -> {
+ return getE2eeContactKey(extras);
+ }
+ case E2eeContactKeys.GET_ALL_CONTACT_KEYS_METHOD -> {
+ return getAllE2eeContactKeys(extras);
+ }
+ case E2eeContactKeys.GET_OWNER_CONTACT_KEYS_METHOD -> {
+ return getOwnerE2eeContactKeys(extras);
+ }
+ case E2eeContactKeys.UPDATE_CONTACT_KEY_LOCAL_VERIFICATION_STATE_METHOD -> {
+ return updateE2eeContactKeyLocalVerificationState(extras);
+ }
+ case E2eeContactKeys.UPDATE_CONTACT_KEY_REMOTE_VERIFICATION_STATE_METHOD -> {
+ return updateE2eeContactKeyRemoteVerificationState(extras);
+ }
+ case E2eeContactKeys.REMOVE_CONTACT_KEY_METHOD -> {
+ return removeE2eeContactKey(extras);
+ }
+ case E2eeContactKeys.UPDATE_OR_INSERT_SELF_KEY_METHOD -> {
+ return updateOrInsertE2eeSelfKey(extras);
+ }
+ case E2eeContactKeys.UPDATE_SELF_KEY_REMOTE_VERIFICATION_STATE_METHOD -> {
+ return updateE2eeSelfKeyRemoteVerificationState(extras);
+ }
+ case E2eeContactKeys.GET_SELF_KEY_METHOD -> {
+ return getE2eeSelfKey(extras);
+ }
+ case E2eeContactKeys.GET_ALL_SELF_KEYS_METHOD -> {
+ return getAllE2eeSelfKeys();
+ }
+ case E2eeContactKeys.GET_OWNER_SELF_KEYS_METHOD -> {
+ return getOwnerE2eeSelfKeys();
+ }
+ case E2eeContactKeys.REMOVE_SELF_KEY_METHOD -> {
+ return removeE2eeSelfKey(extras);
+ }
+ }
+ throw new IllegalArgumentException("Unexpected method " + method);
+ }
+
+ /**
+ * Inserts a new entry into the end-to-end encryption contact keys table or updates one if it
+ * already exists.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_UPDATED_ROWS} as a key and a
+ * boolean value being true if the row was added or updated, false otherwise.
+ */
+ private Bundle updateOrInsertE2eeContactKey(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
+
+ final Bundle response = new Bundle();
+
+ final String lookupKey = extras.getString(E2eeContactKeys.LOOKUP_KEY);
+ final String deviceId = extras.getString(E2eeContactKeys.DEVICE_ID);
+ final String accountId = extras.getString(E2eeContactKeys.ACCOUNT_ID);
+ final byte[] keyValue = extras.getByteArray(E2eeContactKeys.KEY_VALUE);
+
+ Bundle contactInfo = getContactBasicInfoFromCP2(lookupKey);
+ String displayName = contactInfo.getString(E2eeContactKeys.DISPLAY_NAME);
+ String number = contactInfo.getString(E2eeContactKeys.PHONE_NUMBER);
+ String emailAddress = contactInfo.getString(E2eeContactKeys.EMAIL_ADDRESS);
+
+ String callerPackageName = getCallingPackage();
+ long timeUpdated = System.currentTimeMillis();
+
+ int rowsUpdateOrInserted = mDbHelper.updateOrInsertContactKey(lookupKey, keyValue,
+ deviceId, accountId, callerPackageName, timeUpdated, displayName, number,
+ emailAddress);
+
+ response.putBoolean(E2eeContactKeys.KEY_UPDATED_ROWS, rowsUpdateOrInserted > 0);
+
+ return response;
+ }
+
+ /**
+ * Retrieves an end-to-end encryption contact key entry given the lookupKey, deviceId and the
+ * inferred package name of the caller.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_CONTACT_KEY} as a key and a
+ * parcelable {@link E2eeContactKeysManager.E2eeContactKey} as a value
+ */
+ private Bundle getE2eeContactKey(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
+
+ final String lookupKey = extras.getString(E2eeContactKeys.LOOKUP_KEY);
+ final String deviceId = extras.getString(E2eeContactKeys.DEVICE_ID);
+ final String accountId = extras.getString(E2eeContactKeys.ACCOUNT_ID);
+ String callerPackageName = getCallingPackage();
+
+ E2eeContactKeysManager.E2eeContactKey contactKey = mDbHelper.getContactKey(lookupKey,
+ callerPackageName, deviceId, accountId);
+
+ final Bundle response = new Bundle();
+ response.putParcelable(E2eeContactKeys.KEY_CONTACT_KEY, contactKey);
+
+ return response;
+ }
+
+ /**
+ * Retrieves all end-to-end encryption contact key entries given the lookupKey. All keys that
+ * belong to apps visible to the caller will be returned.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_CONTACT_KEYS} as a key and
+ * a parcelable list of {@link E2eeContactKeysManager.E2eeContactKey} as a value
+ */
+ private Bundle getAllE2eeContactKeys(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
+ String lookupKey = extras.getString(E2eeContactKeys.LOOKUP_KEY);
+
+ final Bundle response = new Bundle();
+
+ List<E2eeContactKeysManager.E2eeContactKey> contactKeys =
+ mDbHelper.getAllContactKeys(lookupKey);
+
+ contactKeys = filterVisibleContactKeys(contactKeys);
+ contactKeys = getStrippedContactKeys(contactKeys);
+
+ response.putParcelableList(E2eeContactKeys.KEY_CONTACT_KEYS, contactKeys);
+
+ return response;
+ }
+
+ /**
+ * Retrieves all end-to-end encryption contact key entries given the lookupKey. All keys that
+ * belong to the caller will be returned.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_CONTACT_KEYS} as a key and
+ * a parcelable list of {@link E2eeContactKeysManager.E2eeContactKey} as a value
+ */
+ private Bundle getOwnerE2eeContactKeys(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
+ String lookupKey = extras.getString(E2eeContactKeys.LOOKUP_KEY);
+
+ final Bundle response = new Bundle();
+
+ String callerPackageName = getCallingPackage();
+ List<E2eeContactKeysManager.E2eeContactKey> contactKeys =
+ mDbHelper.getContactKeysForOwnerPackageName(lookupKey, callerPackageName);
+
+ response.putParcelableList(E2eeContactKeys.KEY_CONTACT_KEYS, contactKeys);
+
+ return response;
+ }
+
+ /**
+ * Updates an end-to-end encryption contact key entry
+ * {@link E2eeContactKeys.LOCAL_VERIFICATION_STATE} given the lookupKey, deviceId, accountId
+ * and the inferred package name of the caller.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_UPDATED_ROWS} as a key and
+ * a boolean value being true if the row was updated, false otherwise.
+ */
+ private Bundle updateE2eeContactKeyLocalVerificationState(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
+
+ final String lookupKey = extras.getString(E2eeContactKeys.LOOKUP_KEY);
+ final String deviceId = extras.getString(E2eeContactKeys.DEVICE_ID);
+ final String accountId = extras.getString(E2eeContactKeys.ACCOUNT_ID);
+ final int localVerificationState =
+ extras.getInt(E2eeContactKeys.LOCAL_VERIFICATION_STATE);
+ final long timeUpdated = System.currentTimeMillis();
+ final String callerPackageName = getCallingPackage();
+
+ int rowsUpdated;
+ if (extras.containsKey(E2eeContactKeys.OWNER_PACKAGE_NAME)) {
+ final String ownerPackageName = extras.getString(E2eeContactKeys.OWNER_PACKAGE_NAME);
+ E2eeContactKeysPermissions.enforceVisibility(getContext(),
+ callerPackageName, ownerPackageName);
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(),
+ UPDATE_VERIFICATION_STATE_PERMISSION);
+ rowsUpdated = mDbHelper.updateContactKeyLocalVerificationState(lookupKey,
+ ownerPackageName, deviceId, accountId, localVerificationState, timeUpdated);
+ } else {
+ rowsUpdated = mDbHelper.updateContactKeyLocalVerificationState(lookupKey,
+ callerPackageName, deviceId, accountId, localVerificationState, timeUpdated);
+ }
+
+ final Bundle response = new Bundle();
+ response.putBoolean(E2eeContactKeys.KEY_UPDATED_ROWS, rowsUpdated > 0);
+ return response;
+ }
+
+ /**
+ * Updates an end-to-end encryption contact key entry
+ * {@link E2eeContactKeys.REMOTE_VERIFICATION_STATE} given the lookupKey, deviceId, accountId
+ * and the inferred package name of the caller.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_UPDATED_ROWS} as a key and
+ * a boolean value being true if the row was updated, false otherwise.
+ */
+ private Bundle updateE2eeContactKeyRemoteVerificationState(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
+
+ final String lookupKey = extras.getString(E2eeContactKeys.LOOKUP_KEY);
+ final String deviceId = extras.getString(E2eeContactKeys.DEVICE_ID);
+ final String accountId = extras.getString(E2eeContactKeys.ACCOUNT_ID);
+ final int remoteVerificationState =
+ extras.getInt(E2eeContactKeys.REMOTE_VERIFICATION_STATE);
+ final long timeUpdated = System.currentTimeMillis();
+ final String callerPackageName = getCallingPackage();
+
+ int rowsUpdated;
+ if (extras.containsKey(E2eeContactKeys.OWNER_PACKAGE_NAME)) {
+ final String ownerPackageName = extras.getString(E2eeContactKeys.OWNER_PACKAGE_NAME);
+ E2eeContactKeysPermissions.enforceVisibility(getContext(),
+ callerPackageName, ownerPackageName);
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(),
+ UPDATE_VERIFICATION_STATE_PERMISSION);
+ rowsUpdated = mDbHelper.updateContactKeyRemoteVerificationState(lookupKey,
+ ownerPackageName, deviceId, accountId, remoteVerificationState, timeUpdated);
+ } else {
+ rowsUpdated = mDbHelper.updateContactKeyRemoteVerificationState(lookupKey,
+ callerPackageName, deviceId, accountId, remoteVerificationState, timeUpdated);
+ }
+ final Bundle response = new Bundle();
+ response.putBoolean(E2eeContactKeys.KEY_UPDATED_ROWS, rowsUpdated > 0);
+ return response;
+ }
+
+ /**
+ * Removes an end-to-end encryption contact key entry given the lookupKey, deviceId, accountId
+ * and the inferred package name of the caller.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_UPDATED_ROWS} as a key and
+ * a boolean value being true if the row was removed, false otherwise.
+ */
+ private Bundle removeE2eeContactKey(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
+
+ final String lookupKey = extras.getString(E2eeContactKeys.LOOKUP_KEY);
+ final String deviceId = extras.getString(E2eeContactKeys.DEVICE_ID);
+ final String accountId = extras.getString(E2eeContactKeys.ACCOUNT_ID);
+ String callerPackageName = getCallingPackage();
+
+ int rowsRemoved = mDbHelper.removeContactKey(lookupKey, deviceId, accountId,
+ callerPackageName);
+
+ final Bundle response = new Bundle();
+ response.putBoolean(E2eeContactKeys.KEY_UPDATED_ROWS, rowsRemoved > 0);
+ return response;
+ }
+
+ /**
+ * Inserts a new entry into the end-to-end encryption self keys table or updates one if it
+ * already exists.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_UPDATED_ROWS} as a key and
+ * a boolean value being true if the row was added or updated, false otherwise.
+ */
+ private Bundle updateOrInsertE2eeSelfKey(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
+
+ final String deviceId = extras.getString(E2eeContactKeys.DEVICE_ID);
+ final String accountId = extras.getString(E2eeContactKeys.ACCOUNT_ID);
+ final byte[] keyValue = extras.getByteArray(E2eeContactKeys.KEY_VALUE);
+
+ String callerPackageName = getCallingPackage();
+ long timeUpdated = System.currentTimeMillis();
+
+ int rowsUpdateOrInserted = mDbHelper.updateOrInsertSelfKey(keyValue, deviceId, accountId,
+ callerPackageName, timeUpdated);
+
+ final Bundle response = new Bundle();
+ response.putBoolean(E2eeContactKeys.KEY_UPDATED_ROWS,
+ rowsUpdateOrInserted > 0);
+ return response;
+ }
+
+ /**
+ * Updates an end-to-end encryption self key entry
+ * {@link E2eeContactKeys.REMOTE_VERIFICATION_STATE} given the deviceId, accountId and the
+ * inferred package name of the caller.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_UPDATED_ROWS} as a key and
+ * a boolean value being true if the row was updated, false otherwise.
+ */
+ private Bundle updateE2eeSelfKeyRemoteVerificationState(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
+
+ final String deviceId = extras.getString(E2eeContactKeys.DEVICE_ID);
+ final String accountId = extras.getString(E2eeContactKeys.ACCOUNT_ID);
+ final int remoteVerificationState =
+ extras.getInt(E2eeContactKeys.REMOTE_VERIFICATION_STATE);
+ final long timeUpdated = System.currentTimeMillis();
+ final String callerPackageName = getCallingPackage();
+
+ int rowsUpdated;
+ if (extras.containsKey(E2eeContactKeys.OWNER_PACKAGE_NAME)) {
+ final String ownerPackageName = extras.getString(E2eeContactKeys.OWNER_PACKAGE_NAME);
+ E2eeContactKeysPermissions.enforceVisibility(getContext(),
+ callerPackageName, ownerPackageName);
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(),
+ UPDATE_VERIFICATION_STATE_PERMISSION);
+ rowsUpdated = mDbHelper.updateSelfKeyRemoteVerificationState(ownerPackageName,
+ deviceId, accountId, remoteVerificationState, timeUpdated);
+ } else {
+ rowsUpdated = mDbHelper.updateSelfKeyRemoteVerificationState(callerPackageName,
+ deviceId, accountId, remoteVerificationState, timeUpdated);
+ }
+
+ final Bundle response = new Bundle();
+ response.putBoolean(E2eeContactKeys.KEY_UPDATED_ROWS, rowsUpdated > 0);
+ return response;
+ }
+
+ /**
+ * Retrieves an end-to-end encryption self key entry given the deviceId, accountId and the
+ * inferred package name of the caller.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_CONTACT_KEY} as a key and a
+ * parcelable {@link E2eeContactKeysManager.E2eeContactKey} as a value
+ */
+ private Bundle getE2eeSelfKey(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
+ final String deviceId = extras.getString(E2eeContactKeys.DEVICE_ID);
+ final String accountId = extras.getString(E2eeContactKeys.ACCOUNT_ID);
+ String callerPackageName = getCallingPackage();
+
+ E2eeContactKeysManager.E2eeSelfKey selfKey = mDbHelper.getSelfKey(deviceId, accountId,
+ callerPackageName);
+
+ final Bundle response = new Bundle();
+ response.putParcelable(E2eeContactKeys.KEY_CONTACT_KEY, selfKey);
+
+ return response;
+ }
+
+ /**
+ * Retrieves all end-to-end encryption self key entries that belong to apps visible to the
+ * caller.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_CONTACT_KEYS} as a key and
+ * a parcelable list of {@link E2eeContactKeysManager.E2eeSelfKey} as a value
+ */
+ private Bundle getAllE2eeSelfKeys() {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
+
+ final Bundle response = new Bundle();
+
+ List<E2eeContactKeysManager.E2eeSelfKey> selfKeys = mDbHelper.getAllSelfKeys();
+
+ selfKeys = filterVisibleSelfKeys(selfKeys);
+ selfKeys = getStrippedSelfKeys(selfKeys);
+
+ response.putParcelableList(E2eeContactKeys.KEY_CONTACT_KEYS, selfKeys);
+
+ return response;
+ }
+
+ /**
+ * Retrieves all end-to-end encryption self key entries that are owned by the caller.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_CONTACT_KEYS} as a key and
+ * a parcelable list of {@link E2eeContactKeysManager.E2eeContactKey} as a value
+ */
+ private Bundle getOwnerE2eeSelfKeys() {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), READ_PERMISSION);
+
+ final Bundle response = new Bundle();
+
+ String callerPackageName = getCallingPackage();
+ List<E2eeContactKeysManager.E2eeSelfKey> selfKeys =
+ mDbHelper.getSelfKeysForOwnerPackageName(callerPackageName);
+
+ response.putParcelableList(E2eeContactKeys.KEY_CONTACT_KEYS, selfKeys);
+
+ return response;
+ }
+
+ /**
+ * Removes an end-to-end encryption self key entry
+ * {@link E2eeContactKeys.REMOTE_VERIFICATION_STATE} given the deviceId and the inferred
+ * package name of the caller.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.KEY_UPDATED_ROWS} as a key and a
+ * boolean value being true if the row was removed, false otherwise.
+ */
+ private Bundle removeE2eeSelfKey(Bundle extras) {
+ E2eeContactKeysPermissions.enforceCallingOrSelfPermission(getContext(), WRITE_PERMISSION);
+
+ final String deviceId = extras.getString(E2eeContactKeys.DEVICE_ID);
+ final String accountId = extras.getString(E2eeContactKeys.ACCOUNT_ID);
+ String callerPackageName = getCallingPackage();
+
+ int rowsRemoved = mDbHelper.removeSelfKey(deviceId, accountId, callerPackageName);
+
+ final Bundle response = new Bundle();
+
+ response.putBoolean(E2eeContactKeys.KEY_UPDATED_ROWS, rowsRemoved > 0);
+
+ return response;
+ }
+
+ /**
+ * Retrieves contact basic info - given the lookupKey of the contact, returns display name,
+ * phone number and email address.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.DISPLAY_NAME},
+ * {@link E2eeContactKeys.PHONE_NUMBER}
+ * and {@link E2eeContactKeys.EMAIL_ADDRESS} as keys and their corresponding
+ * values.
+ */
+ private Bundle getContactBasicInfoFromCP2(String lookupKey) {
+ Bundle bundle = new Bundle();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Bundle nameAndNumberBundle = getDisplayNameAndNumber(lookupKey);
+ bundle.putString(E2eeContactKeys.DISPLAY_NAME,
+ nameAndNumberBundle.getString(E2eeContactKeys.DISPLAY_NAME));
+ bundle.putString(E2eeContactKeys.PHONE_NUMBER,
+ nameAndNumberBundle.getString(E2eeContactKeys.PHONE_NUMBER));
+ bundle.putString(E2eeContactKeys.EMAIL_ADDRESS, getEmail(lookupKey));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return bundle;
+ }
+
+ /**
+ * Returns display name and phone number given the lookupKey of the contact.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.DISPLAY_NAME}
+ * and {@link E2eeContactKeys.PHONE_NUMBER} as keys and their corresponding values.
+ */
+ private Bundle getDisplayNameAndNumber(String lookupKey) {
+ Bundle bundle = new Bundle();
+ Cursor c = getContext().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
+ new String[] {ContactsContract.Data.DISPLAY_NAME,
+ ContactsContract.CommonDataKinds.Phone.NUMBER},
+ ContactsContract.Data.LOOKUP_KEY + " = ?",
+ new String[] { lookupKey }, null);
+ if (c.moveToFirst()) {
+ bundle.putString(E2eeContactKeys.DISPLAY_NAME,
+ c.getString(c.getColumnIndexOrThrow(ContactsContract.Data.DISPLAY_NAME)));
+ bundle.putString(E2eeContactKeys.PHONE_NUMBER,
+ c.getString(c.getColumnIndexOrThrow(
+ ContactsContract.CommonDataKinds.Phone.NUMBER)));
+ }
+ c.close();
+ return bundle;
+ }
+
+ /**
+ * Returns email address given the lookupKey of the contact.
+ *
+ * @return Bundle with a {@link E2eeContactKeys.EMAIL_ADDRESS} as key and an
+ * email address as a value.
+ */
+ private String getEmail(String lookupKey) {
+ String email = null;
+ Cursor c = getContext().getContentResolver().query(
+ ContactsContract.CommonDataKinds.Email.CONTENT_URI,
+ new String[] { ContactsContract.CommonDataKinds.Email.ADDRESS },
+ ContactsContract.Data.LOOKUP_KEY + " = ?",
+ new String[] { lookupKey }, null);
+ if (c.moveToFirst()) {
+ email = c.getString(c.getColumnIndexOrThrow(
+ ContactsContract.CommonDataKinds.Email.ADDRESS));
+ }
+ c.close();
+
+ return email;
+ }
+
+ /**
+ * Returns end-to-end encryption contact keys owned by the packages that are visible to the
+ * caller.
+ * This is verified by checking that the caller package can query the package owning the key.
+ */
+ private List<E2eeContactKeysManager.E2eeContactKey> filterVisibleContactKeys(
+ List<E2eeContactKeysManager.E2eeContactKey> contactKeys) {
+ List<E2eeContactKeysManager.E2eeContactKey> visibleContactKeys =
+ new ArrayList<>(contactKeys.size());
+ PackageManager packageManager = getContext().getPackageManager();
+ String callingPackageName = getCallingPackage();
+ for (E2eeContactKeysManager.E2eeContactKey contactKey : contactKeys) {
+ try {
+ String targetPackageName = contactKey.getOwnerPackageName();
+ if (packageManager.canPackageQuery(callingPackageName, targetPackageName)) {
+ visibleContactKeys.add(contactKey);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // The caller doesn't have visibility of the owner package
+ }
+ }
+ return visibleContactKeys;
+ }
+
+ /**
+ * Removes deviceId, timeUpdated, and key value data from end-to-end encryption contact keys.
+ */
+ private static List<E2eeContactKeysManager.E2eeContactKey> getStrippedContactKeys(
+ List<E2eeContactKeysManager.E2eeContactKey> visibleContactKeys) {
+ List<E2eeContactKeysManager.E2eeContactKey> strippedContactKeys = new ArrayList<>(
+ visibleContactKeys.size());
+ for (E2eeContactKeysManager.E2eeContactKey key : visibleContactKeys) {
+ E2eeContactKeysManager.E2eeContactKey strippedContactKey =
+ new E2eeContactKeysManager.E2eeContactKey(null, key.getAccountId(),
+ key.getOwnerPackageName(), STRIPPED_TIME_UPDATED, null,
+ key.getLocalVerificationState(), key.getRemoteVerificationState(),
+ key.getDisplayName(), key.getPhoneNumber(), key.getEmailAddress());
+ strippedContactKeys.add(strippedContactKey);
+ }
+ return strippedContactKeys;
+ }
+
+ /**
+ * Returns end-to-end encryption self keys owned by the packages that are visible to the caller.
+ * This is verified by checking that the caller package can query the package owning the key.
+ */
+ private List<E2eeContactKeysManager.E2eeSelfKey> filterVisibleSelfKeys(
+ List<E2eeContactKeysManager.E2eeSelfKey> selfKeys) {
+ List<E2eeContactKeysManager.E2eeSelfKey> visibleSelfKeys =
+ new ArrayList<>(selfKeys.size());
+ PackageManager packageManager = getContext().getPackageManager();
+ String callingPackageName = getCallingPackage();
+ for (E2eeContactKeysManager.E2eeSelfKey selfKey : selfKeys) {
+ try {
+ String targetPackageName = selfKey.getOwnerPackageName();
+ if (packageManager.canPackageQuery(callingPackageName, targetPackageName)) {
+ visibleSelfKeys.add(selfKey);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // The caller doesn't have visibility of the owner package
+ }
+ }
+ return visibleSelfKeys;
+ }
+
+
+ /**
+ * Removes deviceId, timeUpdated, and key value data from end-to-end encryption self keys.
+ */
+ private static List<E2eeContactKeysManager.E2eeSelfKey> getStrippedSelfKeys(
+ List<E2eeContactKeysManager.E2eeSelfKey> visibleSelfKeys) {
+ List<E2eeContactKeysManager.E2eeSelfKey> strippedSelfKeys = new ArrayList<>(
+ visibleSelfKeys.size());
+ for (E2eeContactKeysManager.E2eeSelfKey key : visibleSelfKeys) {
+ E2eeContactKeysManager.E2eeSelfKey strippedContactKey =
+ new E2eeContactKeysManager.E2eeSelfKey(null, key.getAccountId(),
+ key.getOwnerPackageName(), STRIPPED_TIME_UPDATED, null,
+ key.getRemoteVerificationState());
+ strippedSelfKeys.add(strippedContactKey);
+ }
+ return strippedSelfKeys;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ // Not implemented
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ // Not implemented
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues initialValues) {
+ // Not implemented
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String where, String[] whereArgs) {
+ // Not implemented
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
+ // Not implemented
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/providers/contactkeys/util/ContactKeysPermissions.java b/src/com/android/providers/contactkeys/util/E2eeContactKeysPermissions.java
similarity index 93%
rename from src/com/android/providers/contactkeys/util/ContactKeysPermissions.java
rename to src/com/android/providers/contactkeys/util/E2eeContactKeysPermissions.java
index 5e8240a..ce3b0c5 100644
--- a/src/com/android/providers/contactkeys/util/ContactKeysPermissions.java
+++ b/src/com/android/providers/contactkeys/util/E2eeContactKeysPermissions.java
@@ -18,17 +18,16 @@
import android.content.Context;
import android.content.pm.PackageManager;
-import android.net.Uri;
import android.os.Binder;
import android.os.Process;
import android.util.Log;
-public class ContactKeysPermissions {
- private static final String TAG = "ContactKeysPermissions";
+public class E2eeContactKeysPermissions {
+ private static final String TAG = "E2eeContactKeysPermissions";
private static final boolean DEBUG = false; // DO NOT submit with true
- private ContactKeysPermissions() {
+ private E2eeContactKeysPermissions() {
}
public static boolean hasCallerOrSelfPermission(Context context, String permission) {
diff --git a/tests/Android.bp b/tests/Android.bp
index 3eb6669..3ff2bf8 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -4,7 +4,7 @@
}
android_test {
- name: "ContactKeysProviderTests",
+ name: "E2eeContactKeysProviderTests",
static_libs: [
"ContactsProviderTestUtils",
"androidx.test.rules",
@@ -25,7 +25,7 @@
],
platform_apis: true,
test_suites: ["device-tests"],
- instrumentation_for: "ContactKeysProvider",
+ instrumentation_for: "E2eeContactKeysProvider",
certificate: "shared",
optimize: {
enabled: false,
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 4586ace..0a4ecbb 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -25,7 +25,7 @@
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.providers.contactkeys.tests"
- android:label="ContactKeys Provider Tests">
+ android:label="E2eeContactKeys Provider Tests">
</instrumentation>
</manifest>
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
index 913a9af..3a3bd4c 100644
--- a/tests/AndroidTest.xml
+++ b/tests/AndroidTest.xml
@@ -14,13 +14,13 @@
~ limitations under the License.
-->
-<configuration description="Runs ContactKeys Provider Tests.">
+<configuration description="Runs E2eeContactKeys Provider Tests.">
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="test-file-name" value="ContactKeysProviderTests.apk" />
+ <option name="test-file-name" value="E2eeContactKeysProviderTests.apk" />
</target_preparer>
<option name="test-suite-tag" value="apct" />
- <option name="test-tag" value="ContactKeysProviderTests" />
+ <option name="test-tag" value="E2eeContactKeysProviderTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.providers.contactkeys.tests" />
<option name="hidden-api-checks" value="false"/>
diff --git a/tests/src/com/android/providers/contactkeys/ContactKeysDatabaseHelperTest.java b/tests/src/com/android/providers/contactkeys/E2eeContactKeysDatabaseHelperTest.java
similarity index 62%
rename from tests/src/com/android/providers/contactkeys/ContactKeysDatabaseHelperTest.java
rename to tests/src/com/android/providers/contactkeys/E2eeContactKeysDatabaseHelperTest.java
index 3989ed8..4edfe44 100644
--- a/tests/src/com/android/providers/contactkeys/ContactKeysDatabaseHelperTest.java
+++ b/tests/src/com/android/providers/contactkeys/E2eeContactKeysDatabaseHelperTest.java
@@ -17,7 +17,7 @@
package com.android.providers.contactkeys;
import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.provider.ContactKeysManager;
+import android.provider.E2eeContactKeysManager;
import android.provider.Flags;
import android.test.ProviderTestCase2;
@@ -26,7 +26,7 @@
import java.util.List;
@RequiresFlagsEnabled(Flags.FLAG_USER_KEYS)
-public class ContactKeysDatabaseHelperTest extends ProviderTestCase2<ContactKeysProvider> {
+public class E2eeContactKeysDatabaseHelperTest extends ProviderTestCase2<E2eeContactKeysProvider> {
private static final String LOOKUP_KEY = "0r1-423A2E4644502A2E50";
private static final String LOOKUP_KEY_2 = "0r2-8T03DE4644502A2E50";
@@ -44,10 +44,10 @@
private static final String PHONE_NUMBER = "(555) 555-1234";
private static final String EMAIL_ADDRESS = "[email protected]";
- private ContactKeysDatabaseHelper mDbHelper;
+ private E2eeContactKeysDatabaseHelper mDbHelper;
- public ContactKeysDatabaseHelperTest() {
- super(ContactKeysProvider.class, ContactKeysProvider.AUTHORITY);
+ public E2eeContactKeysDatabaseHelperTest() {
+ super(E2eeContactKeysProvider.class, E2eeContactKeysProvider.AUTHORITY);
}
/**
@@ -55,7 +55,7 @@
*/
public void setUp() throws Exception {
super.setUp();
- mDbHelper = ((ContactKeysProvider) getProvider()).mDbHelper;
+ mDbHelper = ((E2eeContactKeysProvider) getProvider()).mDbHelper;
mDbHelper.getWritableDatabase().execSQL("DROP TABLE IF EXISTS contactkeys");
mDbHelper.getWritableDatabase().execSQL("DROP TABLE IF EXISTS selfkeys");
mDbHelper.onCreate(mDbHelper.getWritableDatabase());
@@ -76,12 +76,13 @@
public void testInsertAndGetContactKey() {
mDbHelper.updateOrInsertContactKey(LOOKUP_KEY, KEY_VALUE, DEVICE_ID, ACCOUNT_ID,
OWNER_PACKAGE_NAME, TIME_UPDATED, DISPLAY_NAME, PHONE_NUMBER, EMAIL_ADDRESS);
- ContactKeysManager.ContactKey contactKey =
+ E2eeContactKeysManager.E2eeContactKey contactKey =
mDbHelper.getContactKey(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID, ACCOUNT_ID);
- ContactKeysManager.ContactKey expectedContactKey =
- new ContactKeysManager.ContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- TIME_UPDATED, KEY_VALUE, ContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED, DISPLAY_NAME,
+ E2eeContactKeysManager.E2eeContactKey expectedContactKey =
+ new E2eeContactKeysManager.E2eeContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ TIME_UPDATED, KEY_VALUE,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED, DISPLAY_NAME,
PHONE_NUMBER, EMAIL_ADDRESS);
assertEquals(expectedContactKey, contactKey);
@@ -90,12 +91,13 @@
public void testInsertContactKeyNoBasicContactInfo() {
mDbHelper.updateOrInsertContactKey(LOOKUP_KEY, KEY_VALUE, DEVICE_ID, ACCOUNT_ID,
OWNER_PACKAGE_NAME, TIME_UPDATED, null, null, null);
- ContactKeysManager.ContactKey contactKey =
+ E2eeContactKeysManager.E2eeContactKey contactKey =
mDbHelper.getContactKey(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID, ACCOUNT_ID);
- ContactKeysManager.ContactKey expectedContactKey =
- new ContactKeysManager.ContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- TIME_UPDATED, KEY_VALUE, ContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED, null, null, null);
+ E2eeContactKeysManager.E2eeContactKey expectedContactKey =
+ new E2eeContactKeysManager.E2eeContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ TIME_UPDATED, KEY_VALUE,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED, null, null, null);
assertEquals(expectedContactKey, contactKey);
}
@@ -103,8 +105,8 @@
public void testUpdateContactKey() {
mDbHelper.updateOrInsertContactKey(LOOKUP_KEY, KEY_VALUE, DEVICE_ID, ACCOUNT_ID,
OWNER_PACKAGE_NAME, TIME_UPDATED, DISPLAY_NAME, PHONE_NUMBER, EMAIL_ADDRESS);
- int localVerificationState = ContactKeysManager.VERIFICATION_STATE_VERIFIED;
- int remoteVerificationState = ContactKeysManager.VERIFICATION_STATE_VERIFIED;
+ int localVerificationState = E2eeContactKeysManager.VERIFICATION_STATE_VERIFIED;
+ int remoteVerificationState = E2eeContactKeysManager.VERIFICATION_STATE_VERIFIED;
mDbHelper.updateContactKeyLocalVerificationState(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID,
ACCOUNT_ID, localVerificationState, TIME_UPDATED + 1);
mDbHelper.updateContactKeyRemoteVerificationState(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID,
@@ -113,11 +115,11 @@
long timeUpdated = TIME_UPDATED + 3;
mDbHelper.updateOrInsertContactKey(LOOKUP_KEY, KEY_VALUE_2, DEVICE_ID, ACCOUNT_ID,
OWNER_PACKAGE_NAME, timeUpdated, DISPLAY_NAME, PHONE_NUMBER, EMAIL_ADDRESS);
- ContactKeysManager.ContactKey contactKey =
+ E2eeContactKeysManager.E2eeContactKey contactKey =
mDbHelper.getContactKey(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID, ACCOUNT_ID);
- ContactKeysManager.ContactKey expectedContactKey =
- new ContactKeysManager.ContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ E2eeContactKeysManager.E2eeContactKey expectedContactKey =
+ new E2eeContactKeysManager.E2eeContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
timeUpdated, KEY_VALUE_2, localVerificationState, remoteVerificationState,
DISPLAY_NAME, PHONE_NUMBER, EMAIL_ADDRESS);
@@ -133,7 +135,7 @@
assertEquals(1, rowsRemoved);
- ContactKeysManager.ContactKey contactKey =
+ E2eeContactKeysManager.E2eeContactKey contactKey =
mDbHelper.getContactKey(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID, ACCOUNT_ID);
assertNull(contactKey);
@@ -143,16 +145,16 @@
mDbHelper.updateOrInsertContactKey(LOOKUP_KEY, KEY_VALUE, DEVICE_ID, ACCOUNT_ID,
OWNER_PACKAGE_NAME, TIME_UPDATED, DISPLAY_NAME, PHONE_NUMBER, EMAIL_ADDRESS);
- int updatedLvs = ContactKeysManager.VERIFICATION_STATE_VERIFIED;
+ int updatedLvs = E2eeContactKeysManager.VERIFICATION_STATE_VERIFIED;
mDbHelper.updateContactKeyLocalVerificationState(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID,
ACCOUNT_ID, updatedLvs, TIME_UPDATED);
- ContactKeysManager.ContactKey contactKey =
+ E2eeContactKeysManager.E2eeContactKey contactKey =
mDbHelper.getContactKey(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID, ACCOUNT_ID);
- ContactKeysManager.ContactKey expectedContactKey =
- new ContactKeysManager.ContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ E2eeContactKeysManager.E2eeContactKey expectedContactKey =
+ new E2eeContactKeysManager.E2eeContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
TIME_UPDATED, KEY_VALUE, updatedLvs,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED, DISPLAY_NAME,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED, DISPLAY_NAME,
PHONE_NUMBER, EMAIL_ADDRESS);
assertEquals(expectedContactKey, contactKey);
@@ -162,16 +164,17 @@
mDbHelper.updateOrInsertContactKey(LOOKUP_KEY, KEY_VALUE, DEVICE_ID, ACCOUNT_ID,
OWNER_PACKAGE_NAME, TIME_UPDATED, DISPLAY_NAME, PHONE_NUMBER, EMAIL_ADDRESS);
- int updatedRvs = ContactKeysManager.VERIFICATION_STATE_VERIFIED;
+ int updatedRvs = E2eeContactKeysManager.VERIFICATION_STATE_VERIFIED;
mDbHelper.updateContactKeyRemoteVerificationState(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID,
ACCOUNT_ID, updatedRvs, TIME_UPDATED);
- ContactKeysManager.ContactKey contactKey =
+ E2eeContactKeysManager.E2eeContactKey contactKey =
mDbHelper.getContactKey(LOOKUP_KEY, OWNER_PACKAGE_NAME, DEVICE_ID, ACCOUNT_ID);
- ContactKeysManager.ContactKey expectedContactKey =
- new ContactKeysManager.ContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- TIME_UPDATED, KEY_VALUE, ContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
- updatedRvs, DISPLAY_NAME, PHONE_NUMBER, EMAIL_ADDRESS);
+ E2eeContactKeysManager.E2eeContactKey expectedContactKey =
+ new E2eeContactKeysManager.E2eeContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ TIME_UPDATED, KEY_VALUE,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED, updatedRvs,
+ DISPLAY_NAME, PHONE_NUMBER, EMAIL_ADDRESS);
assertEquals(expectedContactKey, contactKey);
}
@@ -185,21 +188,22 @@
mDbHelper.updateOrInsertContactKey(LOOKUP_KEY_2, KEY_VALUE_3, DEVICE_ID_2, ACCOUNT_ID_2,
OWNER_PACKAGE_NAME, TIME_UPDATED, "Bob", null, null);
- List<ContactKeysManager.ContactKey> contactKeys =
+ List<E2eeContactKeysManager.E2eeContactKey> contactKeys =
mDbHelper.getAllContactKeys(LOOKUP_KEY);
- ContactKeysManager.ContactKey expectedContactKey1 =
- new ContactKeysManager.ContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- TIME_UPDATED, KEY_VALUE, ContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED, DISPLAY_NAME,
+ E2eeContactKeysManager.E2eeContactKey expectedContactKey1 =
+ new E2eeContactKeysManager.E2eeContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ TIME_UPDATED, KEY_VALUE,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED, DISPLAY_NAME,
PHONE_NUMBER, EMAIL_ADDRESS);
- ContactKeysManager.ContactKey expectedContactKey2 =
- new ContactKeysManager.ContactKey(DEVICE_ID_2, ACCOUNT_ID, OWNER_PACKAGE_NAME_2,
- TIME_UPDATED, KEY_VALUE_2,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED, DISPLAY_NAME, null,
- null);
- List<ContactKeysManager.ContactKey> expectedContactKeys = ImmutableList.of(
+ E2eeContactKeysManager.E2eeContactKey expectedContactKey2 =
+ new E2eeContactKeysManager.E2eeContactKey(DEVICE_ID_2, ACCOUNT_ID,
+ OWNER_PACKAGE_NAME_2, TIME_UPDATED, KEY_VALUE_2,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
+ DISPLAY_NAME, null, null);
+ List<E2eeContactKeysManager.E2eeContactKey> expectedContactKeys = ImmutableList.of(
expectedContactKey1, expectedContactKey2);
assertEquals(expectedContactKeys.size(), contactKeys.size());
@@ -216,21 +220,22 @@
mDbHelper.updateOrInsertContactKey(LOOKUP_KEY_2, KEY_VALUE_3, DEVICE_ID_2, ACCOUNT_ID_2,
OWNER_PACKAGE_NAME, TIME_UPDATED, "Charlie", null, null);
- List<ContactKeysManager.ContactKey> contactKeys =
+ List<E2eeContactKeysManager.E2eeContactKey> contactKeys =
mDbHelper.getContactKeysForOwnerPackageName(LOOKUP_KEY, OWNER_PACKAGE_NAME);
- ContactKeysManager.ContactKey expectedContactKey1 =
- new ContactKeysManager.ContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- TIME_UPDATED, KEY_VALUE, ContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED, DISPLAY_NAME,
- PHONE_NUMBER, EMAIL_ADDRESS);
- ContactKeysManager.ContactKey expectedContactKey2 =
- new ContactKeysManager.ContactKey(DEVICE_ID_2, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- TIME_UPDATED, KEY_VALUE_2,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED, DISPLAY_NAME, null,
- null);
- List<ContactKeysManager.ContactKey> expectedContactKeys = ImmutableList.of(
+ E2eeContactKeysManager.E2eeContactKey expectedContactKey1 =
+ new E2eeContactKeysManager.E2eeContactKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ TIME_UPDATED, KEY_VALUE,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
+ DISPLAY_NAME, PHONE_NUMBER, EMAIL_ADDRESS);
+ E2eeContactKeysManager.E2eeContactKey expectedContactKey2 =
+ new E2eeContactKeysManager.E2eeContactKey(DEVICE_ID_2, ACCOUNT_ID,
+ OWNER_PACKAGE_NAME, TIME_UPDATED, KEY_VALUE_2,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED,
+ DISPLAY_NAME, null, null);
+ List<E2eeContactKeysManager.E2eeContactKey> expectedContactKeys = ImmutableList.of(
expectedContactKey1, expectedContactKey2);
assertEquals(expectedContactKeys.size(), contactKeys.size());
@@ -240,11 +245,12 @@
public void testInsertAndGetSelfKey() {
mDbHelper.updateOrInsertSelfKey(KEY_VALUE, DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
TIME_UPDATED);
- ContactKeysManager.SelfKey selfKey =
+ E2eeContactKeysManager.E2eeSelfKey selfKey =
mDbHelper.getSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME);
- ContactKeysManager.SelfKey expectedSelfKey =
- new ContactKeysManager.SelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- TIME_UPDATED, KEY_VALUE, ContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
+ E2eeContactKeysManager.E2eeSelfKey expectedSelfKey =
+ new E2eeContactKeysManager.E2eeSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ TIME_UPDATED, KEY_VALUE,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
assertEquals(expectedSelfKey, selfKey);
}
@@ -255,17 +261,18 @@
mDbHelper.updateOrInsertSelfKey(KEY_VALUE_2, DEVICE_ID_2, ACCOUNT_ID_2,
OWNER_PACKAGE_NAME_2, TIME_UPDATED);
- List<ContactKeysManager.SelfKey> selfKeys =
+ List<E2eeContactKeysManager.E2eeSelfKey> selfKeys =
mDbHelper.getAllSelfKeys();
- ContactKeysManager.SelfKey expectedSelfKey1 =
- new ContactKeysManager.SelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- TIME_UPDATED, KEY_VALUE, ContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
- ContactKeysManager.SelfKey expectedSelfKey2 =
- new ContactKeysManager.SelfKey(DEVICE_ID_2, ACCOUNT_ID_2, OWNER_PACKAGE_NAME_2,
- TIME_UPDATED, KEY_VALUE_2,
- ContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
- List<ContactKeysManager.SelfKey> expectedSelfKeys = ImmutableList.of(
+ E2eeContactKeysManager.E2eeSelfKey expectedSelfKey1 =
+ new E2eeContactKeysManager.E2eeSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ TIME_UPDATED, KEY_VALUE,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
+ E2eeContactKeysManager.E2eeSelfKey expectedSelfKey2 =
+ new E2eeContactKeysManager.E2eeSelfKey(DEVICE_ID_2, ACCOUNT_ID_2,
+ OWNER_PACKAGE_NAME_2, TIME_UPDATED, KEY_VALUE_2,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
+ List<E2eeContactKeysManager.E2eeSelfKey> expectedSelfKeys = ImmutableList.of(
expectedSelfKey1, expectedSelfKey2);
assertEquals(expectedSelfKeys.size(), selfKeys.size());
@@ -278,13 +285,15 @@
mDbHelper.updateOrInsertSelfKey(KEY_VALUE_2, DEVICE_ID_2, ACCOUNT_ID_2,
OWNER_PACKAGE_NAME_2, TIME_UPDATED);
- List<ContactKeysManager.SelfKey> selfKeys =
+ List<E2eeContactKeysManager.E2eeSelfKey> selfKeys =
mDbHelper.getSelfKeysForOwnerPackageName(OWNER_PACKAGE_NAME);
- ContactKeysManager.SelfKey expectedSelfKey1 =
- new ContactKeysManager.SelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- TIME_UPDATED, KEY_VALUE, ContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
- List<ContactKeysManager.SelfKey> expectedSelfKeys = ImmutableList.of(expectedSelfKey1);
+ E2eeContactKeysManager.E2eeSelfKey expectedSelfKey1 =
+ new E2eeContactKeysManager.E2eeSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ TIME_UPDATED, KEY_VALUE,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
+ List<E2eeContactKeysManager.E2eeSelfKey> expectedSelfKeys =
+ ImmutableList.of(expectedSelfKey1);
assertEquals(expectedSelfKeys.size(), selfKeys.size());
assertTrue(expectedSelfKeys.containsAll(selfKeys));
@@ -297,12 +306,13 @@
long timeUpdated = TIME_UPDATED + 1;
mDbHelper.updateOrInsertSelfKey(KEY_VALUE_2, DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
timeUpdated);
- ContactKeysManager.SelfKey selfKey =
+ E2eeContactKeysManager.E2eeSelfKey selfKey =
mDbHelper.getSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME);
- ContactKeysManager.SelfKey expectedSelfKey =
- new ContactKeysManager.SelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
- timeUpdated, KEY_VALUE_2, ContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
+ E2eeContactKeysManager.E2eeSelfKey expectedSelfKey =
+ new E2eeContactKeysManager.E2eeSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ timeUpdated, KEY_VALUE_2,
+ E2eeContactKeysManager.VERIFICATION_STATE_UNVERIFIED);
assertEquals(expectedSelfKey, selfKey);
}
@@ -312,14 +322,14 @@
TIME_UPDATED);
long timeUpdated = TIME_UPDATED + 1;
- int updatedRvs = ContactKeysManager.VERIFICATION_STATE_VERIFIED;
+ int updatedRvs = E2eeContactKeysManager.VERIFICATION_STATE_VERIFIED;
mDbHelper.updateSelfKeyRemoteVerificationState(OWNER_PACKAGE_NAME, DEVICE_ID, ACCOUNT_ID,
updatedRvs, timeUpdated);
- ContactKeysManager.SelfKey selfKey =
+ E2eeContactKeysManager.E2eeSelfKey selfKey =
mDbHelper.getSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME);
- ContactKeysManager.SelfKey expectedSelfKey =
- new ContactKeysManager.SelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
+ E2eeContactKeysManager.E2eeSelfKey expectedSelfKey =
+ new E2eeContactKeysManager.E2eeSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME,
timeUpdated, KEY_VALUE, updatedRvs);
assertEquals(expectedSelfKey, selfKey);
@@ -330,7 +340,7 @@
TIME_UPDATED);
mDbHelper.removeSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME);
- ContactKeysManager.SelfKey selfKey =
+ E2eeContactKeysManager.E2eeSelfKey selfKey =
mDbHelper.getSelfKey(DEVICE_ID, ACCOUNT_ID, OWNER_PACKAGE_NAME);
assertNull(selfKey);