diff options
author | 2025-03-16 23:36:32 -0700 | |
---|---|---|
committer | 2025-03-16 23:36:32 -0700 | |
commit | 3a1b674587c960b359368f544b9d98a8d5e7e6ba (patch) | |
tree | 08db94ef2d0c78bda54d6e297315c298a8c108f6 | |
parent | 870ec11450e9e12edfd2b3c82d851ab7eff9dec3 (diff) | |
parent | fc363417bced93fb2e2024d8d0054cafaa55d028 (diff) |
Merge "Extract `HidHostServiceBinder` to its own class" into main
4 files changed, 250 insertions, 235 deletions
diff --git a/android/app/src/com/android/bluetooth/hid/HidHostService.java b/android/app/src/com/android/bluetooth/hid/HidHostService.java index 3a29ed5b62..1eac6ed336 100644 --- a/android/app/src/com/android/bluetooth/hid/HidHostService.java +++ b/android/app/src/com/android/bluetooth/hid/HidHostService.java @@ -17,7 +17,6 @@ package com.android.bluetooth.hid; import static android.Manifest.permission.BLUETOOTH_CONNECT; -import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN; @@ -27,14 +26,11 @@ import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; import static java.util.Objects.requireNonNull; -import android.annotation.RequiresPermission; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHidHost; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.BluetoothUuid; -import android.bluetooth.IBluetoothHidHost; -import android.content.AttributionSource; import android.content.Intent; import android.os.Bundle; import android.os.Handler; @@ -145,7 +141,7 @@ public class HidHostService extends ProfileService { @Override public IProfileServiceBinder initBinder() { - return new BluetoothHidHostBinder(this); + return new HidHostServiceBinder(this); } @Override @@ -713,207 +709,6 @@ public class HidHostService extends ProfileService { return true; } - @VisibleForTesting - static class BluetoothHidHostBinder extends IBluetoothHidHost.Stub - implements IProfileServiceBinder { - private HidHostService mService; - - BluetoothHidHostBinder(HidHostService svc) { - mService = svc; - } - - @Override - public void cleanup() { - mService = null; - } - - @RequiresPermission(BLUETOOTH_CONNECT) - private HidHostService getService(AttributionSource source) { - // Cache mService because it can change while getService is called - HidHostService service = mService; - - if (Utils.isInstrumentationTestMode()) { - return service; - } - - if (!Utils.checkServiceAvailable(service, TAG) - || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG) - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return null; - } - - return service; - } - - @Override - public boolean connect(BluetoothDevice device, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.connect(device); - } - - @Override - public boolean disconnect(BluetoothDevice device, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.disconnect(device); - } - - @Override - public int getConnectionState(BluetoothDevice device, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return STATE_DISCONNECTED; - } - return service.getConnectionState(device); - } - - @Override - public List<BluetoothDevice> getConnectedDevices(AttributionSource source) { - return getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED}, source); - } - - @Override - public List<BluetoothDevice> getDevicesMatchingConnectionStates( - int[] states, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return Collections.emptyList(); - } - return service.getDevicesMatchingConnectionStates(states); - } - - @Override - public boolean setConnectionPolicy( - BluetoothDevice device, int connectionPolicy, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.setConnectionPolicy(device, connectionPolicy); - } - - @Override - public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return CONNECTION_POLICY_UNKNOWN; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.getConnectionPolicy(device); - } - - @Override - public boolean setPreferredTransport( - BluetoothDevice device, int transport, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.setPreferredTransport(device, transport); - } - - @Override - public int getPreferredTransport(BluetoothDevice device, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return BluetoothDevice.TRANSPORT_AUTO; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.getPreferredTransport(device); - } - - /* The following APIs regarding test app for compliance */ - @Override - public boolean getProtocolMode(BluetoothDevice device, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - return service.getProtocolMode(device); - } - - @Override - public boolean virtualUnplug(BluetoothDevice device, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - return service.virtualUnplug(device); - } - - @Override - public boolean setProtocolMode( - BluetoothDevice device, int protocolMode, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - return service.setProtocolMode(device, protocolMode); - } - - @Override - public boolean getReport( - BluetoothDevice device, - byte reportType, - byte reportId, - int bufferSize, - AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - return service.getReport(device, reportType, reportId, bufferSize); - } - - @Override - public boolean setReport( - BluetoothDevice device, byte reportType, String report, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - return service.setReport(device, reportType, report); - } - - @Override - public boolean sendData(BluetoothDevice device, String report, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - return service.sendData(device, report); - } - - @Override - public boolean setIdleTime( - BluetoothDevice device, byte idleTime, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - return service.setIdleTime(device, idleTime); - } - - @Override - public boolean getIdleTime(BluetoothDevice device, AttributionSource source) { - HidHostService service = getService(source); - if (service == null) { - return false; - } - return service.getIdleTime(device); - } - } - ; - // APIs /** @@ -982,7 +777,6 @@ public class HidHostService extends ProfileService { return STATE_DISCONNECTED; } - @VisibleForTesting List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { Log.d(TAG, "getDevicesMatchingConnectionStates()"); return mInputDevices.entrySet().stream() @@ -1073,7 +867,6 @@ public class HidHostService extends ProfileService { /** * @see BluetoothHidHost#getPreferredTransport */ - @VisibleForTesting int getPreferredTransport(BluetoothDevice device) { Log.d(TAG, "getPreferredTransport: device=" + device); @@ -1082,7 +875,6 @@ public class HidHostService extends ProfileService { } /* The following APIs regarding test app for compliance */ - @VisibleForTesting boolean getProtocolMode(BluetoothDevice device) { Log.d(TAG, "getProtocolMode: device=" + device); int state = this.getConnectionState(device); @@ -1094,7 +886,6 @@ public class HidHostService extends ProfileService { return true; } - @VisibleForTesting boolean virtualUnplug(BluetoothDevice device) { Log.d(TAG, "virtualUnplug: device=" + device); int state = this.getConnectionState(device); @@ -1106,7 +897,6 @@ public class HidHostService extends ProfileService { return true; } - @VisibleForTesting boolean setProtocolMode(BluetoothDevice device, int protocolMode) { Log.d(TAG, "setProtocolMode: device=" + device); int state = this.getConnectionState(device); @@ -1120,7 +910,6 @@ public class HidHostService extends ProfileService { return true; } - @VisibleForTesting boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { Log.d(TAG, "getReport: device=" + device); int state = this.getConnectionState(device); @@ -1138,7 +927,6 @@ public class HidHostService extends ProfileService { return true; } - @VisibleForTesting boolean setReport(BluetoothDevice device, byte reportType, String report) { Log.d(TAG, "setReport: device=" + device); int state = this.getConnectionState(device); @@ -1155,7 +943,6 @@ public class HidHostService extends ProfileService { return true; } - @VisibleForTesting boolean sendData(BluetoothDevice device, String report) { Log.d(TAG, "sendData: device=" + device); int state = this.getConnectionState(device); @@ -1393,8 +1180,9 @@ public class HidHostService extends ProfileService { // Allow this connection only if the device is bonded. Any attempt to connect // while bonding would potentially lead to an unauthorized connection. if (bondState != BluetoothDevice.BOND_BONDED) { - Log.w(TAG, "okToConnect: return false, device=" + device + " bondState=" - + bondState); + Log.w( + TAG, + "okToConnect: return false, device=" + device + " bondState=" + bondState); return false; } } diff --git a/android/app/src/com/android/bluetooth/hid/HidHostServiceBinder.java b/android/app/src/com/android/bluetooth/hid/HidHostServiceBinder.java new file mode 100644 index 0000000000..3295c83f01 --- /dev/null +++ b/android/app/src/com/android/bluetooth/hid/HidHostServiceBinder.java @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2025 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.bluetooth.hid; + +import static android.Manifest.permission.BLUETOOTH_CONNECT; +import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; + +import android.annotation.RequiresPermission; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.IBluetoothHidHost; +import android.content.AttributionSource; + +import com.android.bluetooth.Utils; +import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder; + +import java.util.Collections; +import java.util.List; + +class HidHostServiceBinder extends IBluetoothHidHost.Stub implements IProfileServiceBinder { + private static final String TAG = HidHostServiceBinder.class.getSimpleName(); + + private HidHostService mService; + + HidHostServiceBinder(HidHostService svc) { + mService = svc; + } + + @Override + public void cleanup() { + mService = null; + } + + @RequiresPermission(BLUETOOTH_CONNECT) + private HidHostService getService(AttributionSource source) { + HidHostService service = mService; + + if (Utils.isInstrumentationTestMode()) { + return service; + } + + if (!Utils.checkServiceAvailable(service, TAG) + || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG) + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return null; + } + + return service; + } + + @Override + public boolean connect(BluetoothDevice device, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.connect(device); + } + + @Override + public boolean disconnect(BluetoothDevice device, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.disconnect(device); + } + + @Override + public int getConnectionState(BluetoothDevice device, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return STATE_DISCONNECTED; + } + return service.getConnectionState(device); + } + + @Override + public List<BluetoothDevice> getConnectedDevices(AttributionSource source) { + return getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED}, source); + } + + @Override + public List<BluetoothDevice> getDevicesMatchingConnectionStates( + int[] states, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return Collections.emptyList(); + } + return service.getDevicesMatchingConnectionStates(states); + } + + @Override + public boolean setConnectionPolicy( + BluetoothDevice device, int connectionPolicy, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.setConnectionPolicy(device, connectionPolicy); + } + + @Override + public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return CONNECTION_POLICY_UNKNOWN; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.getConnectionPolicy(device); + } + + @Override + public boolean setPreferredTransport( + BluetoothDevice device, int transport, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.setPreferredTransport(device, transport); + } + + @Override + public int getPreferredTransport(BluetoothDevice device, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return BluetoothDevice.TRANSPORT_AUTO; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.getPreferredTransport(device); + } + + /* The following APIs regarding test app for compliance */ + @Override + public boolean getProtocolMode(BluetoothDevice device, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + return service.getProtocolMode(device); + } + + @Override + public boolean virtualUnplug(BluetoothDevice device, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + return service.virtualUnplug(device); + } + + @Override + public boolean setProtocolMode( + BluetoothDevice device, int protocolMode, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + return service.setProtocolMode(device, protocolMode); + } + + @Override + public boolean getReport( + BluetoothDevice device, + byte reportType, + byte reportId, + int bufferSize, + AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + return service.getReport(device, reportType, reportId, bufferSize); + } + + @Override + public boolean setReport( + BluetoothDevice device, byte reportType, String report, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + return service.setReport(device, reportType, report); + } + + @Override + public boolean sendData(BluetoothDevice device, String report, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + return service.sendData(device, report); + } + + @Override + public boolean setIdleTime(BluetoothDevice device, byte idleTime, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + return service.setIdleTime(device, idleTime); + } + + @Override + public boolean getIdleTime(BluetoothDevice device, AttributionSource source) { + HidHostService service = getService(source); + if (service == null) { + return false; + } + return service.getIdleTime(device); + } +} diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java index 02bee889e8..e2b15ebdba 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java @@ -36,9 +36,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +/** Test cases for {@link HidHostServiceBinder}. */ @SmallTest @RunWith(AndroidJUnit4.class) public class HidHostServiceBinderTest { + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Rule public final MockitoRule mMockitoRule = new MockitoRule(); @@ -46,98 +48,90 @@ public class HidHostServiceBinderTest { private final BluetoothDevice mDevice = getTestDevice(50); - private HidHostService.BluetoothHidHostBinder mBinder; + private HidHostServiceBinder mBinder; @Before public void setUp() { - mBinder = new HidHostService.BluetoothHidHostBinder(mService); + mBinder = new HidHostServiceBinder(mService); } @Test public void connect_callsServiceMethod() { mBinder.connect(mDevice, null); - verify(mService).connect(mDevice); } @Test public void disconnect_callsServiceMethod() { mBinder.disconnect(mDevice, null); - verify(mService).disconnect(mDevice); } @Test public void getConnectedDevices_callsServiceMethod() { mBinder.getConnectedDevices(null); - verify(mService).getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED}); } @Test public void getDevicesMatchingConnectionStates_callsServiceMethod() { int[] states = new int[] {STATE_CONNECTED}; - mBinder.getDevicesMatchingConnectionStates(states, null); + mBinder.getDevicesMatchingConnectionStates(states, null); verify(mService).getDevicesMatchingConnectionStates(states); } @Test public void getConnectionState_callsServiceMethod() { mBinder.getConnectionState(mDevice, null); - verify(mService).getConnectionState(mDevice); } @Test public void setConnectionPolicy_callsServiceMethod() { int connectionPolicy = CONNECTION_POLICY_ALLOWED; - mBinder.setConnectionPolicy(mDevice, connectionPolicy, null); + mBinder.setConnectionPolicy(mDevice, connectionPolicy, null); verify(mService).setConnectionPolicy(mDevice, connectionPolicy); } @Test public void getConnectionPolicy_callsServiceMethod() { mBinder.getConnectionPolicy(mDevice, null); - verify(mService).getConnectionPolicy(mDevice); } @Test public void setPreferredTransport_callsServiceMethod() { int preferredTransport = BluetoothDevice.TRANSPORT_AUTO; - mBinder.setPreferredTransport(mDevice, preferredTransport, null); + mBinder.setPreferredTransport(mDevice, preferredTransport, null); verify(mService).setPreferredTransport(mDevice, preferredTransport); } @Test public void getPreferredTransport_callsServiceMethod() { mBinder.getPreferredTransport(mDevice, null); - verify(mService).getPreferredTransport(mDevice); } @Test public void getProtocolMode_callsServiceMethod() { mBinder.getProtocolMode(mDevice, null); - verify(mService).getProtocolMode(mDevice); } @Test public void virtualUnplug_callsServiceMethod() { mBinder.virtualUnplug(mDevice, null); - verify(mService).virtualUnplug(mDevice); } @Test public void setProtocolMode_callsServiceMethod() { int protocolMode = 1; - mBinder.setProtocolMode(mDevice, protocolMode, null); + mBinder.setProtocolMode(mDevice, protocolMode, null); verify(mService).setProtocolMode(mDevice, protocolMode); } @@ -146,8 +140,8 @@ public class HidHostServiceBinderTest { byte reportType = 1; byte reportId = 2; int bufferSize = 16; - mBinder.getReport(mDevice, reportType, reportId, bufferSize, null); + mBinder.getReport(mDevice, reportType, reportId, bufferSize, null); verify(mService).getReport(mDevice, reportType, reportId, bufferSize); } @@ -155,31 +149,30 @@ public class HidHostServiceBinderTest { public void setReport_callsServiceMethod() { byte reportType = 1; String report = "test_report"; - mBinder.setReport(mDevice, reportType, report, null); + mBinder.setReport(mDevice, reportType, report, null); verify(mService).setReport(mDevice, reportType, report); } @Test public void sendData_callsServiceMethod() { String report = "test_report"; - mBinder.sendData(mDevice, report, null); + mBinder.sendData(mDevice, report, null); verify(mService).sendData(mDevice, report); } @Test public void setIdleTime_callsServiceMethod() { byte idleTime = 1; - mBinder.setIdleTime(mDevice, idleTime, null); + mBinder.setIdleTime(mDevice, idleTime, null); verify(mService).setIdleTime(mDevice, idleTime); } @Test public void getIdleTime_callsServiceMethod() { mBinder.getIdleTime(mDevice, null); - verify(mService).getIdleTime(mDevice); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java index a41f93d5d6..10f5f3257f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.android.bluetooth.hid; import static android.bluetooth.BluetoothDevice.BOND_BONDED; @@ -53,6 +54,7 @@ import java.util.List; @MediumTest @RunWith(AndroidJUnit4.class) public class HidHostServiceTest { + @Rule public final MockitoRule mMockitoRule = new MockitoRule(); @Mock private AdapterService mAdapterService; |