• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.nearby.cts;
18 
19 import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
20 import static android.Manifest.permission.READ_DEVICE_CONFIG;
21 import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
22 import static android.nearby.PresenceCredential.IDENTITY_TYPE_PRIVATE;
23 import static android.nearby.ScanCallback.ERROR_UNSUPPORTED;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import static org.junit.Assert.assertThrows;
28 
29 import android.app.UiAutomation;
30 import android.bluetooth.BluetoothAdapter;
31 import android.bluetooth.BluetoothManager;
32 import android.bluetooth.cts.BTAdapterUtils;
33 import android.content.Context;
34 import android.nearby.BroadcastCallback;
35 import android.nearby.BroadcastRequest;
36 import android.nearby.NearbyDevice;
37 import android.nearby.NearbyManager;
38 import android.nearby.OffloadCapability;
39 import android.nearby.PresenceBroadcastRequest;
40 import android.nearby.PresenceDevice;
41 import android.nearby.PrivateCredential;
42 import android.nearby.ScanCallback;
43 import android.nearby.ScanRequest;
44 import android.os.Build;
45 import android.provider.DeviceConfig;
46 
47 import androidx.annotation.NonNull;
48 import androidx.annotation.RequiresApi;
49 import androidx.test.InstrumentationRegistry;
50 import androidx.test.ext.junit.runners.AndroidJUnit4;
51 import androidx.test.filters.SdkSuppress;
52 
53 import com.android.modules.utils.build.SdkLevel;
54 
55 import org.junit.Before;
56 import org.junit.Test;
57 import org.junit.runner.RunWith;
58 
59 import java.util.Collections;
60 import java.util.concurrent.CountDownLatch;
61 import java.util.concurrent.Executor;
62 import java.util.concurrent.Executors;
63 import java.util.concurrent.TimeUnit;
64 import java.util.function.Consumer;
65 
66 /**
67  * TODO(b/215435939) This class doesn't include any logic yet. Because SELinux denies access to
68  * NearbyManager.
69  */
70 @RunWith(AndroidJUnit4.class)
71 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
72 public class NearbyManagerTest {
73     private static final byte[] SALT = new byte[]{1, 2};
74     private static final byte[] SECRET_ID = new byte[]{1, 2, 3, 4};
75     private static final byte[] META_DATA_ENCRYPTION_KEY = new byte[14];
76     private static final byte[] AUTHENTICITY_KEY = new byte[]{0, 1, 1, 1};
77     private static final String DEVICE_NAME = "test_device";
78     private static final int BLE_MEDIUM = 1;
79 
80     private Context mContext;
81     private NearbyManager mNearbyManager;
82     private UiAutomation mUiAutomation =
83             InstrumentationRegistry.getInstrumentation().getUiAutomation();
84 
85     private ScanRequest mScanRequest = new ScanRequest.Builder()
86             .setScanType(ScanRequest.SCAN_TYPE_FAST_PAIR)
87             .setScanMode(ScanRequest.SCAN_MODE_LOW_LATENCY)
88             .setBleEnabled(true)
89             .build();
90     private PresenceDevice.Builder mBuilder =
91             new PresenceDevice.Builder("deviceId", SALT, SECRET_ID, META_DATA_ENCRYPTION_KEY);
92 
93     private  ScanCallback mScanCallback = new ScanCallback() {
94         @Override
95         public void onDiscovered(@NonNull NearbyDevice device) {
96         }
97 
98         @Override
99         public void onUpdated(@NonNull NearbyDevice device) {
100         }
101 
102         @Override
103         public void onLost(@NonNull NearbyDevice device) {
104         }
105 
106         @Override
107         public void onError(int errorCode) {
108         }
109     };
110 
111     private static final Executor EXECUTOR = Executors.newSingleThreadExecutor();
112 
113     @Before
setUp()114     public void setUp() {
115         mUiAutomation.adoptShellPermissionIdentity(READ_DEVICE_CONFIG, WRITE_DEVICE_CONFIG,
116                 BLUETOOTH_PRIVILEGED);
117         String nameSpace = SdkLevel.isAtLeastU() ? DeviceConfig.NAMESPACE_NEARBY
118                 : DeviceConfig.NAMESPACE_TETHERING;
119         DeviceConfig.setProperty(nameSpace,
120                 "nearby_enable_presence_broadcast_legacy",
121                 "true", false);
122 
123         mContext = InstrumentationRegistry.getContext();
124         mNearbyManager = mContext.getSystemService(NearbyManager.class);
125 
126         enableBluetooth();
127     }
128 
129     @Test
130     @SdkSuppress(minSdkVersion = 32, codeName = "T")
test_startAndStopScan()131     public void test_startAndStopScan() {
132         mNearbyManager.startScan(mScanRequest, EXECUTOR, mScanCallback);
133         mNearbyManager.stopScan(mScanCallback);
134     }
135 
136     @Test
137     @SdkSuppress(minSdkVersion = 32, codeName = "T")
test_startScan_noPrivilegedPermission()138     public void test_startScan_noPrivilegedPermission() {
139         mUiAutomation.dropShellPermissionIdentity();
140         assertThrows(SecurityException.class, () -> mNearbyManager
141                 .startScan(mScanRequest, EXECUTOR, mScanCallback));
142     }
143 
144     @Test
145     @SdkSuppress(minSdkVersion = 32, codeName = "T")
test_stopScan_noPrivilegedPermission()146     public void test_stopScan_noPrivilegedPermission() {
147         mNearbyManager.startScan(mScanRequest, EXECUTOR, mScanCallback);
148         mUiAutomation.dropShellPermissionIdentity();
149         assertThrows(SecurityException.class, () -> mNearbyManager.stopScan(mScanCallback));
150     }
151 
152     @Test
153     @SdkSuppress(minSdkVersion = 32, codeName = "T")
testStartStopBroadcast()154     public void testStartStopBroadcast() throws InterruptedException {
155         PrivateCredential credential = new PrivateCredential.Builder(SECRET_ID, AUTHENTICITY_KEY,
156                 META_DATA_ENCRYPTION_KEY, DEVICE_NAME)
157                 .setIdentityType(IDENTITY_TYPE_PRIVATE)
158                 .build();
159         BroadcastRequest broadcastRequest =
160                 new PresenceBroadcastRequest.Builder(
161                         Collections.singletonList(BLE_MEDIUM), SALT, credential)
162                         .addAction(123)
163                         .build();
164 
165         CountDownLatch latch = new CountDownLatch(1);
166         BroadcastCallback callback = status -> {
167             latch.countDown();
168             assertThat(status).isEqualTo(BroadcastCallback.STATUS_OK);
169         };
170         mNearbyManager.startBroadcast(broadcastRequest, Executors.newSingleThreadExecutor(),
171                 callback);
172         latch.await(10, TimeUnit.SECONDS);
173         mNearbyManager.stopBroadcast(callback);
174     }
175 
176     @Test
177     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
queryOffloadScanSupport()178     public void queryOffloadScanSupport() {
179         OffloadCallback callback = new OffloadCallback();
180         mNearbyManager.queryOffloadCapability(EXECUTOR, callback);
181     }
182 
183     @Test
184     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
testAllCallbackMethodsExits()185     public void testAllCallbackMethodsExits() {
186         mScanCallback.onDiscovered(mBuilder.setRssi(-10).build());
187         mScanCallback.onUpdated(mBuilder.setRssi(-5).build());
188         mScanCallback.onLost(mBuilder.setRssi(-8).build());
189         mScanCallback.onError(ERROR_UNSUPPORTED);
190     }
191 
enableBluetooth()192     private void enableBluetooth() {
193         BluetoothManager manager = mContext.getSystemService(BluetoothManager.class);
194         BluetoothAdapter bluetoothAdapter = manager.getAdapter();
195         if (!bluetoothAdapter.isEnabled()) {
196             assertThat(BTAdapterUtils.enableAdapter(bluetoothAdapter, mContext)).isTrue();
197         }
198     }
199 
200     private static class OffloadCallback implements Consumer<OffloadCapability> {
201         @Override
accept(OffloadCapability aBoolean)202         public void accept(OffloadCapability aBoolean) {
203             // no-op for now
204         }
205     }
206 }
207