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

Commit cd94108a authored by Lavender Lin's avatar Lavender Lin Committed by Android (Google) Code Review
Browse files

Merge changes Ibb18380b,I7629e609 into main

* changes:
  Add package monitor
  UsbService: Refactor enableUsbData() for multiple disable requesters
parents 96ff9923 b8e8bee3
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -20,3 +20,10 @@ flag {
    description: "Enable reporting USB data compliance warnings from HAL when set"
    bug: "296119135"
}

flag {
    name: "enable_usb_data_signal_staking"
    namespace: "preload_safety"
    description: "Enables signal API with staking"
    bug: "296119135"
}
 No newline at end of file
+64 −0
Original line number Diff line number Diff line
@@ -53,11 +53,14 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.usb.UsbServiceDumpProto;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
@@ -147,6 +150,7 @@ public class UsbService extends IUsbManager.Stub {
    private final UsbSettingsManager mSettingsManager;
    private final UsbPermissionManager mPermissionManager;

    static final int PACKAGE_MONITOR_OPERATION_ID = 1;
    /**
     * The user id of the current user. There might be several profiles (with separate user ids)
     * per user.
@@ -156,6 +160,10 @@ public class UsbService extends IUsbManager.Stub {

    private final Object mLock = new Object();

    // Key: USB port id
    // Value: A set of UIDs of requesters who request disabling usb data
    private final ArrayMap<String, ArraySet<Integer>> mUsbDisableRequesters = new ArrayMap<>();

    /**
     * @return the {@link UsbUserSettingsManager} for the given userId
     */
@@ -261,6 +269,10 @@ public class UsbService extends IUsbManager.Stub {
        if (mDeviceManager != null) {
            mDeviceManager.bootCompleted();
        }
        if (android.hardware.usb.flags.Flags.enableUsbDataSignalStaking()) {
            new PackageUninstallMonitor()
                    .register(mContext, UserHandle.ALL, BackgroundThread.getHandler());
        }
    }

    /** Called when a user is unlocked. */
@@ -873,6 +885,11 @@ public class UsbService extends IUsbManager.Stub {
        Objects.requireNonNull(callback, "enableUsbData: callback must not be null. opId:"
                + operationId);
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);

        if (android.hardware.usb.flags.Flags.enableUsbDataSignalStaking()) {
            if (!shouldUpdateUsbSignaling(portId, enable, Binder.getCallingUid())) return false;
        }

        final long ident = Binder.clearCallingIdentity();
        boolean wait;
        try {
@@ -892,6 +909,31 @@ public class UsbService extends IUsbManager.Stub {
        return wait;
    }

    /**
     * If enable = true, exclude UID from update list.
     * If enable = false, include UID in update list.
     * Return false if enable = true and the list is empty (no updates).
     * Return true otherwise (let downstream decide on updates).
     */
    private boolean shouldUpdateUsbSignaling(String portId, boolean enable, int uid) {
        synchronized (mUsbDisableRequesters) {
            if (!mUsbDisableRequesters.containsKey(portId)) {
                mUsbDisableRequesters.put(portId, new ArraySet<>());
            }

            ArraySet<Integer> uidsOfDisableRequesters = mUsbDisableRequesters.get(portId);

            if (enable) {
                uidsOfDisableRequesters.remove(uid);
                // re-enable USB port (return true) if there are no other disable requesters
                return uidsOfDisableRequesters.isEmpty();
            } else {
                uidsOfDisableRequesters.add(uid);
            }
        }
        return true;
    }

    @Override
    public void enableUsbDataWhileDocked(String portId, int operationId,
            IUsbOperationInternal callback) {
@@ -1344,4 +1386,26 @@ public class UsbService extends IUsbManager.Stub {
    private static String removeLastChar(String value) {
        return value.substring(0, value.length() - 1);
    }

    /**
     * Upon app removal, clear associated UIDs from the mUsbDisableRequesters list
     * and re-enable USB data signaling if no remaining apps require USB disabling.
     */
    private class PackageUninstallMonitor extends PackageMonitor {
        @Override
        public void onUidRemoved(int uid) {
            synchronized (mUsbDisableRequesters) {
                for (String portId : mUsbDisableRequesters.keySet()) {
                    ArraySet<Integer> disabledUid = mUsbDisableRequesters.get(portId);
                    if (disabledUid != null) {
                        disabledUid.remove(uid);
                        if (disabledUid.isEmpty()) {
                            enableUsbData(portId, true, PACKAGE_MONITOR_OPERATION_ID,
                                    new IUsbOperationInternal.Default());
                        }
                    }
                }
            }
        }
    }
}