Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b11a2125 authored by George Chan's avatar George Chan
Browse files

Added new metrics for tracking unexpected USB events (USB is expected to be...

Added new metrics for tracking unexpected USB events (USB is expected to be disabled, yet USB activity is detected.)

Bug: 439009345
Test: atest, manual testing
Flag: android.security.aapm_feature_usb_data_protection
Change-Id: I2b3e6017cd34629d5c9b0b9c7d6622e52bef19e6
parent b94dec98
Loading
Loading
Loading
Loading
+57 −5
Original line number Diff line number Diff line
@@ -19,6 +19,10 @@ package com.android.server.security.advancedprotection.features;
import static android.app.Notification.EXTRA_SUBSTITUTE_APP_NAME;
import static android.content.Intent.ACTION_LOCKED_BOOT_COMPLETED;
import static android.hardware.usb.UsbManager.ACTION_USB_PORT_CHANGED;
import static android.hardware.usb.UsbManager.ACTION_USB_ACCESSORY_ATTACHED;
import static android.hardware.usb.UsbManager.ACTION_USB_ACCESSORY_DETACHED;
import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_ATTACHED;
import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_DETACHED;
import static android.security.advancedprotection.AdvancedProtectionManager.FEATURE_ID_DISALLOW_USB;
import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_FORCE;
import static android.hardware.usb.UsbPortStatus.DATA_STATUS_ENABLED;
@@ -80,6 +84,7 @@ import com.android.server.security.advancedprotection.AdvancedProtectionService;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
@@ -331,7 +336,7 @@ public class UsbDataAdvancedProtectionHook extends AdvancedProtectionHook {
                                mLastUsbPortStatus = portStatus;

                                if (Build.IS_DEBUGGABLE) {
                                    dumpUsbDevices(portStatus);
                                    dumpUsbDevices();
                                }

                                if (mKeyguardManager.isKeyguardLocked()) {
@@ -378,12 +383,55 @@ public class UsbDataAdvancedProtectionHook extends AdvancedProtectionHook {
                            // request dropped due to USB stack not being ready.
                            else if (ACTION_LOCKED_BOOT_COMPLETED.equals(intent.getAction())) {
                                setUsbDataSignalIfPossible(false);
                            } else if (Set.of(
                                            ACTION_USB_ACCESSORY_ATTACHED,
                                            ACTION_USB_DEVICE_ATTACHED,
                                            ACTION_USB_ACCESSORY_DETACHED,
                                            ACTION_USB_DEVICE_DETACHED)
                                    .contains(intent.getAction())) {
                                if (!mApmRequestedUsbDataStatus.get()) {
                                    Slog.d(
                                            TAG,
                                            "Unexpected USB event when USB is disabled: "
                                                    + intent.getAction());
                                    logUnexpectedUsbEvent(intent.getAction());
                                    dumpUsbDevices();
                                }
                            }
                        } catch (Exception e) {
                            Slog.e(TAG, "USB Data protection failed with: " + e.getMessage());
                        }
                    }

                    private void logUnexpectedUsbEvent(String usbEvent) {
                        FrameworkStatsLog.write(
                                FrameworkStatsLog
                                        .ADVANCED_PROTECTION_USB_STATE_CHANGE_ERROR_REPORTED,
                                //populating with default values as StatsLog cannot skip fields
                                false,
                                 -1,
                                getAtomUsbErrorType(usbEvent));
                    }

                    private int getAtomUsbErrorType(String usbEvent) {
                        switch (usbEvent) {
                            case ACTION_USB_ACCESSORY_ATTACHED:
                                return AdvancedProtectionProtoEnums
                                        .USB_ERROR_TYPE_UNEXPECTED_ACCESSORY_ATTACHED;
                            case ACTION_USB_DEVICE_ATTACHED:
                                return AdvancedProtectionProtoEnums
                                        .USB_ERROR_TYPE_UNEXPECTED_DEVICE_ATTACHED;
                            case ACTION_USB_ACCESSORY_DETACHED:
                                return AdvancedProtectionProtoEnums
                                        .USB_ERROR_TYPE_UNEXPECTED_ACCESSORY_DETACHED;
                            case ACTION_USB_DEVICE_DETACHED:
                                return AdvancedProtectionProtoEnums
                                        .USB_ERROR_TYPE_UNEXPECTED_DEVICE_DETACHED;
                            default:
                                return AdvancedProtectionProtoEnums.USB_ERROR_TYPE_UNKNOWN;
                        }
                    }

                    private void updateDelayedNotificationTask(long delayTimeMillis) {
                        if (!mDelayedNotificationHandler.hasMessagesOrCallbacks()
                                && delayTimeMillis > 0) {
@@ -446,8 +494,7 @@ public class UsbDataAdvancedProtectionHook extends AdvancedProtectionHook {
                        }
                    }

                    // TODO:(b/401540215) Remove this as part of pre-release cleanup
                    private void dumpUsbDevices(UsbPortStatus portStatus) {
                    private void dumpUsbDevices() {
                        Map<String, UsbDevice> portStatusMap = mUsbManager.getDeviceList();
                        for (UsbDevice device : portStatusMap.values()) {
                            Slog.d(TAG, "Device: " + device.getDeviceName());
@@ -649,7 +696,8 @@ public class UsbDataAdvancedProtectionHook extends AdvancedProtectionHook {
                FrameworkStatsLog.write(
                        FrameworkStatsLog.ADVANCED_PROTECTION_USB_STATE_CHANGE_ERROR_REPORTED,
                        /* desired_signal_state */ status,
                        /* retries_occurred */ usbChangeStateReattempts);
                        /* retries_occurred */ usbChangeStateReattempts,
                        AdvancedProtectionProtoEnums.USB_ERROR_TYPE_CHANGE_DATA_STATUS_FAILED);
            }
            if (status) {
                clearExistingNotification();
@@ -684,7 +732,11 @@ public class UsbDataAdvancedProtectionHook extends AdvancedProtectionHook {
        final IntentFilter filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        filter.addAction(ACTION_LOCKED_BOOT_COMPLETED);
        filter.addAction(UsbManager.ACTION_USB_PORT_CHANGED);
        filter.addAction(ACTION_USB_PORT_CHANGED);
        filter.addAction(ACTION_USB_ACCESSORY_ATTACHED);
        filter.addAction(ACTION_USB_ACCESSORY_DETACHED);
        filter.addAction(ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(ACTION_USB_DEVICE_DETACHED);

        mContext.registerReceiverAsUser(
                mUsbProtectionBroadcastReceiver, UserHandle.ALL, filter, null, null);
+48 −1
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ import android.security.Flags;
import android.security.advancedprotection.AdvancedProtectionProtoEnums;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.R;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.server.security.advancedprotection.AdvancedProtectionService;
@@ -102,6 +103,8 @@ import org.mockito.Spy;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ExecutorService;

import java.util.Map;

/**
 * Unit tests for {@link UsbDataAdvancedProtectionHook}.
 *
@@ -125,6 +128,7 @@ public class UsbDataAdvancedProtectionHookTest {
                    .mockStatic(ActivityManager.class)
                    .mockStatic(SystemProperties.class)
                    .mockStatic(Settings.Secure.class)
                    .mockStatic(FrameworkStatsLog.class)
                    .mockStatic(Intent.class)
                    .build();

@@ -339,7 +343,7 @@ public class UsbDataAdvancedProtectionHookTest {
        IntentFilter mainFilter = mIntentFilterCaptor.getAllValues().get(0);
        assertEquals(UserHandle.ALL, mUserHandleCaptor.getAllValues().get(0));

        assertEquals(2, mainFilter.countActions());
        assertEquals(6, mainFilter.countActions());
        assertTrue(mainFilter.hasAction(Intent.ACTION_LOCKED_BOOT_COMPLETED));
        assertTrue(mainFilter.hasAction(UsbManager.ACTION_USB_PORT_CHANGED));

@@ -697,6 +701,12 @@ public class UsbDataAdvancedProtectionHookTest {
        mUsbDataHook.onAdvancedProtectionChanged(false);

        verify(mUsbManagerInternal, times(3)).enableUsbDataSignal(eq(true), eq(1));
        verify(() -> FrameworkStatsLog
                .write(
                        FrameworkStatsLog.ADVANCED_PROTECTION_USB_STATE_CHANGE_ERROR_REPORTED,
                        true,
                        2,
                        AdvancedProtectionProtoEnums.USB_ERROR_TYPE_CHANGE_DATA_STATUS_FAILED));
    }

    @Test
@@ -847,4 +857,41 @@ public class UsbDataAdvancedProtectionHookTest {
                        anyInt());
        return mBroadcastReceiverCaptor.getAllValues().get(0);
    }

    @Test
    @EnableFlags(Flags.FLAG_AAPM_FEATURE_USB_DATA_PROTECTION)
    public void unexpectedUsbEvent_logsError() throws RemoteException {
        setupAndEnableFeature(false, true, true);
        mApmRequestedUsbDataStatusBoolean.set(false);
        BroadcastReceiver receiver = getAndCaptureReceiver();

        for (Map.Entry<String, Integer> event :
                Map.of(
                                UsbManager.ACTION_USB_ACCESSORY_ATTACHED,
                                AdvancedProtectionProtoEnums
                                        .USB_ERROR_TYPE_UNEXPECTED_ACCESSORY_ATTACHED,
                                UsbManager.ACTION_USB_DEVICE_ATTACHED,
                                AdvancedProtectionProtoEnums
                                        .USB_ERROR_TYPE_UNEXPECTED_DEVICE_ATTACHED,
                                UsbManager.ACTION_USB_ACCESSORY_DETACHED,
                                AdvancedProtectionProtoEnums
                                        .USB_ERROR_TYPE_UNEXPECTED_ACCESSORY_DETACHED,
                                UsbManager.ACTION_USB_DEVICE_DETACHED,
                                AdvancedProtectionProtoEnums
                                        .USB_ERROR_TYPE_UNEXPECTED_DEVICE_DETACHED)
                        .entrySet()) {
            Intent intent = new Intent(event.getKey());

            receiver.onReceive(mContext, intent);

            verify(
                    () ->
                            FrameworkStatsLog.write(
                                    FrameworkStatsLog
                                            .ADVANCED_PROTECTION_USB_STATE_CHANGE_ERROR_REPORTED,
                                    false,
                                    -1,
                                    event.getValue()));
        }
    }
}