• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 com.android.cts.deviceowner;
18 
19 import static com.google.common.truth.Truth.assertWithMessage;
20 
21 import android.bluetooth.BluetoothAdapter;
22 import android.content.ComponentName;
23 import android.content.pm.PackageManager;
24 import android.os.SystemClock;
25 import android.os.UserManager;
26 import android.util.DebugUtils;
27 import android.util.Log;
28 
29 import com.android.bedstead.nene.TestApis;
30 import com.android.internal.util.ArrayUtils;
31 
32 /**
33  * Test interaction between {@link UserManager#DISALLOW_BLUETOOTH} user restriction and the state
34  * of Bluetooth.
35  */
36 public class BluetoothRestrictionTest extends BaseDeviceOwnerTest {
37 
38     private static final String TAG = BluetoothRestrictionTest.class.getSimpleName();
39     private static final boolean VERBOSE = false;
40 
41     private static final int DISABLE_TIMEOUT_MS = 8000;   // ms timeout for BT disable
42     private static final int ENABLE_TIMEOUT_MS = 20_000;  // ms timeout for BT enable
43     private static final int POLL_TIME_MS = 400;          // ms to poll BT state
44     private static final int CHECK_WAIT_TIME_MS = 1_000;  // ms to wait before enable/disable
45     private static final int COMPONENT_STATE_TIMEOUT_MS = 10_000;
46     private static final String OPP_LAUNCHER_CLASS =
47             "com.android.bluetooth.opp.BluetoothOppLauncherActivity";
48     private BluetoothAdapter mBluetoothAdapter;
49     private PackageManager mPackageManager;
50 
51     @Override
setUp()52     protected void setUp() throws Exception {
53         super.setUp();
54 
55         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
56         if (mBluetoothAdapter == null) {
57             Log.w(TAG, "No Bluetooth adapter");
58         } else {
59             int state = mBluetoothAdapter.getConnectionState();
60             Log.d(TAG, "BluetoothAdapter: " + mBluetoothAdapter
61                     + " enabled: " + mBluetoothAdapter.isEnabled()
62                     + " state: "  + state + " (" + btStateToString(state) + ")");
63         }
64         mPackageManager = mContext.getPackageManager();
65     }
66 
67     @Override
tearDown()68     protected void tearDown() throws Exception {
69         super.tearDown();
70 
71         clearBluetoothRestriction();
72         enable();
73     }
74 
testEnableBluetoothFailsWhenDisallowed()75     public void testEnableBluetoothFailsWhenDisallowed() throws Exception {
76         if (mBluetoothAdapter == null) {
77             return;
78         }
79 
80         // Make sure Bluetooth is initially disabled.
81         disable();
82 
83         // Add the user restriction disallowing Bluetooth.
84         addBluetoothRestriction();
85 
86         // Check that enabling Bluetooth fails.
87         assertBluetoothAdapterDisabled();
88     }
89 
testBluetoothGetsDisabledAfterRestrictionSet()90     public void testBluetoothGetsDisabledAfterRestrictionSet() throws Exception {
91         if (mBluetoothAdapter == null) {
92             return;
93         }
94 
95         // Make sure Bluetooth is enabled first.
96         enable();
97 
98         // Add the user restriction to disallow Bluetooth.
99         addBluetoothRestriction();
100 
101         // Check that Bluetooth gets disabled as a result.
102         assertDisabledAfterTimeout();
103     }
104 
testEnableBluetoothSucceedsAfterRestrictionRemoved()105     public void testEnableBluetoothSucceedsAfterRestrictionRemoved() throws Exception {
106         if (mBluetoothAdapter == null) {
107             return;
108         }
109 
110         // Add the user restriction.
111         addBluetoothRestriction();
112 
113         // Make sure Bluetooth is disabled.
114         assertDisabledAfterTimeout();
115 
116         // Remove the user restriction.
117         clearBluetoothRestriction();
118 
119         // Check that it is possible to enable Bluetooth again once the restriction has been
120         // removed.
121         enable();
122     }
123 
124     /**
125      * Tests that BluetoothOppLauncherActivity gets disabled when Bluetooth itself or Bluetooth
126      * sharing is disallowed.
127      *
128      * <p> It also checks the state of the activity is set back to default if Bluetooth is not
129      * disallowed anymore.
130      */
testOppDisabledWhenRestrictionSet()131     public void testOppDisabledWhenRestrictionSet() throws Exception {
132         if (mBluetoothAdapter == null || UserManager.isHeadlessSystemUserMode()) {
133             return;
134         }
135 
136         ComponentName oppLauncherComponent =
137                 new ComponentName(TestApis.bluetooth().findPackageName(), OPP_LAUNCHER_CLASS);
138 
139         // First verify DISALLOW_BLUETOOTH.
140         testOppDisabledWhenRestrictionSet(UserManager.DISALLOW_BLUETOOTH,
141                 oppLauncherComponent);
142 
143         // Verify DISALLOW_BLUETOOTH_SHARING which leaves bluetooth workable but the sharing
144         // component should be disabled.
145         testOppDisabledWhenRestrictionSet(
146                 UserManager.DISALLOW_BLUETOOTH_SHARING, oppLauncherComponent);
147     }
148 
149     /** Verifies that a given restriction disables the bluetooth sharing component. */
testOppDisabledWhenRestrictionSet(String restriction, ComponentName oppLauncherComponent)150     private void testOppDisabledWhenRestrictionSet(String restriction,
151             ComponentName oppLauncherComponent) {
152         // Add the user restriction.
153         addUserRestriction(restriction);
154 
155         // The BluetoothOppLauncherActivity's component should be disabled.
156         assertComponentStateAfterTimeout(
157                 oppLauncherComponent, new int[] {PackageManager.COMPONENT_ENABLED_STATE_DISABLED});
158 
159         // Remove the user restriction.
160         clearUserRestriction(restriction);
161 
162         // The BluetoothOppLauncherActivity's component should be enabled or default.
163         assertComponentStateAfterTimeout(
164                 oppLauncherComponent, new int[] {PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
165                     PackageManager.COMPONENT_ENABLED_STATE_DEFAULT});
166     }
167 
168     /** Helper to turn BT off.
169      * This method will either fail on an assert, or return with BT turned off.
170      * Behavior of getState() and isEnabled() are validated along the way.
171      */
disable()172     private void disable() {
173         // Can't disable a bluetooth adapter that does not exist.
174         if (mBluetoothAdapter == null) {
175             Log.v(TAG, "disable(): ignoring as there is no BT adapter");
176             return;
177         }
178 
179         sleep(CHECK_WAIT_TIME_MS);
180         int state = mBluetoothAdapter.getState();
181         Log.v(TAG, "disable(): Current state: " + btStateToString(state));
182         if (state == BluetoothAdapter.STATE_OFF) {
183             assertBluetoothAdapterDisabled();
184             return;
185         }
186 
187         assertBluetoothAdapterState(BluetoothAdapter.STATE_ON);
188         assertBluetoothAdapterEnabled();
189         Log.i(TAG, "Disabling BT");
190         boolean result = mBluetoothAdapter.disable();
191         Log.v(TAG, "Result: " + result);
192         assertDisabledAfterTimeout();
193     }
194 
195     /**
196      * Helper method which waits for Bluetooth to be disabled. Fails if it doesn't happen in a
197      * given time.
198      */
assertDisabledAfterTimeout()199     private void assertDisabledAfterTimeout() {
200         boolean turningOff = false;
201         long timeout = SystemClock.elapsedRealtime() + DISABLE_TIMEOUT_MS;
202         Log.d(TAG, "Waiting up to " + timeout + " ms for STATE_OFF and disabled");
203         int state = Integer.MIN_VALUE;
204         while (SystemClock.elapsedRealtime() < timeout) {
205             state = mBluetoothAdapter.getState();
206             Log.v(TAG, "State: " + btStateToString(state) + " turningOff: " + turningOff);
207             switch (state) {
208                 case BluetoothAdapter.STATE_OFF:
209                     Log.d(TAG, "STATE_OFF received, check that adapter is disabled");
210                     assertBluetoothAdapterDisabled();
211                     return;
212                 default:
213                     if (state != BluetoothAdapter.STATE_ON || turningOff) {
214                         assertBluetoothAdapterState(BluetoothAdapter.STATE_TURNING_OFF);
215                         turningOff = true;
216                     }
217                     break;
218             }
219             sleep(POLL_TIME_MS);
220         }
221         fail("disable() timeout - BT adapter state is " + btStateToString(state)
222                 + " instead of STATE_OFF");
223     }
224 
assertComponentStateAfterTimeout(ComponentName component, int[] expectedState)225     private void assertComponentStateAfterTimeout(ComponentName component, int[] expectedState) {
226         final long timeout = SystemClock.elapsedRealtime() + COMPONENT_STATE_TIMEOUT_MS;
227         int state = -1;
228         while (SystemClock.elapsedRealtime() < timeout) {
229             state = mPackageManager.getComponentEnabledSetting(component);
230             if (ArrayUtils.contains(expectedState, state)) {
231                 // Success, waiting for component to be fully turned on/off
232                 sleep(CHECK_WAIT_TIME_MS);
233                 return;
234             }
235             sleep(POLL_TIME_MS);
236         }
237         fail("The state of " + component + " should have been "
238                 + ArrayUtils.deepToString(expectedState) + ", it but was "
239                 + state + " after timeout.");
240     }
241 
242     /** Helper to turn BT on.
243      * This method will either fail on an assert, or return with BT turned on.
244      * Behavior of getState() and isEnabled() are validated along the way.
245      */
enable()246     private void enable() {
247         // Can't enable a bluetooth adapter that does not exist.
248         if (mBluetoothAdapter == null) {
249             Log.v(TAG, "enable(): ignoring as there is no BT adapter");
250             return;
251         }
252 
253         sleep(CHECK_WAIT_TIME_MS);
254         int state = mBluetoothAdapter.getState();
255         Log.v(TAG, "enable(): Current state: " + btStateToString(state));
256 
257         if (state == BluetoothAdapter.STATE_ON) {
258             assertBluetoothAdapterEnabled();
259             return;
260         }
261 
262         assertBluetoothAdapterState(BluetoothAdapter.STATE_OFF);
263         assertBluetoothAdapterDisabled();
264         Log.i(TAG, "Enabling BT");
265         boolean result = mBluetoothAdapter.enable();
266         Log.v(TAG, "Result: " + result);
267         assertEnabledAfterTimeout();
268     }
269 
270     /**
271      * Helper method which waits for Bluetooth to be enabled. Fails if it doesn't happen in a given
272      * time.
273      */
assertEnabledAfterTimeout()274     private void assertEnabledAfterTimeout() {
275         boolean turningOn = false;
276         long timeout = SystemClock.elapsedRealtime() + ENABLE_TIMEOUT_MS;
277         Log.d(TAG, "Waiting up to " + timeout + " ms for STATE_ON and enabled");
278         int state = Integer.MIN_VALUE;
279         while (SystemClock.elapsedRealtime() < timeout) {
280             state = mBluetoothAdapter.getState();
281             Log.v(TAG, "State: " + btStateToString(state) + " turningOn: " + turningOn);
282             switch (state) {
283                 case BluetoothAdapter.STATE_ON:
284                     Log.d(TAG, "STATE_ON received, check that adapter is enabled");
285                     assertBluetoothAdapterEnabled();
286                     return;
287                 default:
288                     if (state != BluetoothAdapter.STATE_OFF || turningOn) {
289                         assertBluetoothAdapterState(BluetoothAdapter.STATE_TURNING_ON);
290                         turningOn = true;
291                     }
292                     break;
293             }
294             sleep(POLL_TIME_MS);
295         }
296         fail("enable() timeout - BT adapter state is " + btStateToString(state)
297                 + " instead of STATE_ON");
298     }
299 
assertBluetoothAdapterEnabled()300     private void assertBluetoothAdapterEnabled() {
301         assertWithMessage("mBluetoothAdapter.isEnabled()").that(mBluetoothAdapter.isEnabled())
302                 .isTrue();
303     }
304 
assertBluetoothAdapterDisabled()305     private void assertBluetoothAdapterDisabled() {
306         assertWithMessage("mBluetoothAdapter.isEnabled()").that(mBluetoothAdapter.isEnabled())
307                 .isFalse();
308     }
309 
assertBluetoothAdapterState(int expectedState)310     private void assertBluetoothAdapterState(int expectedState) {
311         int actualState = mBluetoothAdapter.getState();
312         assertWithMessage("mBluetoothAdapter.getState() (where %s is %s and %s is %s)",
313                 expectedState, btStateToString(expectedState),
314                 actualState, btStateToString(actualState))
315                         .that(actualState).isEqualTo(expectedState);
316     }
317 
addBluetoothRestriction()318     private void addBluetoothRestriction() {
319         addUserRestriction(UserManager.DISALLOW_BLUETOOTH);
320     }
321 
clearBluetoothRestriction()322     private void clearBluetoothRestriction() {
323         clearUserRestriction(UserManager.DISALLOW_BLUETOOTH);
324     }
325 
addUserRestriction(String restriction)326     private void addUserRestriction(String restriction) {
327         Log.d(TAG, "Adding " + restriction + " using " + mDevicePolicyManager);
328         mDevicePolicyManager.addUserRestriction(getWho(), restriction);
329     }
330 
clearUserRestriction(String restriction)331     private void clearUserRestriction(String restriction) {
332         Log.d(TAG, "Clearing " + restriction + " using " + mDevicePolicyManager);
333         mDevicePolicyManager.clearUserRestriction(getWho(), restriction);
334     }
335 
btStateToString(int state)336     private static String btStateToString(int state) {
337         return DebugUtils.constantToString(BluetoothAdapter.class, "STATE_", state);
338     }
339 
sleep(long t)340     private static void sleep(long t) {
341         if (VERBOSE) {
342             Log.v(TAG, "Sleeping for " + t + "ms");
343         }
344         SystemClock.sleep(t);
345     }
346 }
347