blob: 3443b53885ba988fcb14a559ce0ce6692b0f0bac [file] [log] [blame]
/*
* 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 com.android.server.nearby.common.ble;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
/** Test for Bluetooth LE {@link BleSighting}. */
public class BleSightingTest {
private static final String DEVICE_NAME = "device1";
private static final String OTHER_DEVICE_NAME = "device2";
private static final long TIME_EPOCH_MILLIS = 123456;
private static final long OTHER_TIME_EPOCH_MILLIS = 456789;
private static final int RSSI = 1;
private static final int OTHER_RSSI = 2;
private final BluetoothDevice mBluetoothDevice1 =
BluetoothAdapter.getDefaultAdapter().getRemoteDevice("00:11:22:33:44:55");
private final BluetoothDevice mBluetoothDevice2 =
BluetoothAdapter.getDefaultAdapter().getRemoteDevice("AA:BB:CC:DD:EE:FF");
@Test
public void testEquals() {
BleSighting sighting =
buildBleSighting(mBluetoothDevice1, DEVICE_NAME, TIME_EPOCH_MILLIS, RSSI);
BleSighting sighting2 =
buildBleSighting(mBluetoothDevice1, DEVICE_NAME, TIME_EPOCH_MILLIS, RSSI);
assertThat(sighting.equals(sighting2)).isTrue();
assertThat(sighting2.equals(sighting)).isTrue();
assertThat(sighting.hashCode()).isEqualTo(sighting2.hashCode());
// Transitive property.
BleSighting sighting3 =
buildBleSighting(mBluetoothDevice1, DEVICE_NAME, TIME_EPOCH_MILLIS, RSSI);
assertThat(sighting2.equals(sighting3)).isTrue();
assertThat(sighting.equals(sighting3)).isTrue();
// Set different values for each field, one at a time.
sighting2 = buildBleSighting(mBluetoothDevice2, DEVICE_NAME, TIME_EPOCH_MILLIS, RSSI);
assertSightingsNotEquals(sighting, sighting2);
sighting2 = buildBleSighting(mBluetoothDevice1, OTHER_DEVICE_NAME, TIME_EPOCH_MILLIS, RSSI);
assertSightingsNotEquals(sighting, sighting2);
sighting2 = buildBleSighting(mBluetoothDevice1, DEVICE_NAME, OTHER_TIME_EPOCH_MILLIS, RSSI);
assertSightingsNotEquals(sighting, sighting2);
sighting2 = buildBleSighting(mBluetoothDevice1, DEVICE_NAME, TIME_EPOCH_MILLIS, OTHER_RSSI);
assertSightingsNotEquals(sighting, sighting2);
}
@Test
public void getNormalizedRSSI_usingNearbyRssiOffset_getCorrectValue() {
BleSighting sighting =
buildBleSighting(mBluetoothDevice1, DEVICE_NAME, TIME_EPOCH_MILLIS, RSSI);
int defaultRssiOffset = 3;
assertThat(sighting.getNormalizedRSSI()).isEqualTo(RSSI + defaultRssiOffset);
}
@Test
public void testFields() {
BleSighting sighting =
buildBleSighting(mBluetoothDevice1, DEVICE_NAME, TIME_EPOCH_MILLIS, RSSI);
assertThat(byteString(sighting.getBleRecordBytes()))
.isEqualTo("080964657669636531");
assertThat(sighting.getRssi()).isEqualTo(RSSI);
assertThat(sighting.getTimestampMillis()).isEqualTo(TIME_EPOCH_MILLIS);
assertThat(sighting.getTimestampNanos())
.isEqualTo(TimeUnit.MILLISECONDS.toNanos(TIME_EPOCH_MILLIS));
assertThat(sighting.toString()).isEqualTo(
"BleSighting{device=" + mBluetoothDevice1 + ","
+ " bleRecord=BleRecord [advertiseFlags=-1,"
+ " serviceUuids=[],"
+ " manufacturerSpecificData={}, serviceData={},"
+ " txPowerLevel=-2147483648,"
+ " deviceName=device1],"
+ " rssi=1,"
+ " timestampNanos=123456000000}");
}
@Test
public void testParcelable() {
BleSighting sighting =
buildBleSighting(mBluetoothDevice1, DEVICE_NAME, TIME_EPOCH_MILLIS, RSSI);
Parcel dest = Parcel.obtain();
sighting.writeToParcel(dest, 0);
dest.setDataPosition(0);
assertThat(sighting.getRssi()).isEqualTo(RSSI);
}
@Test
public void testCreatorNewArray() {
BleSighting[] sightings =
BleSighting.CREATOR.newArray(2);
assertThat(sightings.length).isEqualTo(2);
}
private static String byteString(byte[] bytes) {
if (bytes == null) {
return "[null]";
} else {
final char[] hexArray = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for (int i = 0; i < bytes.length; i++) {
int v = bytes[i] & 0xFF;
hexChars[i * 2] = hexArray[v >>> 4];
hexChars[i * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}
/** Builds a BleSighting instance which will correctly match filters by device name. */
private static BleSighting buildBleSighting(
BluetoothDevice bluetoothDevice, String deviceName, long timeEpochMillis, int rssi) {
byte[] nameBytes = deviceName.getBytes(UTF_8);
byte[] bleRecordBytes = new byte[nameBytes.length + 2];
bleRecordBytes[0] = (byte) (nameBytes.length + 1);
bleRecordBytes[1] = 0x09; // Value of private BleRecord.DATA_TYPE_LOCAL_NAME_COMPLETE;
System.arraycopy(nameBytes, 0, bleRecordBytes, 2, nameBytes.length);
return new BleSighting(bluetoothDevice, bleRecordBytes,
rssi, TimeUnit.MILLISECONDS.toNanos(timeEpochMillis));
}
private static void assertSightingsNotEquals(BleSighting sighting1, BleSighting sighting2) {
assertThat(sighting1.equals(sighting2)).isFalse();
assertThat(sighting1.hashCode()).isNotEqualTo(sighting2.hashCode());
}
}