Loading service/java/com/android/server/bluetooth/BluetoothManagerService.java +26 −19 Original line number Original line Diff line number Diff line Loading @@ -155,7 +155,8 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { private static final int DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS = 86400000; private static final int DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS = 86400000; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; @VisibleForTesting static final int MESSAGE_DISABLE = 2; private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; Loading Loading @@ -324,19 +325,19 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { public void onUserRestrictionsChanged(UserHandle userHandle) { public void onUserRestrictionsChanged(UserHandle userHandle) { final boolean newBluetoothDisallowed = mUserManager.hasUserRestrictionForUser( final boolean newBluetoothDisallowed = mUserManager.hasUserRestrictionForUser( UserManager.DISALLOW_BLUETOOTH, userHandle); UserManager.DISALLOW_BLUETOOTH, userHandle); boolean newBluetoothSharingDisallowed = mUserManager.hasUserRestrictionForUser( // Disallow Bluetooth sharing when either Bluetooth is disallowed or Bluetooth sharing UserManager.DISALLOW_BLUETOOTH_SHARING, userHandle); // is disallowed final boolean newBluetoothSharingDisallowed = mUserManager.hasUserRestrictionForUser( UserManager.DISALLOW_BLUETOOTH_SHARING, userHandle) || newBluetoothDisallowed; // Disable OPP activities for this userHandle updateOppLauncherComponentState(userHandle, newBluetoothSharingDisallowed); // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. if (userHandle == UserHandle.SYSTEM) { // Only trigger once instead of for all users if (newBluetoothDisallowed) { if (userHandle == UserHandle.SYSTEM && newBluetoothDisallowed) { updateOppLauncherComponentState(userHandle, true); // Sharing disallowed sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED, sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED, mContext.getPackageName()); mContext.getPackageName()); } else { updateOppLauncherComponentState(userHandle, newBluetoothSharingDisallowed); } } else { updateOppLauncherComponentState(userHandle, newBluetoothSharingDisallowed); } } } } Loading Loading @@ -568,10 +569,12 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { }; }; BluetoothManagerService(Context context) { BluetoothManagerService(Context context) { mBluetoothHandlerThread = new HandlerThread("BluetoothManagerService"); mBluetoothHandlerThread = BluetoothServerProxy.getInstance() .createHandlerThread("BluetoothManagerService"); mBluetoothHandlerThread.start(); mBluetoothHandlerThread.start(); mHandler = new BluetoothHandler(mBluetoothHandlerThread.getLooper()); mHandler = BluetoothServerProxy.getInstance().newBluetoothHandler( new BluetoothHandler(mBluetoothHandlerThread.getLooper())); mContext = context; mContext = context; Loading Loading @@ -819,8 +822,11 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { } } return; return; } } mName = Settings.Secure.getString(mContentResolver, Settings.Secure.BLUETOOTH_NAME); mName = BluetoothServerProxy.getInstance() mAddress = Settings.Secure.getString(mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); .settingsSecureGetString(mContentResolver, Settings.Secure.BLUETOOTH_NAME); mAddress = BluetoothServerProxy.getInstance() .settingsSecureGetString(mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); if (DBG) { if (DBG) { Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); } } Loading Loading @@ -2062,7 +2068,8 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); private class BluetoothHandler extends Handler { @VisibleForTesting class BluetoothHandler extends Handler { boolean mGetNameAddressOnly = false; boolean mGetNameAddressOnly = false; private int mWaitForEnableRetry; private int mWaitForEnableRetry; private int mWaitForDisableRetry; private int mWaitForDisableRetry; Loading Loading @@ -2968,7 +2975,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { } } private void sendDisableMsg(int reason, String packageName) { private void sendDisableMsg(int reason, String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); BluetoothServerProxy.getInstance().handlerSendWhatMessage(mHandler, MESSAGE_DISABLE); addActiveLog(reason, packageName, false); addActiveLog(reason, packageName, false); } } Loading service/java/com/android/server/bluetooth/BluetoothServerProxy.java 0 → 100644 +103 −0 Original line number Original line Diff line number Diff line /* * Copyright 2023 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.bluetooth; import android.content.ContentResolver; import android.os.HandlerThread; import android.provider.Settings; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; /** * Proxy class for method calls to help with unit testing */ public class BluetoothServerProxy { private static final String TAG = BluetoothServerProxy.class.getSimpleName(); private static final Object INSTANCE_LOCK = new Object(); private static BluetoothServerProxy sInstance; private BluetoothServerProxy() { } /** * Get the singleton instance of proxy * * @return the singleton instance, guaranteed not null */ public static BluetoothServerProxy getInstance() { synchronized (INSTANCE_LOCK) { if (sInstance == null) { sInstance = new BluetoothServerProxy(); } } return sInstance; } /** * Allow unit tests to substitute BluetoothPbapMethodCallProxy with a test instance * * @param proxy a test instance of the BluetoothPbapMethodCallProxy */ @VisibleForTesting public static void setInstanceForTesting(BluetoothServerProxy proxy) { synchronized (INSTANCE_LOCK) { Log.d(TAG, "setInstanceForTesting(), set to " + proxy); sInstance = proxy; } } /** * Proxies {@link com.android.server.bluetooth.BluetoothManagerService.BluetoothHandler}. */ public BluetoothManagerService.BluetoothHandler createBluetoothHandler( BluetoothManagerService.BluetoothHandler bluetoothHandler) { return bluetoothHandler; } /** * Proxies {@link com.android.server.bluetooth.BluetoothManagerService.BluetoothHandler}. */ public BluetoothManagerService.BluetoothHandler newBluetoothHandler( BluetoothManagerService.BluetoothHandler bluetoothHandler) { return bluetoothHandler; } /** * Proxies {@link HandlerThread(String)}. */ public HandlerThread createHandlerThread(String name) { return new HandlerThread(name); } /** * Proxies {@link android.provider.Settings.Secure.getString}. */ public String settingsSecureGetString(ContentResolver contentResolver, String name) { return Settings.Secure.getString(contentResolver, name); } /** * Proxies * {@link com.android.server.bluetooth.BluetoothManagerService.BluetoothHandler.sendMessage}. */ public boolean handlerSendWhatMessage( com.android.server.bluetooth.BluetoothManagerService.BluetoothHandler handler, int what) { return handler.sendMessage(handler.obtainMessage(what)); } } service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java 0 → 100644 +108 −0 Original line number Original line Diff line number Diff line /* * Copyright 2023 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.bluetooth; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.os.HandlerThread; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class BluetoothManagerServiceTest { static int sTimeout = 3000; BluetoothManagerService mManagerService; Context mContext; @Mock BluetoothServerProxy mBluetoothServerProxy; @Mock BluetoothManagerService.BluetoothHandler mHandler; HandlerThread mHandlerThread; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContext = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); mHandlerThread = new HandlerThread("BluetoothManagerServiceTest"); } @After public void tearDown() { mHandlerThread.quitSafely(); } @Test public void onUserRestrictionsChanged_disallowBluetooth_onlySendDisableMessageOnSystemUser() throws InterruptedException { doReturn(mock(Intent.class)).when(mContext).registerReceiverForAllUsers(any(), any(), eq(null), eq(null)); BluetoothServerProxy.setInstanceForTesting(mBluetoothServerProxy); // Mock the handler to avoid handle message & to terminate the thread after // test doReturn(mHandlerThread).when(mBluetoothServerProxy).createHandlerThread(any()); doReturn(mHandler).when(mBluetoothServerProxy).newBluetoothHandler(any()); // Mock these functions so security errors won't throw doReturn("name").when(mBluetoothServerProxy).settingsSecureGetString(any(), eq(Settings.Secure.BLUETOOTH_NAME)); doReturn("00:11:22:33:44:55").when(mBluetoothServerProxy).settingsSecureGetString(any(), eq(Settings.Secure.BLUETOOTH_ADDRESS)); // Spy UserManager so we can mimic the case when restriction settings changed UserManager userManager = mock(UserManager.class); doReturn(userManager).when(mContext).getSystemService(UserManager.class); doReturn(true).when(userManager).hasUserRestrictionForUser( eq(UserManager.DISALLOW_BLUETOOTH), any()); doReturn(false).when(userManager).hasUserRestrictionForUser( eq(UserManager.DISALLOW_BLUETOOTH_SHARING), any()); mManagerService = new BluetoothManagerService(mContext); // Check if disable message sent once for system user only // Since Message object is recycled after processed, use proxy function to get what value // test run on user -1, should not turning Bluetooth off mManagerService.onUserRestrictionsChanged(UserHandle.CURRENT); verify(mBluetoothServerProxy, timeout(sTimeout).times(0)).handlerSendWhatMessage(mHandler, BluetoothManagerService.MESSAGE_DISABLE); // called from SYSTEM user, should try to toggle Bluetooth off mManagerService.onUserRestrictionsChanged(UserHandle.SYSTEM); verify(mBluetoothServerProxy, timeout(sTimeout)).handlerSendWhatMessage(mHandler, BluetoothManagerService.MESSAGE_DISABLE); } } Loading
service/java/com/android/server/bluetooth/BluetoothManagerService.java +26 −19 Original line number Original line Diff line number Diff line Loading @@ -155,7 +155,8 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { private static final int DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS = 86400000; private static final int DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS = 86400000; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; @VisibleForTesting static final int MESSAGE_DISABLE = 2; private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; Loading Loading @@ -324,19 +325,19 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { public void onUserRestrictionsChanged(UserHandle userHandle) { public void onUserRestrictionsChanged(UserHandle userHandle) { final boolean newBluetoothDisallowed = mUserManager.hasUserRestrictionForUser( final boolean newBluetoothDisallowed = mUserManager.hasUserRestrictionForUser( UserManager.DISALLOW_BLUETOOTH, userHandle); UserManager.DISALLOW_BLUETOOTH, userHandle); boolean newBluetoothSharingDisallowed = mUserManager.hasUserRestrictionForUser( // Disallow Bluetooth sharing when either Bluetooth is disallowed or Bluetooth sharing UserManager.DISALLOW_BLUETOOTH_SHARING, userHandle); // is disallowed final boolean newBluetoothSharingDisallowed = mUserManager.hasUserRestrictionForUser( UserManager.DISALLOW_BLUETOOTH_SHARING, userHandle) || newBluetoothDisallowed; // Disable OPP activities for this userHandle updateOppLauncherComponentState(userHandle, newBluetoothSharingDisallowed); // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user. if (userHandle == UserHandle.SYSTEM) { // Only trigger once instead of for all users if (newBluetoothDisallowed) { if (userHandle == UserHandle.SYSTEM && newBluetoothDisallowed) { updateOppLauncherComponentState(userHandle, true); // Sharing disallowed sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED, sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED, mContext.getPackageName()); mContext.getPackageName()); } else { updateOppLauncherComponentState(userHandle, newBluetoothSharingDisallowed); } } else { updateOppLauncherComponentState(userHandle, newBluetoothSharingDisallowed); } } } } Loading Loading @@ -568,10 +569,12 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { }; }; BluetoothManagerService(Context context) { BluetoothManagerService(Context context) { mBluetoothHandlerThread = new HandlerThread("BluetoothManagerService"); mBluetoothHandlerThread = BluetoothServerProxy.getInstance() .createHandlerThread("BluetoothManagerService"); mBluetoothHandlerThread.start(); mBluetoothHandlerThread.start(); mHandler = new BluetoothHandler(mBluetoothHandlerThread.getLooper()); mHandler = BluetoothServerProxy.getInstance().newBluetoothHandler( new BluetoothHandler(mBluetoothHandlerThread.getLooper())); mContext = context; mContext = context; Loading Loading @@ -819,8 +822,11 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { } } return; return; } } mName = Settings.Secure.getString(mContentResolver, Settings.Secure.BLUETOOTH_NAME); mName = BluetoothServerProxy.getInstance() mAddress = Settings.Secure.getString(mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); .settingsSecureGetString(mContentResolver, Settings.Secure.BLUETOOTH_NAME); mAddress = BluetoothServerProxy.getInstance() .settingsSecureGetString(mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); if (DBG) { if (DBG) { Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); Log.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); } } Loading Loading @@ -2062,7 +2068,8 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); private BluetoothServiceConnection mConnection = new BluetoothServiceConnection(); private class BluetoothHandler extends Handler { @VisibleForTesting class BluetoothHandler extends Handler { boolean mGetNameAddressOnly = false; boolean mGetNameAddressOnly = false; private int mWaitForEnableRetry; private int mWaitForEnableRetry; private int mWaitForDisableRetry; private int mWaitForDisableRetry; Loading Loading @@ -2968,7 +2975,7 @@ public class BluetoothManagerService extends IBluetoothManager.Stub { } } private void sendDisableMsg(int reason, String packageName) { private void sendDisableMsg(int reason, String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); BluetoothServerProxy.getInstance().handlerSendWhatMessage(mHandler, MESSAGE_DISABLE); addActiveLog(reason, packageName, false); addActiveLog(reason, packageName, false); } } Loading
service/java/com/android/server/bluetooth/BluetoothServerProxy.java 0 → 100644 +103 −0 Original line number Original line Diff line number Diff line /* * Copyright 2023 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.bluetooth; import android.content.ContentResolver; import android.os.HandlerThread; import android.provider.Settings; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; /** * Proxy class for method calls to help with unit testing */ public class BluetoothServerProxy { private static final String TAG = BluetoothServerProxy.class.getSimpleName(); private static final Object INSTANCE_LOCK = new Object(); private static BluetoothServerProxy sInstance; private BluetoothServerProxy() { } /** * Get the singleton instance of proxy * * @return the singleton instance, guaranteed not null */ public static BluetoothServerProxy getInstance() { synchronized (INSTANCE_LOCK) { if (sInstance == null) { sInstance = new BluetoothServerProxy(); } } return sInstance; } /** * Allow unit tests to substitute BluetoothPbapMethodCallProxy with a test instance * * @param proxy a test instance of the BluetoothPbapMethodCallProxy */ @VisibleForTesting public static void setInstanceForTesting(BluetoothServerProxy proxy) { synchronized (INSTANCE_LOCK) { Log.d(TAG, "setInstanceForTesting(), set to " + proxy); sInstance = proxy; } } /** * Proxies {@link com.android.server.bluetooth.BluetoothManagerService.BluetoothHandler}. */ public BluetoothManagerService.BluetoothHandler createBluetoothHandler( BluetoothManagerService.BluetoothHandler bluetoothHandler) { return bluetoothHandler; } /** * Proxies {@link com.android.server.bluetooth.BluetoothManagerService.BluetoothHandler}. */ public BluetoothManagerService.BluetoothHandler newBluetoothHandler( BluetoothManagerService.BluetoothHandler bluetoothHandler) { return bluetoothHandler; } /** * Proxies {@link HandlerThread(String)}. */ public HandlerThread createHandlerThread(String name) { return new HandlerThread(name); } /** * Proxies {@link android.provider.Settings.Secure.getString}. */ public String settingsSecureGetString(ContentResolver contentResolver, String name) { return Settings.Secure.getString(contentResolver, name); } /** * Proxies * {@link com.android.server.bluetooth.BluetoothManagerService.BluetoothHandler.sendMessage}. */ public boolean handlerSendWhatMessage( com.android.server.bluetooth.BluetoothManagerService.BluetoothHandler handler, int what) { return handler.sendMessage(handler.obtainMessage(what)); } }
service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java 0 → 100644 +108 −0 Original line number Original line Diff line number Diff line /* * Copyright 2023 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.bluetooth; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.os.HandlerThread; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class BluetoothManagerServiceTest { static int sTimeout = 3000; BluetoothManagerService mManagerService; Context mContext; @Mock BluetoothServerProxy mBluetoothServerProxy; @Mock BluetoothManagerService.BluetoothHandler mHandler; HandlerThread mHandlerThread; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContext = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); mHandlerThread = new HandlerThread("BluetoothManagerServiceTest"); } @After public void tearDown() { mHandlerThread.quitSafely(); } @Test public void onUserRestrictionsChanged_disallowBluetooth_onlySendDisableMessageOnSystemUser() throws InterruptedException { doReturn(mock(Intent.class)).when(mContext).registerReceiverForAllUsers(any(), any(), eq(null), eq(null)); BluetoothServerProxy.setInstanceForTesting(mBluetoothServerProxy); // Mock the handler to avoid handle message & to terminate the thread after // test doReturn(mHandlerThread).when(mBluetoothServerProxy).createHandlerThread(any()); doReturn(mHandler).when(mBluetoothServerProxy).newBluetoothHandler(any()); // Mock these functions so security errors won't throw doReturn("name").when(mBluetoothServerProxy).settingsSecureGetString(any(), eq(Settings.Secure.BLUETOOTH_NAME)); doReturn("00:11:22:33:44:55").when(mBluetoothServerProxy).settingsSecureGetString(any(), eq(Settings.Secure.BLUETOOTH_ADDRESS)); // Spy UserManager so we can mimic the case when restriction settings changed UserManager userManager = mock(UserManager.class); doReturn(userManager).when(mContext).getSystemService(UserManager.class); doReturn(true).when(userManager).hasUserRestrictionForUser( eq(UserManager.DISALLOW_BLUETOOTH), any()); doReturn(false).when(userManager).hasUserRestrictionForUser( eq(UserManager.DISALLOW_BLUETOOTH_SHARING), any()); mManagerService = new BluetoothManagerService(mContext); // Check if disable message sent once for system user only // Since Message object is recycled after processed, use proxy function to get what value // test run on user -1, should not turning Bluetooth off mManagerService.onUserRestrictionsChanged(UserHandle.CURRENT); verify(mBluetoothServerProxy, timeout(sTimeout).times(0)).handlerSendWhatMessage(mHandler, BluetoothManagerService.MESSAGE_DISABLE); // called from SYSTEM user, should try to toggle Bluetooth off mManagerService.onUserRestrictionsChanged(UserHandle.SYSTEM); verify(mBluetoothServerProxy, timeout(sTimeout)).handlerSendWhatMessage(mHandler, BluetoothManagerService.MESSAGE_DISABLE); } }