425 lines
14 KiB
Java
425 lines
14 KiB
Java
/*
|
|
* Copyright (C) 2022 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 android.nearby;
|
|
|
|
import android.annotation.IntDef;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.annotation.SystemApi;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* Represents a Presence device from nearby scans.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public final class PresenceDevice extends NearbyDevice implements Parcelable {
|
|
|
|
/** The type of presence device. */
|
|
/** @hide **/
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@IntDef({
|
|
DeviceType.UNKNOWN,
|
|
DeviceType.PHONE,
|
|
DeviceType.TABLET,
|
|
DeviceType.DISPLAY,
|
|
DeviceType.LAPTOP,
|
|
DeviceType.TV,
|
|
DeviceType.WATCH,
|
|
})
|
|
public @interface DeviceType {
|
|
/** The type of the device is unknown. */
|
|
int UNKNOWN = 0;
|
|
/** The device is a phone. */
|
|
int PHONE = 1;
|
|
/** The device is a tablet. */
|
|
int TABLET = 2;
|
|
/** The device is a display. */
|
|
int DISPLAY = 3;
|
|
/** The device is a laptop. */
|
|
int LAPTOP = 4;
|
|
/** The device is a TV. */
|
|
int TV = 5;
|
|
/** The device is a watch. */
|
|
int WATCH = 6;
|
|
}
|
|
|
|
private final String mDeviceId;
|
|
private final byte[] mSalt;
|
|
private final byte[] mSecretId;
|
|
private final byte[] mEncryptedIdentity;
|
|
private final int mDeviceType;
|
|
private final String mDeviceImageUrl;
|
|
private final long mDiscoveryTimestampMillis;
|
|
private final List<DataElement> mExtendedProperties;
|
|
|
|
/**
|
|
* The id of the device.
|
|
*
|
|
* <p>This id is not a hardware id. It may rotate based on the remote device's broadcasts.
|
|
*/
|
|
@NonNull
|
|
public String getDeviceId() {
|
|
return mDeviceId;
|
|
}
|
|
|
|
/**
|
|
* Returns the salt used when presence device is discovered.
|
|
*/
|
|
@NonNull
|
|
public byte[] getSalt() {
|
|
return mSalt;
|
|
}
|
|
|
|
/**
|
|
* Returns the secret used when presence device is discovered.
|
|
*/
|
|
@NonNull
|
|
public byte[] getSecretId() {
|
|
return mSecretId;
|
|
}
|
|
|
|
/**
|
|
* Returns the encrypted identity used when presence device is discovered.
|
|
*/
|
|
@NonNull
|
|
public byte[] getEncryptedIdentity() {
|
|
return mEncryptedIdentity;
|
|
}
|
|
|
|
/** The type of the device. */
|
|
@DeviceType
|
|
public int getDeviceType() {
|
|
return mDeviceType;
|
|
}
|
|
|
|
/** An image URL representing the device. */
|
|
@Nullable
|
|
public String getDeviceImageUrl() {
|
|
return mDeviceImageUrl;
|
|
}
|
|
|
|
/** The timestamp (since boot) when the device is discovered. */
|
|
public long getDiscoveryTimestampMillis() {
|
|
return mDiscoveryTimestampMillis;
|
|
}
|
|
|
|
/**
|
|
* The extended properties of the device.
|
|
*/
|
|
@NonNull
|
|
public List<DataElement> getExtendedProperties() {
|
|
return mExtendedProperties;
|
|
}
|
|
|
|
/**
|
|
* This can only be hidden because this is the System API,
|
|
* which cannot be changed in T timeline.
|
|
*
|
|
* @hide
|
|
*/
|
|
@Override
|
|
public boolean equals(Object other) {
|
|
if (other instanceof PresenceDevice) {
|
|
PresenceDevice otherDevice = (PresenceDevice) other;
|
|
if (super.equals(otherDevice)) {
|
|
return Arrays.equals(mSalt, otherDevice.mSalt)
|
|
&& Arrays.equals(mSecretId, otherDevice.mSecretId)
|
|
&& Arrays.equals(mEncryptedIdentity, otherDevice.mEncryptedIdentity)
|
|
&& Objects.equals(mDeviceId, otherDevice.mDeviceId)
|
|
&& mDeviceType == otherDevice.mDeviceType
|
|
&& Objects.equals(mDeviceImageUrl, otherDevice.mDeviceImageUrl)
|
|
&& mDiscoveryTimestampMillis == otherDevice.mDiscoveryTimestampMillis
|
|
&& Objects.equals(mExtendedProperties, otherDevice.mExtendedProperties);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This can only be hidden because this is the System API,
|
|
* which cannot be changed in T timeline.
|
|
*
|
|
* @hide
|
|
*
|
|
* @return The unique hash value of the {@link PresenceDevice}
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(
|
|
getName(),
|
|
getMediums(),
|
|
getRssi(),
|
|
Arrays.hashCode(mSalt),
|
|
Arrays.hashCode(mSecretId),
|
|
Arrays.hashCode(mEncryptedIdentity),
|
|
mDeviceId,
|
|
mDeviceType,
|
|
mDeviceImageUrl,
|
|
mDiscoveryTimestampMillis,
|
|
mExtendedProperties);
|
|
}
|
|
|
|
private PresenceDevice(String deviceName, List<Integer> mMediums, int rssi, String deviceId,
|
|
byte[] salt, byte[] secretId, byte[] encryptedIdentity, int deviceType,
|
|
String deviceImageUrl, long discoveryTimestampMillis,
|
|
List<DataElement> extendedProperties) {
|
|
super(deviceName, mMediums, rssi);
|
|
mDeviceId = deviceId;
|
|
mSalt = salt;
|
|
mSecretId = secretId;
|
|
mEncryptedIdentity = encryptedIdentity;
|
|
mDeviceType = deviceType;
|
|
mDeviceImageUrl = deviceImageUrl;
|
|
mDiscoveryTimestampMillis = discoveryTimestampMillis;
|
|
mExtendedProperties = extendedProperties;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
|
String name = getName();
|
|
dest.writeInt(name == null ? 0 : 1);
|
|
if (name != null) {
|
|
dest.writeString(name);
|
|
}
|
|
List<Integer> mediums = getMediums();
|
|
dest.writeInt(mediums.size());
|
|
for (int medium : mediums) {
|
|
dest.writeInt(medium);
|
|
}
|
|
dest.writeInt(getRssi());
|
|
dest.writeInt(mSalt.length);
|
|
dest.writeByteArray(mSalt);
|
|
dest.writeInt(mSecretId.length);
|
|
dest.writeByteArray(mSecretId);
|
|
dest.writeInt(mEncryptedIdentity.length);
|
|
dest.writeByteArray(mEncryptedIdentity);
|
|
dest.writeString(mDeviceId);
|
|
dest.writeInt(mDeviceType);
|
|
dest.writeInt(mDeviceImageUrl == null ? 0 : 1);
|
|
if (mDeviceImageUrl != null) {
|
|
dest.writeString(mDeviceImageUrl);
|
|
}
|
|
dest.writeLong(mDiscoveryTimestampMillis);
|
|
dest.writeInt(mExtendedProperties.size());
|
|
for (DataElement dataElement : mExtendedProperties) {
|
|
dest.writeParcelable(dataElement, 0);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@NonNull
|
|
public static final Creator<PresenceDevice> CREATOR = new Creator<PresenceDevice>() {
|
|
@Override
|
|
public PresenceDevice createFromParcel(Parcel in) {
|
|
String name = null;
|
|
if (in.readInt() == 1) {
|
|
name = in.readString();
|
|
}
|
|
int size = in.readInt();
|
|
List<Integer> mediums = new ArrayList<>();
|
|
for (int i = 0; i < size; i++) {
|
|
mediums.add(in.readInt());
|
|
}
|
|
int rssi = in.readInt();
|
|
byte[] salt = new byte[in.readInt()];
|
|
in.readByteArray(salt);
|
|
byte[] secretId = new byte[in.readInt()];
|
|
in.readByteArray(secretId);
|
|
byte[] encryptedIdentity = new byte[in.readInt()];
|
|
in.readByteArray(encryptedIdentity);
|
|
String deviceId = in.readString();
|
|
int deviceType = in.readInt();
|
|
String deviceImageUrl = null;
|
|
if (in.readInt() == 1) {
|
|
deviceImageUrl = in.readString();
|
|
}
|
|
long discoveryTimeMillis = in.readLong();
|
|
int dataElementSize = in.readInt();
|
|
List<DataElement> dataElements = new ArrayList<>();
|
|
for (int i = 0; i < dataElementSize; i++) {
|
|
dataElements.add(
|
|
in.readParcelable(DataElement.class.getClassLoader(), DataElement.class));
|
|
}
|
|
Builder builder = new Builder(deviceId, salt, secretId, encryptedIdentity)
|
|
.setName(name)
|
|
.setRssi(rssi)
|
|
.setDeviceType(deviceType)
|
|
.setDeviceImageUrl(deviceImageUrl)
|
|
.setDiscoveryTimestampMillis(discoveryTimeMillis);
|
|
for (int i = 0; i < mediums.size(); i++) {
|
|
builder.addMedium(mediums.get(i));
|
|
}
|
|
for (int i = 0; i < dataElements.size(); i++) {
|
|
builder.addExtendedProperty(dataElements.get(i));
|
|
}
|
|
return builder.build();
|
|
}
|
|
|
|
@Override
|
|
public PresenceDevice[] newArray(int size) {
|
|
return new PresenceDevice[size];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Builder class for {@link PresenceDevice}.
|
|
*/
|
|
public static final class Builder {
|
|
|
|
private final List<DataElement> mExtendedProperties;
|
|
private final List<Integer> mMediums;
|
|
private final String mDeviceId;
|
|
private final byte[] mSalt;
|
|
private final byte[] mSecretId;
|
|
private final byte[] mEncryptedIdentity;
|
|
|
|
private String mName;
|
|
private int mRssi;
|
|
private int mDeviceType;
|
|
private String mDeviceImageUrl;
|
|
private long mDiscoveryTimestampMillis;
|
|
|
|
/**
|
|
* Constructs a {@link Builder}.
|
|
*
|
|
* @param deviceId the identifier on the discovered Presence device
|
|
* @param salt a random salt used in the beacon from the Presence device.
|
|
* @param secretId a secret identifier used in the beacon from the Presence device.
|
|
* @param encryptedIdentity the identity associated with the Presence device.
|
|
*/
|
|
public Builder(@NonNull String deviceId, @NonNull byte[] salt, @NonNull byte[] secretId,
|
|
@NonNull byte[] encryptedIdentity) {
|
|
Objects.requireNonNull(deviceId);
|
|
Objects.requireNonNull(salt);
|
|
Objects.requireNonNull(secretId);
|
|
Objects.requireNonNull(encryptedIdentity);
|
|
|
|
mDeviceId = deviceId;
|
|
mSalt = salt;
|
|
mSecretId = secretId;
|
|
mEncryptedIdentity = encryptedIdentity;
|
|
mMediums = new ArrayList<>();
|
|
mExtendedProperties = new ArrayList<>();
|
|
mRssi = -127;
|
|
}
|
|
|
|
/**
|
|
* Sets the name of the Presence device.
|
|
*
|
|
* @param name Name of the Presence. Can be {@code null} if there is no name.
|
|
*/
|
|
@NonNull
|
|
public Builder setName(@Nullable String name) {
|
|
mName = name;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Adds the medium over which the Presence device is discovered.
|
|
*
|
|
* @param medium The {@link Medium} over which the device is discovered.
|
|
*/
|
|
@NonNull
|
|
public Builder addMedium(@Medium int medium) {
|
|
mMediums.add(medium);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the RSSI on the discovered Presence device.
|
|
*
|
|
* @param rssi The received signal strength in dBm.
|
|
*/
|
|
@NonNull
|
|
public Builder setRssi(int rssi) {
|
|
mRssi = rssi;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the type of discovered Presence device.
|
|
*
|
|
* @param deviceType Type of the Presence device.
|
|
*/
|
|
@NonNull
|
|
public Builder setDeviceType(@DeviceType int deviceType) {
|
|
mDeviceType = deviceType;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the image url of the discovered Presence device.
|
|
*
|
|
* @param deviceImageUrl Url of the image for the Presence device.
|
|
*/
|
|
@NonNull
|
|
public Builder setDeviceImageUrl(@Nullable String deviceImageUrl) {
|
|
mDeviceImageUrl = deviceImageUrl;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets discovery timestamp, the clock is based on elapsed time.
|
|
*
|
|
* @param discoveryTimestampMillis Timestamp when the presence device is discovered.
|
|
*/
|
|
@NonNull
|
|
public Builder setDiscoveryTimestampMillis(long discoveryTimestampMillis) {
|
|
mDiscoveryTimestampMillis = discoveryTimestampMillis;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Adds an extended property of the discovered presence device.
|
|
*
|
|
* @param dataElement Data element of the extended property.
|
|
*/
|
|
@NonNull
|
|
public Builder addExtendedProperty(@NonNull DataElement dataElement) {
|
|
Objects.requireNonNull(dataElement);
|
|
mExtendedProperties.add(dataElement);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Builds a Presence device.
|
|
*/
|
|
@NonNull
|
|
public PresenceDevice build() {
|
|
return new PresenceDevice(mName, mMediums, mRssi, mDeviceId,
|
|
mSalt, mSecretId, mEncryptedIdentity,
|
|
mDeviceType,
|
|
mDeviceImageUrl,
|
|
mDiscoveryTimestampMillis, mExtendedProperties);
|
|
}
|
|
}
|
|
}
|