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

Commit 55d10dff authored by Jerry Zhang's avatar Jerry Zhang
Browse files

Update USB settings screen

Screen now handles data role and power
role switching as separate categories.

Change the UsbBackend api to use predefined
constants. Split out data and power direction
changes into separate functions.

Add tests for new controllers and new backend
functionality.

Bug: 72829348
Test: passes
Change-Id: I28b96cf49463fa4f3a4b6be41c57d5841731fbd6
parent 34bfe742
Loading
Loading
Loading
Loading
+21 −11
Original line number Diff line number Diff line
@@ -8130,7 +8130,7 @@
    <!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user
         select what the USB connection for this device should be used for. This choice
         is for charging only. -->
    <string name="usb_use_charging_only">Charge this device</string>
    <string name="usb_use_charging_only">No data transfer</string>
    <!-- Decription of one of the choices in a dialog (with title defined in usb_use) that lets the
         user select what the USB connection for this device should be used for. This choice
         is for charging only. -->
@@ -8138,11 +8138,7 @@
    <!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user
         select what the USB connection for this device should be used for. This choice
         is for powering the other device only. -->
    <string name="usb_use_power_only">Charging connected device</string>
    <!-- Decription of one of the choices in a dialog (with title defined in usb_use) that lets the
         user select what the USB connection for this device should be used for. This choice
         is for powering the other device. -->
    <string name="usb_use_power_only_desc">Other settings unavailable when turned on</string>
    <string name="usb_use_power_only">Charge connected device</string>
    <!-- Title of one of the choices in a dialog (with title defined in usb_use) that lets the user
         select what the USB connection for this device should be used for. This choice
         is for transferring files via MTP. -->
@@ -8175,17 +8171,31 @@
         for this device should be used for. These options are more commonly used.
         Choices are usb_use_file_transfer.-->
    <string name="usb_use">Use USB for</string>
    <!-- The title used in a dialog which lets the user select what the USB connection
         for this device should be used for. These options are less commonly used.
         Choices are usb_use_tethering, usb_use_photo_transfers, usb_use_MIDI, and usb_use_power_only.-->
    <string name="usb_use_also">Also use USB for</string>
    <!-- The label that leads to the Default USB configuration window. -->
    <string name="usb_default_label">Default USB Configuration</string>
    <string name="usb_default_label">Default USB configuration</string>
    <!-- Description at the footer of the default USB configuration window that describes how the setting works. -->
    <string name="usb_default_info">When another device is connected and your phone is unlocked, these settings will be applied. Only connect to trusted devices.</string>
    <!-- Settings item title for USB preference [CHAR LIMIT=35] -->
    <string name="usb_pref">USB</string>
    <!-- Settings screen title for USB preference [CHAR LIMIT=35] -->
    <string name="usb_preference">USB Preferences</string>
    <!-- The title used in USB Preferences which lets the user select whether USB
         should be in host or device mode. -->
    <string name="usb_control_title">USB controlled by</string>
    <!-- The option in USB Preferences for selecting USB to be in host mode. This allows
         the user to connect peripherals such as a mouse or flash drive to the device. -->
    <string name="usb_control_host">Connected device</string>
    <!-- The option in USB Preferences for selecting USB to be in device mode. This allows
         the device to provide services such as file transfer or tethering to another device. -->
    <string name="usb_control_device">This device</string>
    <!-- The summary text that appears under a USB control option while it is in the process of
         switching control or power. -->
    <string name="usb_switching">Switching...</string>
    <!-- The summary text that appears under a USB control option when switching control or power has
         failed. -->
    <string name="usb_switching_failed">Couldn\'t switch</string>
    <!-- Settings item summary for USB preference when set to charging only [CHAR LIMIT=NONE] -->
    <string name="usb_summary_charging_only">Charging this device</string>
+9 −5
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright (C) 2017 The Android Open Source Project
  Copyright (C) 2018 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.
@@ -17,7 +17,8 @@
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res-auto"
    android:title="@string/device_details_title">
    android:title="@string/usb_preference"
    android:key="usb_details_fragment">

    <com.android.settings.applications.LayoutPreference
        android:key="usb_device_header"
@@ -25,11 +26,14 @@
        android:selectable="false"/>

    <PreferenceCategory
        android:key="usb_main_options"
        android:key="usb_details_data_role"
        android:title="@string/usb_control_title"/>

    <PreferenceCategory
        android:key="usb_details_functions"
        android:title="@string/usb_use"/>

    <PreferenceCategory
        android:key="usb_secondary_options"
        android:title="@string/usb_use_also"/>
        android:key="usb_details_power_role"/>

</PreferenceScreen>
+31 −24
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
package com.android.settings.connecteddevice.usb;

import android.content.Context;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.support.annotation.VisibleForTesting;

import com.android.settings.R;
@@ -38,9 +40,10 @@ public class ConnectedUsbDeviceUpdater {

    @VisibleForTesting
    UsbConnectionBroadcastReceiver.UsbConnectionListener mUsbConnectionListener =
            (connected, newMode) -> {
            (connected, functions, powerRole, dataRole) -> {
                if (connected) {
                    mUsbPreference.setSummary(getSummary(mUsbBackend.getCurrentMode()));
                    mUsbPreference.setSummary(getSummary(mUsbBackend.getCurrentFunctions(),
                            mUsbBackend.getPowerRole()));
                    mDevicePreferenceCallback.onDeviceAdded(mUsbPreference);
                } else {
                    mDevicePreferenceCallback.onDeviceRemoved(mUsbPreference);
@@ -94,28 +97,32 @@ public class ConnectedUsbDeviceUpdater {
        mUsbReceiver.register();
    }

    public static int getSummary(int mode) {
        switch (mode) {
            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE:
                return R.string.usb_summary_charging_only;
            case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE:
                return R.string.usb_summary_power_only;
            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP:
    public static int getSummary(long functions, int power) {
        switch (power) {
            case UsbPort.POWER_ROLE_SINK:
                if (functions == UsbManager.FUNCTION_MTP) {
                    return R.string.usb_summary_file_transfers;
            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP:
                } else if (functions == UsbManager.FUNCTION_RNDIS) {
                    return R.string.usb_summary_tether;
                } else if (functions == UsbManager.FUNCTION_PTP) {
                    return R.string.usb_summary_photo_transfers;
            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI:
                } else if (functions == UsbManager.FUNCTION_MIDI) {
                    return R.string.usb_summary_MIDI;
            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_TETHER:
                return R.string.usb_summary_tether;
            case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_MTP:
                } else {
                    return R.string.usb_summary_charging_only;
                }
            case UsbPort.POWER_ROLE_SOURCE:
                if (functions == UsbManager.FUNCTION_MTP) {
                    return R.string.usb_summary_file_transfers_power;
            case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_PTP:
                } else if (functions == UsbManager.FUNCTION_RNDIS) {
                    return R.string.usb_summary_tether_power;
                } else if (functions == UsbManager.FUNCTION_PTP) {
                    return R.string.usb_summary_photo_transfers_power;
            case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_MIDI:
                } else if (functions == UsbManager.FUNCTION_MIDI) {
                    return R.string.usb_summary_MIDI_power;
            case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_TETHER:
                return R.string.usb_summary_tether_power;
                } else {
                    return R.string.usb_summary_power_only;
                }
            default:
                return R.string.usb_summary_charging_only;
        }
+120 −121
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.settings.connecteddevice.usb;

import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.usb.UsbManager;
@@ -27,18 +28,13 @@ import android.support.annotation.VisibleForTesting;
import com.android.settings.wrapper.UsbManagerWrapper;
import com.android.settings.wrapper.UserManagerWrapper;

/**
 * Provides access to underlying system USB functionality.
 */
public class UsbBackend {

    public static final int MODE_POWER_MASK  = 0x01;
    public static final int MODE_POWER_SINK   = 0x00;
    public static final int MODE_POWER_SOURCE = 0x01;

    public static final int MODE_DATA_MASK  = 0x0f << 1;
    public static final int MODE_DATA_NONE   = 0;
    public static final int MODE_DATA_MTP    = 0x01 << 1;
    public static final int MODE_DATA_PTP    = 0x01 << 2;
    public static final int MODE_DATA_MIDI   = 0x01 << 3;
    public static final int MODE_DATA_TETHER   = 0x01 << 4;
    static final int PD_ROLE_SWAP_TIMEOUT_MS = 3000;
    static final int NONPD_ROLE_SWAP_TIMEOUT_MS = 15000;

    private final boolean mFileTransferRestricted;
    private final boolean mFileTransferRestrictedBySystem;
@@ -48,13 +44,13 @@ public class UsbBackend {
    private final boolean mTetheringSupported;

    private UsbManager mUsbManager;
    @VisibleForTesting
    UsbManagerWrapper mUsbManagerWrapper;
    private UsbManagerWrapper mUsbManagerWrapper;

    @Nullable
    private UsbPort mPort;
    @Nullable
    private UsbPortStatus mPortStatus;

    private Context mContext;

    public UsbBackend(Context context) {
        this(context, new UserManagerWrapper(UserManager.get(context)), null);
    }
@@ -62,7 +58,6 @@ public class UsbBackend {
    @VisibleForTesting
    public UsbBackend(Context context, UserManagerWrapper userManagerWrapper,
            UsbManagerWrapper usbManagerWrapper) {
        mContext = context;
        mUsbManager = context.getSystemService(UsbManager.class);

        mUsbManagerWrapper = usbManagerWrapper;
@@ -77,139 +72,143 @@ public class UsbBackend {

        mMidiSupported = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
        ConnectivityManager cm =
                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        mTetheringSupported = cm.isTetheringSupported();

        UsbPort[] ports = mUsbManager.getPorts();
        if (ports == null) {
            return;
        }
        // For now look for a connected port, in the future we should identify port in the
        // notification and pick based on that.
        final int N = ports.length;
        for (int i = 0; i < N; i++) {
            UsbPortStatus status = mUsbManager.getPortStatus(ports[i]);
            if (status.isConnected()) {
                mPort = ports[i];
                mPortStatus = status;
                break;
        updatePorts();
    }

    public long getCurrentFunctions() {
        return mUsbManagerWrapper.getCurrentFunctions();
    }

    public void setCurrentFunctions(long functions) {
        mUsbManager.setCurrentFunctions(functions);
    }

    public int getCurrentMode() {
        if (mPort != null) {
            int power = mPortStatus.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE
                    && mPortStatus.isConnected()
                    ? MODE_POWER_SOURCE : MODE_POWER_SINK;
            return power | getUsbDataMode();
    public long getDefaultUsbFunctions() {
        return mUsbManager.getScreenUnlockedFunctions();
    }
        return MODE_POWER_SINK | getUsbDataMode();

    public void setDefaultUsbFunctions(long functions) {
        mUsbManager.setScreenUnlockedFunctions(functions);
    }

    public int getUsbDataMode() {
        return usbFunctionToMode(mUsbManagerWrapper.getCurrentFunctions());
    public boolean areFunctionsSupported(long functions) {
        if ((!mMidiSupported && (functions & UsbManager.FUNCTION_MIDI) != 0)
                || (!mTetheringSupported && (functions & UsbManager.FUNCTION_RNDIS) != 0)) {
            return false;
        }
        return !(areFunctionDisallowed(functions) || areFunctionsDisallowedBySystem(functions));
    }

    public void setDefaultUsbMode(int mode) {
        mUsbManager.setScreenUnlockedFunctions(modeToUsbFunction(mode & MODE_DATA_MASK));
    public int getPowerRole() {
        updatePorts();
        return mPortStatus == null ? UsbPort.POWER_ROLE_NONE : mPortStatus.getCurrentPowerRole();
    }

    public int getDefaultUsbMode() {
        return usbFunctionToMode(mUsbManager.getScreenUnlockedFunctions());
    public int getDataRole() {
        updatePorts();
        return mPortStatus == null ? UsbPort.DATA_ROLE_NONE : mPortStatus.getCurrentDataRole();
    }

    public void setMode(int mode) {
    public void setPowerRole(int role) {
        int newDataRole = getDataRole();
        if (!areAllRolesSupported()) {
            switch (role) {
                case UsbPort.POWER_ROLE_SINK:
                    newDataRole = UsbPort.DATA_ROLE_DEVICE;
                    break;
                case UsbPort.POWER_ROLE_SOURCE:
                    newDataRole = UsbPort.DATA_ROLE_HOST;
                    break;
                default:
                    newDataRole = UsbPort.DATA_ROLE_NONE;
            }
        }
        if (mPort != null) {
            int powerRole = modeToPower(mode);
            // If we aren't using any data modes and we support host mode, then go to host mode
            // so maybe? the other device can provide data if it wants, otherwise go into device
            // mode because we have no choice.
            int dataRole = (mode & MODE_DATA_MASK) == MODE_DATA_NONE
                    && mPortStatus.isRoleCombinationSupported(powerRole, UsbPort.DATA_ROLE_HOST)
                    ? UsbPort.DATA_ROLE_HOST : UsbPort.DATA_ROLE_DEVICE;
            mUsbManager.setPortRoles(mPort, powerRole, dataRole);
            mUsbManager.setPortRoles(mPort, role, newDataRole);
        }
        setUsbFunction(mode & MODE_DATA_MASK);
    }

    public boolean isModeDisallowed(int mode) {
        if (mFileTransferRestricted && ((mode & MODE_DATA_MASK) == MODE_DATA_MTP
                || (mode & MODE_DATA_MASK) == MODE_DATA_PTP)) {
            return true;
        } else if (mTetheringRestricted && ((mode & MODE_DATA_MASK) == MODE_DATA_TETHER)) {
            return true;
    public void setDataRole(int role) {
        int newPowerRole = getPowerRole();
        if (!areAllRolesSupported()) {
            switch (role) {
                case UsbPort.DATA_ROLE_DEVICE:
                    newPowerRole = UsbPort.POWER_ROLE_SINK;
                    break;
                case UsbPort.DATA_ROLE_HOST:
                    newPowerRole = UsbPort.POWER_ROLE_SOURCE;
                    break;
                default:
                    newPowerRole = UsbPort.POWER_ROLE_NONE;
            }
        }
        if (mPort != null) {
            mUsbManager.setPortRoles(mPort, newPowerRole, role);
        }
        return false;
    }

    public boolean isModeDisallowedBySystem(int mode) {
        if (mFileTransferRestrictedBySystem && ((mode & MODE_DATA_MASK) == MODE_DATA_MTP
                || (mode & MODE_DATA_MASK) == MODE_DATA_PTP)) {
            return true;
        } else if (mTetheringRestrictedBySystem && ((mode & MODE_DATA_MASK) == MODE_DATA_TETHER)) {
            return true;
    public boolean areAllRolesSupported() {
        return mPort != null && mPortStatus != null
                && mPortStatus
                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE)
                && mPortStatus
                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST)
                && mPortStatus
                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE)
                && mPortStatus
                .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
    }
        return false;

    public static String usbFunctionsToString(long functions) {
        // TODO replace with UsbManager.usbFunctionsToString once supported by Roboelectric
        return Long.toBinaryString(functions);
    }

    public boolean isModeSupported(int mode) {
        if (!mMidiSupported && (mode & MODE_DATA_MASK) == MODE_DATA_MIDI) {
            return false;
    public static long usbFunctionsFromString(String functions) {
        // TODO replace with UsbManager.usbFunctionsFromString once supported by Roboelectric
        return Long.parseLong(functions, 2);
    }
        if (!mTetheringSupported && (mode & MODE_DATA_MASK) == MODE_DATA_TETHER) {
                return false;

    public static String dataRoleToString(int role) {
        return Integer.toString(role);
    }
        if (mPort != null) {
            int power = modeToPower(mode);
            if ((mode & MODE_DATA_MASK) != 0) {
                // We have a port and data, need to be in device mode.
                return mPortStatus.isRoleCombinationSupported(power,
                        UsbPort.DATA_ROLE_DEVICE);
            } else {
                // No data needed, we can do this power mode in either device or host.
                return mPortStatus.isRoleCombinationSupported(power, UsbPort.DATA_ROLE_DEVICE)
                        || mPortStatus.isRoleCombinationSupported(power, UsbPort.DATA_ROLE_HOST);
            }
        }
        // No port, support sink modes only.
        return (mode & MODE_POWER_MASK) != MODE_POWER_SOURCE;
    }

    private static int usbFunctionToMode(long functions) {
        if (functions == UsbManager.FUNCTION_MTP) {
            return MODE_DATA_MTP;
        } else if (functions == UsbManager.FUNCTION_PTP) {
            return MODE_DATA_PTP;
        } else if (functions == UsbManager.FUNCTION_MIDI) {
            return MODE_DATA_MIDI;
        } else if (functions == UsbManager.FUNCTION_RNDIS) {
            return MODE_DATA_TETHER;
        }
        return MODE_DATA_NONE;
    }

    private static long modeToUsbFunction(int mode) {
        switch (mode) {
            case MODE_DATA_MTP:
                return UsbManager.FUNCTION_MTP;
            case MODE_DATA_PTP:
                return UsbManager.FUNCTION_PTP;
            case MODE_DATA_MIDI:
                return UsbManager.FUNCTION_MIDI;
            case MODE_DATA_TETHER:
                return UsbManager.FUNCTION_RNDIS;
            default:
                return UsbManager.FUNCTION_NONE;

    public static int dataRoleFromString(String role) {
        return Integer.parseInt(role);
    }

    private boolean areFunctionDisallowed(long functions) {
        return (mFileTransferRestricted && ((functions & UsbManager.FUNCTION_MTP) != 0
                || (functions & UsbManager.FUNCTION_PTP) != 0))
                || (mTetheringRestricted && ((functions & UsbManager.FUNCTION_RNDIS) != 0));
    }

    private static int modeToPower(int mode) {
        return (mode & MODE_POWER_MASK) == MODE_POWER_SOURCE
                ? UsbPort.POWER_ROLE_SOURCE : UsbPort.POWER_ROLE_SINK;
    private boolean areFunctionsDisallowedBySystem(long functions) {
        return (mFileTransferRestrictedBySystem && ((functions & UsbManager.FUNCTION_MTP) != 0
                || (functions & UsbManager.FUNCTION_PTP) != 0))
                || (mTetheringRestrictedBySystem && ((functions & UsbManager.FUNCTION_RNDIS) != 0));
    }

    private void setUsbFunction(int mode) {
        mUsbManager.setCurrentFunctions(modeToUsbFunction(mode));
    private void updatePorts() {
        mPort = null;
        mPortStatus = null;
        UsbPort[] ports = mUsbManager.getPorts();
        if (ports == null) {
            return;
        }
        // For now look for a connected port, in the future we should identify port in the
        // notification and pick based on that.
        final int N = ports.length;
        for (int i = 0; i < N; i++) {
            UsbPortStatus status = mUsbManager.getPortStatus(ports[i]);
            if (status.isConnected()) {
                mPort = ports[i];
                mPortStatus = status;
                break;
            }
        }
    }
}
+22 −18
Original line number Diff line number Diff line
@@ -15,8 +15,6 @@
 */
package com.android.settings.connecteddevice.usb;



import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -37,15 +35,22 @@ public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements
    private Context mContext;
    private UsbConnectionListener mUsbConnectionListener;
    private boolean mListeningToUsbEvents;
    private int mMode;
    private boolean mConnected;
    private UsbBackend mUsbBackend;

    private boolean mConnected;
    private long mFunctions;
    private int mDataRole;
    private int mPowerRole;

    public UsbConnectionBroadcastReceiver(Context context,
            UsbConnectionListener usbConnectionListener, UsbBackend backend) {
        mContext = context;
        mUsbConnectionListener = usbConnectionListener;
        mUsbBackend = backend;

        mFunctions = UsbManager.FUNCTION_NONE;
        mDataRole = UsbPort.DATA_ROLE_NONE;
        mPowerRole = UsbPort.POWER_ROLE_NONE;
    }

    @Override
@@ -54,42 +59,41 @@ public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements
            mConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED)
                    || intent.getExtras().getBoolean(UsbManager.USB_HOST_CONNECTED);
            if (mConnected) {
                mMode &= UsbBackend.MODE_POWER_MASK;
                long functions = UsbManager.FUNCTION_NONE;
                if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_MTP)
                        && intent.getExtras().getBoolean(UsbManager.USB_DATA_UNLOCKED, false)) {
                    mMode |= UsbBackend.MODE_DATA_MTP;
                    functions |= UsbManager.FUNCTION_MTP;
                }
                if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_PTP)
                        && intent.getExtras().getBoolean(UsbManager.USB_DATA_UNLOCKED, false)) {
                    mMode |= UsbBackend.MODE_DATA_PTP;
                    functions |= UsbManager.FUNCTION_PTP;
                }
                if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_MIDI)) {
                    mMode |= UsbBackend.MODE_DATA_MIDI;
                    functions |= UsbManager.FUNCTION_MIDI;
                }
                if (intent.getExtras().getBoolean(UsbManager.USB_FUNCTION_RNDIS)) {
                    mMode |= UsbBackend.MODE_DATA_TETHER;
                    functions |= UsbManager.FUNCTION_RNDIS;
                }
                mFunctions = functions;
                mDataRole = mUsbBackend.getDataRole();
                mPowerRole = mUsbBackend.getPowerRole();
            }
        } else if (UsbManager.ACTION_USB_PORT_CHANGED.equals(intent.getAction())) {
            mMode &= UsbBackend.MODE_DATA_MASK;
            UsbPortStatus portStatus = intent.getExtras()
                    .getParcelable(UsbManager.EXTRA_PORT_STATUS);
            if (portStatus != null) {
                mConnected = portStatus.isConnected();
                if (mConnected) {
                    mMode |= portStatus.getCurrentPowerRole() == UsbPort.POWER_ROLE_SOURCE
                            ? UsbBackend.MODE_POWER_SOURCE : UsbBackend.MODE_POWER_SINK;
                }
                mDataRole = portStatus.getCurrentDataRole();
                mPowerRole = portStatus.getCurrentPowerRole();
            }
        }
        if (mUsbConnectionListener != null) {
            mUsbConnectionListener.onUsbConnectionChanged(mConnected, mMode);
            mUsbConnectionListener.onUsbConnectionChanged(mConnected, mFunctions, mPowerRole,
                    mDataRole);
        }
    }

    public void register() {
        if (!mListeningToUsbEvents) {
            mMode = mUsbBackend.getCurrentMode();
            mConnected = false;
            final IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(UsbManager.ACTION_USB_STATE);
@@ -124,6 +128,6 @@ public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements
     * Interface definition for a callback to be invoked when usb connection is changed.
     */
    interface UsbConnectionListener {
        void onUsbConnectionChanged(boolean connected, int newMode);
        void onUsbConnectionChanged(boolean connected, long functions, int powerRole, int dataRole);
    }
}
Loading