summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author George Chan <georgechan@google.com> 2024-10-03 15:50:51 +0000
committer George Chan <georgechan@google.com> 2024-10-03 23:36:43 +0000
commit60a54ee232f321cd1326502000a375c59e8c3ea5 (patch)
tree1d9b6a36a21986d1a128e17a1d1c728006684dfc
parent8973771c4125b7dbc3c5adea43466644d00ada87 (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
-rw-r--r--services/usb/java/com/UsbDataSignalDisableRequesters.java4
-rw-r--r--services/usb/java/com/android/server/usb/UsbManagerInternal.java48
-rw-r--r--services/usb/java/com/android/server/usb/UsbService.java36
-rw-r--r--tests/UsbTests/src/com/android/server/usb/UsbServiceTest.java81
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);
+ }
}