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

Commit af90e5c4 authored by Sergei Makarov's avatar Sergei Makarov
Browse files

Add E2eeBaseKey class.

This abstract class is extended by E2eeContactKey and E2eeSelfKey classes.

Bug: 322979243
Test: atest CtsContactKeysManagerTestCases:E2eeContactKeysManagerTest
Change-Id: I0aaab37a72f249a5d9059e064d717388b4c2544e
parent ed7f177a
Loading
Loading
Loading
Loading
+149 −253
Original line number Diff line number Diff line
@@ -76,12 +76,14 @@ import java.util.Objects;
public final class E2eeContactKeysManager {
    /**
     * The authority for the end-to-end encryption contact keys provider.
     *
     * @hide
     */
    public static final String AUTHORITY = "com.android.contactkeys.contactkeysprovider";

    /**
     * A content:// style uri to the authority for the end-to-end encryption contact keys provider.
     *
     * @hide
     */
    @NonNull
@@ -140,7 +142,6 @@ public final class E2eeContactKeysManager {
     * @param lookupKey the value that references the contact
     * @param deviceId  an app-specified identifier for the device
     * @param accountId an app-specified identifier for the account
     *
     * @return a {@link E2eeContactKey} object containing the contact key information,
     * or null if no contact key is found.
     */
@@ -170,7 +171,6 @@ public final class E2eeContactKeysManager {
     * The keys will be stripped of deviceId, timeUpdated and keyValue data.
     *
     * @param lookupKey the value that references the contact
     *
     * @return a list of {@link E2eeContactKey} objects containing the contact key
     * information, or an empty list if no keys are found.
     */
@@ -199,7 +199,6 @@ public final class E2eeContactKeysManager {
     * the caller app.
     *
     * @param lookupKey the value that references the contact
     *
     * @return a list of {@link E2eeContactKey} objects containing the end-to-end encryption
     * contact key information, or an empty list if no keys are found.
     */
@@ -231,7 +230,6 @@ public final class E2eeContactKeysManager {
     * @param deviceId               an app-specified identifier for the device
     * @param accountId              an app-specified identifier for the account
     * @param localVerificationState the new local verification state
     *
     * @return true if the entry was updated, false otherwise.
     */
    @RequiresPermission(android.Manifest.permission.WRITE_CONTACTS)
@@ -262,9 +260,7 @@ public final class E2eeContactKeysManager {
     * @param accountId              an app-specified identifier for the account
     * @param ownerPackageName       the package name of the app that owns the key
     * @param localVerificationState the new local verification state
     *
     * @return true if the entry was updated, false otherwise.
     *
     * @hide
     */
    @SystemApi
@@ -300,7 +296,6 @@ public final class E2eeContactKeysManager {
     * @param deviceId                an app-specified identifier for the device
     * @param accountId               an app-specified identifier for the account
     * @param remoteVerificationState the new remote verification state
     *
     * @return true if the entry was updated, false otherwise.
     */
    @RequiresPermission(android.Manifest.permission.WRITE_CONTACTS)
@@ -331,9 +326,7 @@ public final class E2eeContactKeysManager {
     * @param accountId               an app-specified identifier for the account
     * @param ownerPackageName        the package name of the app that owns the key
     * @param remoteVerificationState the new remote verification state
     *
     * @return true if the entry was updated, false otherwise.
     *
     * @hide
     */
    @SystemApi
@@ -376,7 +369,6 @@ public final class E2eeContactKeysManager {
     * @param lookupKey the value that references the contact
     * @param deviceId  an app-specified identifier for the device
     * @param accountId an app-specified identifier for the account
     *
     * @return true if the entry was removed, false otherwise.
     */
    @RequiresPermission(android.Manifest.permission.WRITE_CONTACTS)
@@ -397,11 +389,10 @@ public final class E2eeContactKeysManager {
    /**
     * Inserts a new entry into the end-to-end encryption self keys table or updates one if it
     * already exists.

     *
     * @param deviceId  an app-specified identifier for the device
     * @param accountId an app-specified identifier for the account
     * @param keyValue  the raw bytes for the key (max size is {@link #getMaxKeySizeBytes} bytes)
     *
     * @return true if the entry was added or updated, false otherwise.
     */
    @RequiresPermission(android.Manifest.permission.WRITE_CONTACTS)
@@ -435,7 +426,6 @@ public final class E2eeContactKeysManager {
     * @param deviceId                an app-specified identifier for the device
     * @param accountId               an app-specified identifier for the account
     * @param remoteVerificationState the new remote verification state
     *
     * @return true if the entry was updated, false otherwise.
     */
    @RequiresPermission(android.Manifest.permission.WRITE_CONTACTS)
@@ -463,9 +453,7 @@ public final class E2eeContactKeysManager {
     * @param accountId               an app-specified identifier for the account
     * @param ownerPackageName        the package name of the app that owns the key
     * @param remoteVerificationState the new remote verification state
     *
     * @return true if the entry was updated, false otherwise.
     *
     * @hide
     */
    @SystemApi
@@ -504,7 +492,6 @@ public final class E2eeContactKeysManager {
     *
     * @param deviceId  an app-specified identifier for the device
     * @param accountId an app-specified identifier for the account
     *
     * @return a {@link E2eeSelfKey} object containing the end-to-end encryption self key
     * information, or null if no self key is found.
     */
@@ -579,9 +566,9 @@ public final class E2eeContactKeysManager {
    /**
     * Removes an end-to-end encryption self key entry given the deviceId and the inferred
     * package name of the caller.
     *
     * @param deviceId  an app-specified identifier for the device
     * @param accountId an app-specified identifier for the account
     *
     * @return true if the entry was removed, false otherwise.
     */
    @RequiresPermission(android.Manifest.permission.WRITE_CONTACTS)
@@ -608,6 +595,7 @@ public final class E2eeContactKeysManager {

    /**
     * Possible values of verification state.
     *
     * @hide
     */
    @IntDef(prefix = {"VERIFICATION_STATE_"}, value = {
@@ -616,7 +604,8 @@ public final class E2eeContactKeysManager {
            VERIFICATION_STATE_VERIFIED
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface VerificationState {}
    public @interface VerificationState {
    }

    /**
     * Unverified state of a contact end to end encrypted key.
@@ -634,7 +623,8 @@ public final class E2eeContactKeysManager {
    /** @hide */
    public static final class E2eeContactKeys {

        private E2eeContactKeys() {}
        private E2eeContactKeys() {
        }

        /**
         * <p>
@@ -808,34 +798,7 @@ public final class E2eeContactKeysManager {
    /**
     * A parcelable class encapsulating other users' end to end encrypted contact key.
     */
    public static final class E2eeContactKey implements Parcelable {
        /**
         * An app-specified identifier for the device for which the end-to-end encryption
         * contact key can be used.
         */
        private final String mDeviceId;

        /**
         * An app-specified identifier for the account for which the end-to-end encryption
         * contact key can be used.
         * Usually a phone number.
         */
        private final String mAccountId;

        /**
         * Owner application package name.
         */
        private final String mOwnerPackageName;

        /**
         * Timestamp at which the key was updated.
         */
        private final long mTimeUpdated;

        /**
         * The raw bytes for the key.
         */
        private final byte[] mKeyValue;
    public static final class E2eeContactKey extends E2eeBaseKey implements Parcelable {

        /**
         * Describes the local verification state for the key, for instance QR-code based
@@ -843,12 +806,6 @@ public final class E2eeContactKeysManager {
         */
        private final int mLocalVerificationState;

        /**
         * Describes the remote verification state for the key, for instance through a key
         * transparency server.
         */
        private final int mRemoteVerificationState;

        /**
         * The display name for the contact.
         */
@@ -873,76 +830,14 @@ public final class E2eeContactKeysManager {
                @VerificationState int remoteVerificationState,
                @Nullable String displayName,
                @Nullable String phoneNumber, @Nullable String emailAddress) {
            this.mDeviceId = deviceId;
            this.mAccountId = accountId;
            this.mOwnerPackageName = ownerPackageName;
            this.mTimeUpdated = timeUpdated;
            this.mKeyValue = keyValue == null ? null : Arrays.copyOf(keyValue, keyValue.length);
            super(deviceId, accountId, ownerPackageName, timeUpdated, keyValue,
                    remoteVerificationState);
            this.mLocalVerificationState = localVerificationState;
            this.mRemoteVerificationState = remoteVerificationState;
            this.mDisplayName = displayName;
            this.mPhoneNumber = phoneNumber;
            this.mEmailAddress = emailAddress;
        }

        /**
         * Gets the app-specified identifier for the device for which the end-to-end encryption
         * contact key can be used.
         * Returns null if the app doesn't have the required visibility into
         * the end-to-end encryption contact key.
         *
         * @return An app-specified identifier for the device.
         */
        @Nullable
        public String getDeviceId() {
            return mDeviceId;
        }

        /**
         * Gets the app-specified identifier for the account for which the end-to-end encryption
         * contact key can be used.
         * Usually a phone number.
         *
         * @return An app-specified identifier for the account.
         */
        @NonNull
        public String getAccountId() {
            return mAccountId;
        }

        /**
         * Gets the owner application package name.
         *
         * @return The owner application package name.
         */
        @NonNull
        public String getOwnerPackageName() {
            return mOwnerPackageName;
        }

        /**
         * Gets the timestamp at which the key was updated. Returns -1 if the app doesn't have the
         * required visibility into the end-to-end encryption contact key.
         *
         * @return The timestamp at which the key was updated in the System.currentTimeMillis()
         * base.
         */
        public long getTimeUpdated() {
            return mTimeUpdated;
        }

        /**
         * Gets the raw bytes for the key.
         * Returns null if the app doesn't have the required visibility into
         * the end-to-end encryption contact key.
         *
         * @return A copy of the raw bytes for the key.
         */
        @Nullable
        public byte[] getKeyValue() {
            return mKeyValue == null ? null : Arrays.copyOf(mKeyValue, mKeyValue.length);
        }

        /**
         * Gets the local verification state for the key, for instance QR-code based verification.
         *
@@ -952,16 +847,6 @@ public final class E2eeContactKeysManager {
            return mLocalVerificationState;
        }

        /**
         * Gets the remote verification state for the key, for instance through a key transparency
         * server.
         *
         * @return The remote verification state for the key.
         */
        public @VerificationState int getRemoteVerificationState() {
            return mRemoteVerificationState;
        }

        /**
         * Gets the display name for the contact.
         *
@@ -1079,46 +964,126 @@ public final class E2eeContactKeysManager {
    /**
     * A parcelable class encapsulating self end to end encrypted contact key.
     */
    public static final class E2eeSelfKey implements Parcelable {
    public static final class E2eeSelfKey extends E2eeBaseKey implements Parcelable {
        /**
         * An app-specified identifier for the device for which the end-to-end encryption
         * contact key can be used.
         * @hide
         */
        public E2eeSelfKey(@Nullable String deviceId, @NonNull String accountId,
                @NonNull String ownerPackageName, long timeUpdated, @Nullable byte[] keyValue,
                @VerificationState int remoteVerificationState) {
            super(deviceId, accountId, ownerPackageName, timeUpdated, keyValue,
                    remoteVerificationState);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mDeviceId, mAccountId, mOwnerPackageName, mTimeUpdated,
                    Arrays.hashCode(mKeyValue), mRemoteVerificationState);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) return false;
            if (obj == this) return true;

            if (!(obj instanceof E2eeSelfKey toCompare)) {
                return false;
            }

            return Objects.equals(mDeviceId, toCompare.mDeviceId)
                    && Objects.equals(mAccountId, toCompare.mAccountId)
                    && Objects.equals(mOwnerPackageName, toCompare.mOwnerPackageName)
                    && mTimeUpdated == toCompare.mTimeUpdated
                    && Arrays.equals(mKeyValue, toCompare.mKeyValue)
                    && mRemoteVerificationState == toCompare.mRemoteVerificationState;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            dest.writeString8(mDeviceId);
            dest.writeString8(mAccountId);
            dest.writeString8(mOwnerPackageName);
            dest.writeLong(mTimeUpdated);
            dest.writeInt(mKeyValue != null ? mKeyValue.length : ARRAY_IS_NULL);
            if (mKeyValue != null) {
                dest.writeByteArray(mKeyValue);
            }
            dest.writeInt(mRemoteVerificationState);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @NonNull
        public static final Creator<E2eeSelfKey> CREATOR =
                new Creator<>() {
                    @Override
                    public E2eeSelfKey createFromParcel(Parcel source) {
                        String deviceId = source.readString8();
                        String accountId = source.readString8();
                        String ownerPackageName = source.readString8();
                        long timeUpdated = source.readLong();
                        int keyValueLength = source.readInt();
                        byte[] keyValue;
                        if (keyValueLength > 0) {
                            keyValue = new byte[keyValueLength];
                            source.readByteArray(keyValue);
                        } else {
                            keyValue = null;
                        }
                        int remoteVerificationState = source.readInt();
                        return new E2eeSelfKey(deviceId, accountId, ownerPackageName,
                                timeUpdated, keyValue, remoteVerificationState);
                    }

                    @Override
                    public E2eeSelfKey[] newArray(int size) {
                        return new E2eeSelfKey[size];
                    }
                };
    }

    /**
     * An abstract class that's extended by self and contact key classes.
     *
     * @hide
     */
    abstract static class E2eeBaseKey {
        /**
         * An app-specified identifier for the device for which the key can be used.
         */
        private final String mDeviceId;
        protected final String mDeviceId;

        /**
         * An app-specified identifier for the account for which the end-to-end encryption
         * contact key can be used.
         * An app-specified identifier for the account for which the key can be used.
         * Usually a phone number.
         */
        private final String mAccountId;
        protected final String mAccountId;

        /**
         * Owner application package name.
         */
        private final String mOwnerPackageName;
        protected final String mOwnerPackageName;

        /**
         * Timestamp at which the key was updated.
         */
        private final long mTimeUpdated;
        protected final long mTimeUpdated;

        /**
         * The raw bytes for the key.
         */
        private final byte[] mKeyValue;

        protected final byte[] mKeyValue;

        /**
         * Describes the remote verification state for the key, for instance through a key
         * transparency server.
         * Describes the remote verification state for the end-to-end encryption key, for instance
         * through a key transparency server.
         */
        private final int mRemoteVerificationState;
        protected final int mRemoteVerificationState;

        /**
         * @hide
         */
        public E2eeSelfKey(@Nullable String deviceId, @NonNull String accountId,
        protected E2eeBaseKey(@Nullable String deviceId, @NonNull String accountId,
                @NonNull String ownerPackageName, long timeUpdated, @Nullable byte[] keyValue,
                @VerificationState int remoteVerificationState) {
            this.mDeviceId = deviceId;
@@ -1131,9 +1096,9 @@ public final class E2eeContactKeysManager {

        /**
         * Gets the app-specified identifier for the device for which the end-to-end encryption
         * contact key can be used.
         * key can be used.
         * Returns null if the app doesn't have the required visibility into
         * the end-to-end encryption contact key.
         * the end-to-end encryption key.
         *
         * @return An app-specified identifier for the device.
         */
@@ -1144,10 +1109,10 @@ public final class E2eeContactKeysManager {

        /**
         * Gets the app-specified identifier for the account for which the end-to-end encryption
         * contact key can be used.
         * key can be used.
         * Usually a phone number.
         *
         * @return An app-specified identifier for the device.
         * @return An app-specified identifier for the account.
         */
        @NonNull
        public String getAccountId() {
@@ -1165,8 +1130,8 @@ public final class E2eeContactKeysManager {
        }

        /**
         * Gets the timestamp at which the key was updated. Returns -1 if the app doesn't have the
         * required visibility into the end-to-end encryption contact key.
         * Gets the timestamp at which the end-to-end encryption key was updated. Returns -1 if
         * the app doesn't have the required visibility into the key.
         *
         * @return The timestamp at which the key was updated in the System.currentTimeMillis()
         * base.
@@ -1176,11 +1141,11 @@ public final class E2eeContactKeysManager {
        }

        /**
         * Gets the raw bytes for the key.
         * Gets the raw bytes for the end-to-end encryption key.
         * Returns null if the app doesn't have the required visibility into
         * the end-to-end encryption contact key.
         * the end-to-end encryption key.
         *
         * @return A copy of the raw bytes for the key.
         * @return A copy of the raw bytes for the end-to-end encryption key.
         */
        @Nullable
        public byte[] getKeyValue() {
@@ -1188,82 +1153,13 @@ public final class E2eeContactKeysManager {
        }

        /**
         * Gets the remote verification state for the key, for instance through a key transparency
         * server.
         * Gets the remote verification state for the end-to-end encryption key, for instance
         * through a key transparency server.
         *
         * @return The remote verification state for the key.
         * @return The remote verification state for the end-to-end encryption key.
         */
        public @VerificationState int getRemoteVerificationState() {
            return mRemoteVerificationState;
        }

        @Override
        public int hashCode() {
            return Objects.hash(mDeviceId, mAccountId, mOwnerPackageName, mTimeUpdated,
                    Arrays.hashCode(mKeyValue), mRemoteVerificationState);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) return false;
            if (obj == this) return true;

            if (!(obj instanceof E2eeSelfKey toCompare)) {
                return false;
            }

            return Objects.equals(mDeviceId, toCompare.mDeviceId)
                    && Objects.equals(mAccountId, toCompare.mAccountId)
                    && Objects.equals(mOwnerPackageName, toCompare.mOwnerPackageName)
                    && mTimeUpdated == toCompare.mTimeUpdated
                    && Arrays.equals(mKeyValue, toCompare.mKeyValue)
                    && mRemoteVerificationState == toCompare.mRemoteVerificationState;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            dest.writeString8(mDeviceId);
            dest.writeString8(mAccountId);
            dest.writeString8(mOwnerPackageName);
            dest.writeLong(mTimeUpdated);
            dest.writeInt(mKeyValue != null ? mKeyValue.length : ARRAY_IS_NULL);
            if (mKeyValue != null) {
                dest.writeByteArray(mKeyValue);
            }
            dest.writeInt(mRemoteVerificationState);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @NonNull
        public static final Creator<E2eeSelfKey> CREATOR =
                new Creator<>() {
                    @Override
                    public E2eeSelfKey createFromParcel(Parcel source) {
                        String deviceId = source.readString8();
                        String accountId = source.readString8();
                        String ownerPackageName = source.readString8();
                        long timeUpdated = source.readLong();
                        int keyValueLength = source.readInt();
                        byte[] keyValue;
                        if (keyValueLength > 0) {
                            keyValue = new byte[keyValueLength];
                            source.readByteArray(keyValue);
                        } else {
                            keyValue = null;
                        }
                        int remoteVerificationState = source.readInt();
                        return new E2eeSelfKey(deviceId, accountId, ownerPackageName,
                                timeUpdated, keyValue, remoteVerificationState);
                    }

                    @Override
                    public E2eeSelfKey[] newArray(int size) {
                        return new E2eeSelfKey[size];
                    }
                };
    }
}