diff options
author | 2024-10-03 15:50:51 +0000 | |
---|---|---|
committer | 2024-10-03 23:36:43 +0000 | |
commit | 60a54ee232f321cd1326502000a375c59e8c3ea5 (patch) | |
tree | 1d9b6a36a21986d1a128e17a1d1c728006684dfc | |
parent | 8973771c4125b7dbc3c5adea43466644d00ada87 (diff) |
Add UsbManagerInternal interface
This interface will be used by internal services such as AndroidAdvancedProtectionModeService (TBD.)
go/usb_aapm
Change-Id: I843f4957406f1a79a46a880e20978d4c6a6edab9
Test: atest
Flag: android.hardware.usb.flags.enable_usb_data_signal_staking_internal
Bug: 369382558
4 files changed, 149 insertions, 20 deletions
diff --git a/services/usb/java/com/UsbDataSignalDisableRequesters.java b/services/usb/java/com/UsbDataSignalDisableRequesters.java index 145045da68de..d4d6492ab984 100644 --- a/services/usb/java/com/UsbDataSignalDisableRequesters.java +++ b/services/usb/java/com/UsbDataSignalDisableRequesters.java @@ -23,8 +23,10 @@ import android.util.ArraySet; * * External requesters are identified by UIDs. * Internal requesters are identified by a reason code enumerated in UsbManagerInternal. + * + * @hide */ -public class UsbDataSignalDisableRequesters { +public final class UsbDataSignalDisableRequesters { final ArraySet<Integer> mExternalUids = new ArraySet<>(); final ArraySet<Integer> mInternalReasons = new ArraySet<>(); diff --git a/services/usb/java/com/android/server/usb/UsbManagerInternal.java b/services/usb/java/com/android/server/usb/UsbManagerInternal.java new file mode 100644 index 000000000000..c97df6b4f63a --- /dev/null +++ b/services/usb/java/com/android/server/usb/UsbManagerInternal.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 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.usb; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.hardware.usb.IUsbOperationInternal; +import android.hardware.usb.UsbPort; +import android.util.ArraySet; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * UsbManagerInternal provides internal APIs for the UsbService to + * reduce IPC overhead costs and support internal USB data signal stakers. + * + * @hide Only for use within the system server. + */ +public abstract class UsbManagerInternal { + + public static final int OS_USB_DISABLE_REASON_AAPM = 0; + + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {OS_USB_DISABLE_REASON_AAPM}) + public @interface OsUsbDisableReason { + } + + public abstract boolean enableUsbData(String portId, boolean enable, + int operationId, IUsbOperationInternal callback, @OsUsbDisableReason int disableReason); + + public abstract UsbPort[] getPorts(); + +}
\ No newline at end of file diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index e36331b79e15..ba9dff656f0a 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -46,6 +46,7 @@ import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPortStatus; + import android.os.Binder; import android.os.Bundle; import android.os.Looper; @@ -69,6 +70,7 @@ import com.android.internal.util.Preconditions; import com.android.internal.util.dump.DualDumpOutputStream; import com.android.internal.widget.LockPatternUtils; import com.android.server.FgThread; +import com.android.server.LocalServices; import com.android.server.SystemServerInitThreadPool; import com.android.server.SystemService; @@ -223,6 +225,9 @@ public class UsbService extends IUsbManager.Stub { filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); mContext.registerReceiverAsUser(receiver, UserHandle.ALL, filter, null, null); + if(android.hardware.usb.flags.Flags.enableUsbDataSignalStakingInternal()) { + LocalServices.addService(UsbManagerInternal.class, new UsbManagerInternalImpl()); + } } // Ideally we should use the injector pattern so we wouldn't need this constructor for test @@ -238,6 +243,10 @@ public class UsbService extends IUsbManager.Stub { mUserManager = userManager; mSettingsManager = usbSettingsManager; mPermissionManager = new UsbPermissionManager(context, this); + + if(android.hardware.usb.flags.Flags.enableUsbDataSignalStakingInternal()) { + LocalServices.addService(UsbManagerInternal.class, new UsbManagerInternalImpl()); + } } /** @@ -905,7 +914,8 @@ public class UsbService extends IUsbManager.Stub { @Override public boolean enableUsbData(String portId, boolean enable, int operationId, IUsbOperationInternal callback) { - return enableUsbDataInternal(portId, enable, operationId, callback, Binder.getCallingUid(), false); + return enableUsbDataInternal(portId, enable, operationId, callback, + Binder.getCallingUid(), false); } /** @@ -913,7 +923,8 @@ public class UsbService extends IUsbManager.Stub { * 1. UID of the app that requested USB data to be disabled if caller is external. * 2. Enumberated disable request reason if the caller is internal. * - * For internal requests, isInternalRequest should be set to true. Since internal requests all share the same UID, the request managed separately. + * For internal requests, isInternalRequest should be set to true. Since + * internal requests all share the same UID, the request managed separately. */ @VisibleForTesting boolean enableUsbDataInternal(String portId, boolean enable, int operationId, @@ -999,7 +1010,8 @@ public class UsbService extends IUsbManager.Stub { @Override public void enableUsbDataWhileDocked(String portId, int operationId, IUsbOperationInternal callback) { - enableUsbDataWhileDockedInternal(portId, operationId, callback, Binder.getCallingUid(), false); + enableUsbDataWhileDockedInternal(portId, operationId, callback, + Binder.getCallingUid(), false); } /** @@ -1478,7 +1490,8 @@ public class UsbService extends IUsbManager.Stub { public void onUidRemoved(int uid) { synchronized (mUsbDisableRequesters) { for (String portId : mUsbDisableRequesters.keySet()) { - UsbDataSignalDisableRequesters disableRequesters = mUsbDisableRequesters.get(portId); + UsbDataSignalDisableRequesters disableRequesters = + mUsbDisableRequesters.get(portId); if (disableRequesters != null) { disableRequesters.mExternalUids.remove(uid); if (disableRequesters.isEmpty()) { @@ -1519,4 +1532,19 @@ public class UsbService extends IUsbManager.Stub { } } } + + private class UsbManagerInternalImpl extends UsbManagerInternal { + @Override + public boolean enableUsbData(String portId, boolean enable, + int operationId, IUsbOperationInternal callback, + @OsUsbDisableReason int disableReason) { + return enableUsbDataInternal(portId, enable, operationId, callback, + disableReason, true); + } + + @Override + public UsbPort[] getPorts() { + return mPortManager.getPorts(); + } + } } diff --git a/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java b/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java index 03ae72f7db08..51d57f0a0de9 100644 --- a/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java +++ b/tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java @@ -18,6 +18,10 @@ package com.android.server.usb; import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL; +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -31,12 +35,15 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.hardware.usb.IUsbOperationInternal; import android.hardware.usb.flags.Flags; +import android.hardware.usb.UsbPort; import android.os.RemoteException; import android.os.UserManager; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.runner.AndroidJUnit4; +import com.android.server.LocalServices; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -77,6 +84,8 @@ public class UsbServiceTest { private UsbService mUsbService; + private UsbManagerInternal mUsbManagerInternal; + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @@ -84,13 +93,17 @@ public class UsbServiceTest { public void setUp() { mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING); mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_USB_DATA_SIGNAL_STAKING_INTERNAL); + LocalServices.removeAllServicesForTest(); MockitoAnnotations.initMocks(this); - when(mUsbPortManager.enableUsbData(eq(TEST_PORT_ID), anyBoolean(), eq(TEST_TRANSACTION_ID), - eq(mCallback), any())).thenReturn(true); + when(mUsbPortManager.enableUsbData(eq(TEST_PORT_ID), anyBoolean(), + eq(TEST_TRANSACTION_ID), eq(mCallback), any())).thenReturn(true); mUsbService = new UsbService(mContext, mUsbPortManager, mUsbAlsaManager, mUserManager, mUsbSettingsManager); + mUsbManagerInternal = LocalServices.getService(UsbManagerInternal.class); + assertWithMessage("LocalServices.getService(UsbManagerInternal.class)") + .that(mUsbManagerInternal).isNotNull(); } private void assertToggleUsbSuccessfully(int requester, boolean enable, @@ -127,7 +140,8 @@ public class UsbServiceTest { } /** - * Verify enableUsbData successfully enables USB port without error given no other stakers + * Verify enableUsbData successfully enables USB port without error given + * no other stakers */ @Test public void enableUsbWhenNoOtherStakers_successfullyEnable() { @@ -145,7 +159,8 @@ public class UsbServiceTest { } /** - * Verify enableUsbData successfully enables USB port when the last staker is removed + * Verify enableUsbData successfully enables USB port when the last staker + * is removed */ @Test public void enableUsbByTheOnlyStaker_successfullyEnable() { @@ -155,7 +170,8 @@ public class UsbServiceTest { } /** - * Verify enableUsbDataWhileDockedInternal does not enable USB port if other stakers are present + * Verify enableUsbDataWhileDockedInternal does not enable USB port if other + * stakers are present */ @Test public void enableUsbWhileDockedWhenThereAreOtherStakers_failsToEnable() @@ -170,8 +186,8 @@ public class UsbServiceTest { } /** - * Verify enableUsbDataWhileDockedInternal does enable USB port if other stakers are - * not present + * Verify enableUsbDataWhileDockedInternal does enable USB port if other + * stakers are not present */ @Test public void enableUsbWhileDockedWhenThereAreNoStakers_SuccessfullyEnable() { @@ -184,7 +200,8 @@ public class UsbServiceTest { } /** - * Verify enableUsbData successfully enables USB port without error given no other stakers for internal requests + * Verify enableUsbData successfully enables USB port without error given no + * other stakers for internal requests */ @Test public void enableUsbWhenNoOtherStakers_forInternalRequest_successfullyEnable() { @@ -192,37 +209,44 @@ public class UsbServiceTest { } /** - * Verify enableUsbData does not enable USB port if other internal stakers are present for internal requests + * Verify enableUsbData does not enable USB port if other internal stakers + * are present for internal requests */ @Test - public void enableUsbPortWithOtherInternalStakers_forInternalRequest_failsToEnable() throws Exception { + public void enableUsbPortWithOtherInternalStakers_forInternalRequest_failsToEnable() + throws Exception { assertToggleUsbSuccessfully(TEST_INTERNAL_REQUESTER_REASON_1, false, true); assertToggleUsbFailed(TEST_INTERNAL_REQUESTER_REASON_2, true, true); } /** - * Verify enableUsbData does not enable USB port if other external stakers are present for internal requests + * Verify enableUsbData does not enable USB port if other external stakers + * are present for internal requests */ @Test - public void enableUsbPortWithOtherExternalStakers_forInternalRequest_failsToEnable() throws Exception { + public void enableUsbPortWithOtherExternalStakers_forInternalRequest_failsToEnable() + throws Exception { assertToggleUsbSuccessfully(TEST_FIRST_CALLER_ID, false, false); assertToggleUsbFailed(TEST_INTERNAL_REQUESTER_REASON_2, true, true); } /** - * Verify enableUsbData does not enable USB port if other internal stakers are present for external requests + * Verify enableUsbData does not enable USB port if other internal stakers + * are present for external requests */ @Test - public void enableUsbPortWithOtherInternalStakers_forExternalRequest_failsToEnable() throws Exception { + public void enableUsbPortWithOtherInternalStakers_forExternalRequest_failsToEnable() + throws Exception { assertToggleUsbSuccessfully(TEST_INTERNAL_REQUESTER_REASON_1, false, true); assertToggleUsbFailed(TEST_FIRST_CALLER_ID, true, false); } /** - * Verify enableUsbData successfully enables USB port when the last staker is removed for internal requests + * Verify enableUsbData successfully enables USB port when the last staker + * is removed for internal requests */ @Test public void enableUsbByTheOnlyStaker_forInternalRequest_successfullyEnable() { @@ -230,4 +254,31 @@ public class UsbServiceTest { assertToggleUsbSuccessfully(TEST_INTERNAL_REQUESTER_REASON_1, true, false); } + + /** + * Verify USB Manager internal calls mPortManager to get UsbPorts + */ + @Test + public void usbManagerInternal_getPorts_callsPortManager() { + when(mUsbPortManager.getPorts()).thenReturn(new UsbPort[] {}); + + UsbPort[] ports = mUsbManagerInternal.getPorts(); + + verify(mUsbPortManager).getPorts(); + assertEquals(ports.length, 0); + } + + @Test + public void usbManagerInternal_enableUsbData_successfullyEnable() { + boolean desiredEnableState = true; + + assertTrue(mUsbManagerInternal.enableUsbData(TEST_PORT_ID, desiredEnableState, + TEST_TRANSACTION_ID, mCallback, TEST_INTERNAL_REQUESTER_REASON_1)); + + verify(mUsbPortManager).enableUsbData(TEST_PORT_ID, + desiredEnableState, TEST_TRANSACTION_ID, mCallback, null); + verifyZeroInteractions(mCallback); + clearInvocations(mUsbPortManager); + clearInvocations(mCallback); + } } |