/*
 * Copyright (C) 2015 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 static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
import static android.hardware.usb.UsbPortStatus.MODE_DFP;
import static android.hardware.usb.UsbPortStatus.MODE_DUAL;
import static android.hardware.usb.UsbPortStatus.MODE_UFP;
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;

import static com.android.internal.usb.DumpUtils.writePort;
import static com.android.internal.usb.DumpUtils.writePortStatus;

import android.Manifest;
import android.annotation.NonNull;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.hardware.usb.ParcelableUsbPort;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
import android.hardware.usb.V1_0.IUsb;
import android.hardware.usb.V1_0.PortRole;
import android.hardware.usb.V1_0.PortRoleType;
import android.hardware.usb.V1_0.Status;
import android.hardware.usb.V1_1.PortStatus_1_1;
import android.hardware.usb.V1_2.IUsbCallback;
import android.hardware.usb.V1_2.PortStatus;
import android.hidl.manager.V1_0.IServiceManager;
import android.hidl.manager.V1_0.IServiceNotification;
import android.os.Bundle;
import android.os.Handler;
import android.os.HwBinder;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.service.usb.UsbPortInfoProto;
import android.service.usb.UsbPortManagerProto;
import android.service.usb.UsbServiceProto;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.FgThread;

import java.util.ArrayList;
import java.util.NoSuchElementException;

/**
 * Allows trusted components to control the properties of physical USB ports
 * via the IUsb.hal.
 * <p>
 * Note: This interface may not be supported on all chipsets since the USB drivers
 * must be changed to publish this information through the module.  At the moment
 * we only need this for devices with USB Type C ports to allow the System UI to
 * control USB charging and data direction.  On devices that do not support this
 * interface the list of ports may incorrectly appear to be empty
 * (but we don't care today).
 * </p>
 */
public class UsbPortManager {
    private static final String TAG = "UsbPortManager";

    private static final int MSG_UPDATE_PORTS = 1;
    private static final int MSG_SYSTEM_READY = 2;

    // All non-trivial role combinations.
    private static final int COMBO_SOURCE_HOST =
            UsbPort.combineRolesAsBit(POWER_ROLE_SOURCE, DATA_ROLE_HOST);
    private static final int COMBO_SOURCE_DEVICE = UsbPort.combineRolesAsBit(
            POWER_ROLE_SOURCE, DATA_ROLE_DEVICE);
    private static final int COMBO_SINK_HOST =
            UsbPort.combineRolesAsBit(POWER_ROLE_SINK, DATA_ROLE_HOST);
    private static final int COMBO_SINK_DEVICE = UsbPort.combineRolesAsBit(
            POWER_ROLE_SINK, DATA_ROLE_DEVICE);

    // The system context.
    private final Context mContext;

    // Proxy object for the usb hal daemon.
    @GuardedBy("mLock")
    private IUsb mProxy = null;

    // Callback when the UsbPort status is changed by the kernel.
    // Mostly due a command sent by the remote Usb device.
    private HALCallback mHALCallback = new HALCallback(null, this);

    // Cookie sent for usb hal death notification.
    private static final int USB_HAL_DEATH_COOKIE = 1000;

    // Used as the key while sending the bundle to Main thread.
    private static final String PORT_INFO = "port_info";

    // This is monitored to prevent updating the protInfo before the system
    // is ready.
    private boolean mSystemReady;

    // Mutex for all mutable shared state.
    private final Object mLock = new Object();

    // List of all ports, indexed by id.
    // Ports may temporarily have different dispositions as they are added or removed
    // but the class invariant is that this list will only contain ports with DISPOSITION_READY
    // except while updatePortsLocked() is in progress.
    private final ArrayMap<String, PortInfo> mPorts = new ArrayMap<>();

    // List of all simulated ports, indexed by id.
    private final ArrayMap<String, RawPortInfo> mSimulatedPorts =
            new ArrayMap<>();

    // Maintains the current connected status of the port.
    // Uploads logs only when the connection status is changes.
    private final ArrayMap<String, Boolean> mConnected = new ArrayMap<>();

    // Maintains the USB contaminant status that was previously logged.
    // Logs get uploaded only when contaminant presence status changes.
    private final ArrayMap<String, Integer> mContaminantStatus = new ArrayMap<>();

    private NotificationManager mNotificationManager;

    /**
     * If there currently is a notification related to contaminated USB port management
     * shown the id of the notification, or 0 if there is none.
     */
    private int mIsPortContaminatedNotificationId;

    public UsbPortManager(Context context) {
        mContext = context;
        try {
            ServiceNotification serviceNotification = new ServiceNotification();

            boolean ret = IServiceManager.getService()
                    .registerForNotifications("android.hardware.usb@1.0::IUsb",
                            "", serviceNotification);
            if (!ret) {
                logAndPrint(Log.ERROR, null,
                        "Failed to register service start notification");
            }
        } catch (RemoteException e) {
            logAndPrintException(null,
                    "Failed to register service start notification", e);
            return;
        }
        connectToProxy(null);
    }

    public void systemReady() {
	mSystemReady = true;
        if (mProxy != null) {
            try {
                mProxy.queryPortStatus();
            } catch (RemoteException e) {
                logAndPrintException(null,
                        "ServiceStart: Failed to query port status", e);
            }
        }
        mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
    }

    private void updateContaminantNotification() {
        PortInfo currentPortInfo = null;
        Resources r = mContext.getResources();
        int contaminantStatus = UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED;

        // Not handling multiple ports here. Showing the notification
        // for the first port that returns CONTAMINANT_PRESENCE_DETECTED.
        for (PortInfo portInfo : mPorts.values()) {
            contaminantStatus = portInfo.mUsbPortStatus.getContaminantDetectionStatus();
            if (contaminantStatus == UsbPortStatus.CONTAMINANT_DETECTION_DETECTED
                    || contaminantStatus == UsbPortStatus.CONTAMINANT_DETECTION_DISABLED) {
                currentPortInfo = portInfo;
                break;
            }
        }

        // Current contminant status is detected while "safe to use usb port"
        // notification is displayed. Remove safe to use usb port notification
        // and push contaminant detected notification.
        if (contaminantStatus == UsbPortStatus.CONTAMINANT_DETECTION_DETECTED
                    && mIsPortContaminatedNotificationId
                    != SystemMessage.NOTE_USB_CONTAMINANT_DETECTED) {
            if (mIsPortContaminatedNotificationId
                    == SystemMessage.NOTE_USB_CONTAMINANT_NOT_DETECTED) {
                mNotificationManager.cancelAsUser(null, mIsPortContaminatedNotificationId,
                        UserHandle.ALL);
            }

            mIsPortContaminatedNotificationId = SystemMessage.NOTE_USB_CONTAMINANT_DETECTED;
            int titleRes = com.android.internal.R.string.usb_contaminant_detected_title;
            CharSequence title = r.getText(titleRes);
            String channel = SystemNotificationChannels.ALERTS;
            CharSequence message = r.getText(
                    com.android.internal.R.string.usb_contaminant_detected_message);

            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setComponent(ComponentName.unflattenFromString(r.getString(
                    com.android.internal.R.string.config_usbContaminantActivity)));
            intent.putExtra(UsbManager.EXTRA_PORT, ParcelableUsbPort.of(currentPortInfo.mUsbPort));

            PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
                                intent, 0, null, UserHandle.CURRENT);

            Notification.Builder builder = new Notification.Builder(mContext, channel)
                    .setOngoing(true)
                    .setTicker(title)
                    .setColor(mContext.getColor(
                           com.android.internal.R.color
                           .system_notification_accent_color))
                    .setContentIntent(pi)
                    .setContentTitle(title)
                    .setContentText(message)
                    .setVisibility(Notification.VISIBILITY_PUBLIC)
                    .setSmallIcon(android.R.drawable.stat_sys_warning)
                    .setStyle(new Notification.BigTextStyle()
                    .bigText(message));
            Notification notification = builder.build();
            mNotificationManager.notifyAsUser(null, mIsPortContaminatedNotificationId, notification,
                    UserHandle.ALL);
        // No contaminant is detected but contaminant detection notification is displayed.
        // Remove contaminant detection notification and push safe to use USB port notification.
        } else if (contaminantStatus != UsbPortStatus.CONTAMINANT_DETECTION_DETECTED
                && mIsPortContaminatedNotificationId
                == SystemMessage.NOTE_USB_CONTAMINANT_DETECTED) {
            mNotificationManager.cancelAsUser(null, mIsPortContaminatedNotificationId,
                    UserHandle.ALL);
            mIsPortContaminatedNotificationId = 0;

            // Dont show safe to use notification when contaminant detection is disabled.
            // Show only when the status is changing from detected to not detected.
            if (contaminantStatus == UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED) {
                mIsPortContaminatedNotificationId =
                        SystemMessage.NOTE_USB_CONTAMINANT_NOT_DETECTED;
                int titleRes = com.android.internal.R.string.usb_contaminant_not_detected_title;
                CharSequence title = r.getText(titleRes);
                String channel = SystemNotificationChannels.ALERTS;
                CharSequence message = r.getText(
                        com.android.internal.R.string.usb_contaminant_not_detected_message);

                Notification.Builder builder = new Notification.Builder(mContext, channel)
                        .setSmallIcon(com.android.internal.R.drawable.ic_usb_48dp)
                        .setTicker(title)
                        .setColor(mContext.getColor(
                               com.android.internal.R.color
                               .system_notification_accent_color))
                        .setContentTitle(title)
                        .setContentText(message)
                        .setVisibility(Notification.VISIBILITY_PUBLIC)
                        .setStyle(new Notification.BigTextStyle()
                        .bigText(message));
                Notification notification = builder.build();
                mNotificationManager.notifyAsUser(null, mIsPortContaminatedNotificationId,
                        notification, UserHandle.ALL);
            }
        }
    }

    public UsbPort[] getPorts() {
        synchronized (mLock) {
            final int count = mPorts.size();
            final UsbPort[] result = new UsbPort[count];
            for (int i = 0; i < count; i++) {
                result[i] = mPorts.valueAt(i).mUsbPort;
            }
            return result;
        }
    }

    public UsbPortStatus getPortStatus(String portId) {
        synchronized (mLock) {
            final PortInfo portInfo = mPorts.get(portId);
            return portInfo != null ? portInfo.mUsbPortStatus : null;
        }
    }

    /**
     * Enables/disables contaminant detection.
     *
     * @param portId port identifier.
     * @param enable enable contaminant detection when set to true.
     */
    public void enableContaminantDetection(@NonNull String portId, boolean enable,
            @NonNull IndentingPrintWriter pw) {
        final PortInfo portInfo = mPorts.get(portId);
        if (portInfo == null) {
            if (pw != null) {
                pw.println("No such USB port: " + portId);
            }
            return;
        }

        if (!portInfo.mUsbPort.supportsEnableContaminantPresenceDetection()) {
            return;
        }

        if ((enable && portInfo.mUsbPortStatus.getContaminantDetectionStatus()
                != UsbPortStatus.CONTAMINANT_DETECTION_DISABLED) || (!enable
                && portInfo.mUsbPortStatus.getContaminantDetectionStatus()
                == UsbPortStatus.CONTAMINANT_DETECTION_DISABLED)
                || (portInfo.mUsbPortStatus.getContaminantDetectionStatus()
                == UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED)) {
            return;
        }

        try {
            // Oneway call into the hal. Use the castFrom method from HIDL.
            android.hardware.usb.V1_2.IUsb proxy = android.hardware.usb.V1_2.IUsb.castFrom(mProxy);
            proxy.enableContaminantPresenceDetection(portId, enable);
        } catch (RemoteException e) {
            logAndPrintException(pw, "Failed to set contaminant detection", e);
        } catch (ClassCastException e) {
            logAndPrintException(pw, "Method only applicable to V1.2 or above implementation", e);
        }
    }

    public void setPortRoles(String portId, int newPowerRole, int newDataRole,
            IndentingPrintWriter pw) {
        synchronized (mLock) {
            final PortInfo portInfo = mPorts.get(portId);
            if (portInfo == null) {
                if (pw != null) {
                    pw.println("No such USB port: " + portId);
                }
                return;
            }

            // Check whether the new role is actually supported.
            if (!portInfo.mUsbPortStatus.isRoleCombinationSupported(newPowerRole, newDataRole)) {
                logAndPrint(Log.ERROR, pw, "Attempted to set USB port into unsupported "
                        + "role combination: portId=" + portId
                        + ", newPowerRole=" + UsbPort.powerRoleToString(newPowerRole)
                        + ", newDataRole=" + UsbPort.dataRoleToString(newDataRole));
                return;
            }

            // Check whether anything actually changed.
            final int currentDataRole = portInfo.mUsbPortStatus.getCurrentDataRole();
            final int currentPowerRole = portInfo.mUsbPortStatus.getCurrentPowerRole();
            if (currentDataRole == newDataRole && currentPowerRole == newPowerRole) {
                if (pw != null) {
                    pw.println("No change.");
                }
                return;
            }

            // Determine whether we need to change the mode in order to accomplish this goal.
            // We prefer not to do this since it's more likely to fail.
            //
            // Note: Arguably it might be worth allowing the client to influence this policy
            // decision so that we could show more powerful developer facing UI but let's
            // see how far we can get without having to do that.
            final boolean canChangeMode = portInfo.mCanChangeMode;
            final boolean canChangePowerRole = portInfo.mCanChangePowerRole;
            final boolean canChangeDataRole = portInfo.mCanChangeDataRole;
            final int currentMode = portInfo.mUsbPortStatus.getCurrentMode();
            final int newMode;
            if ((!canChangePowerRole && currentPowerRole != newPowerRole)
                    || (!canChangeDataRole && currentDataRole != newDataRole)) {
                if (canChangeMode && newPowerRole == POWER_ROLE_SOURCE
                        && newDataRole == DATA_ROLE_HOST) {
                    newMode = MODE_DFP;
                } else if (canChangeMode && newPowerRole == POWER_ROLE_SINK
                        && newDataRole == DATA_ROLE_DEVICE) {
                    newMode = MODE_UFP;
                } else {
                    logAndPrint(Log.ERROR, pw, "Found mismatch in supported USB role combinations "
                            + "while attempting to change role: " + portInfo
                            + ", newPowerRole=" + UsbPort.powerRoleToString(newPowerRole)
                            + ", newDataRole=" + UsbPort.dataRoleToString(newDataRole));
                    return;
                }
            } else {
                newMode = currentMode;
            }

            // Make it happen.
            logAndPrint(Log.INFO, pw, "Setting USB port mode and role: portId=" + portId
                    + ", currentMode=" + UsbPort.modeToString(currentMode)
                    + ", currentPowerRole=" + UsbPort.powerRoleToString(currentPowerRole)
                    + ", currentDataRole=" + UsbPort.dataRoleToString(currentDataRole)
                    + ", newMode=" + UsbPort.modeToString(newMode)
                    + ", newPowerRole=" + UsbPort.powerRoleToString(newPowerRole)
                    + ", newDataRole=" + UsbPort.dataRoleToString(newDataRole));

            RawPortInfo sim = mSimulatedPorts.get(portId);
            if (sim != null) {
                // Change simulated state.
                sim.currentMode = newMode;
                sim.currentPowerRole = newPowerRole;
                sim.currentDataRole = newDataRole;
                updatePortsLocked(pw, null);
            } else if (mProxy != null) {
                if (currentMode != newMode) {
                    // Changing the mode will have the side-effect of also changing
                    // the power and data roles but it might take some time to apply
                    // and the renegotiation might fail.  Due to limitations of the USB
                    // hardware, we have no way of knowing whether it will work apriori
                    // which is why we would prefer to set the power and data roles
                    // directly instead.

                    logAndPrint(Log.ERROR, pw, "Trying to set the USB port mode: "
                            + "portId=" + portId
                            + ", newMode=" + UsbPort.modeToString(newMode));
                    PortRole newRole = new PortRole();
                    newRole.type = PortRoleType.MODE;
                    newRole.role = newMode;
                    try {
                        mProxy.switchRole(portId, newRole);
                    } catch (RemoteException e) {
                        logAndPrintException(pw, "Failed to set the USB port mode: "
                                + "portId=" + portId
                                + ", newMode=" + UsbPort.modeToString(newRole.role), e);
                    }
                } else {
                    // Change power and data role independently as needed.
                    if (currentPowerRole != newPowerRole) {
                        PortRole newRole = new PortRole();
                        newRole.type = PortRoleType.POWER_ROLE;
                        newRole.role = newPowerRole;
                        try {
                            mProxy.switchRole(portId, newRole);
                        } catch (RemoteException e) {
                            logAndPrintException(pw, "Failed to set the USB port power role: "
                                            + "portId=" + portId
                                            + ", newPowerRole=" + UsbPort.powerRoleToString
                                            (newRole.role),
                                    e);
                            return;
                        }
                    }
                    if (currentDataRole != newDataRole) {
                        PortRole newRole = new PortRole();
                        newRole.type = PortRoleType.DATA_ROLE;
                        newRole.role = newDataRole;
                        try {
                            mProxy.switchRole(portId, newRole);
                        } catch (RemoteException e) {
                            logAndPrintException(pw, "Failed to set the USB port data role: "
                                            + "portId=" + portId
                                            + ", newDataRole=" + UsbPort.dataRoleToString(newRole
                                            .role),
                                    e);
                        }
                    }
                }
            }
        }
    }

    public void addSimulatedPort(String portId, int supportedModes, IndentingPrintWriter pw) {
        synchronized (mLock) {
            if (mSimulatedPorts.containsKey(portId)) {
                pw.println("Port with same name already exists.  Please remove it first.");
                return;
            }

            pw.println("Adding simulated port: portId=" + portId
                    + ", supportedModes=" + UsbPort.modeToString(supportedModes));
            mSimulatedPorts.put(portId,
                    new RawPortInfo(portId, supportedModes));
            updatePortsLocked(pw, null);
        }
    }

    public void connectSimulatedPort(String portId, int mode, boolean canChangeMode,
            int powerRole, boolean canChangePowerRole,
            int dataRole, boolean canChangeDataRole, IndentingPrintWriter pw) {
        synchronized (mLock) {
            final RawPortInfo portInfo = mSimulatedPorts.get(portId);
            if (portInfo == null) {
                pw.println("Cannot connect simulated port which does not exist.");
                return;
            }

            if (mode == 0 || powerRole == 0 || dataRole == 0) {
                pw.println("Cannot connect simulated port in null mode, "
                        + "power role, or data role.");
                return;
            }

            if ((portInfo.supportedModes & mode) == 0) {
                pw.println("Simulated port does not support mode: " + UsbPort.modeToString(mode));
                return;
            }

            pw.println("Connecting simulated port: portId=" + portId
                    + ", mode=" + UsbPort.modeToString(mode)
                    + ", canChangeMode=" + canChangeMode
                    + ", powerRole=" + UsbPort.powerRoleToString(powerRole)
                    + ", canChangePowerRole=" + canChangePowerRole
                    + ", dataRole=" + UsbPort.dataRoleToString(dataRole)
                    + ", canChangeDataRole=" + canChangeDataRole);
            portInfo.currentMode = mode;
            portInfo.canChangeMode = canChangeMode;
            portInfo.currentPowerRole = powerRole;
            portInfo.canChangePowerRole = canChangePowerRole;
            portInfo.currentDataRole = dataRole;
            portInfo.canChangeDataRole = canChangeDataRole;
            updatePortsLocked(pw, null);
        }
    }

    /**
     * Sets contaminant status for simulated USB port objects.
     */
    public void simulateContaminantStatus(String portId, boolean detected,
            IndentingPrintWriter pw) {
        synchronized (mLock) {
            final RawPortInfo portInfo = mSimulatedPorts.get(portId);
            if (portInfo == null) {
                pw.println("Simulated port not found.");
                return;
            }

            pw.println("Simulating wet port: portId=" + portId
                    + ", wet=" + detected);
            portInfo.contaminantDetectionStatus = detected
                    ? UsbPortStatus.CONTAMINANT_DETECTION_DETECTED
                    : UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED;
            updatePortsLocked(pw, null);
        }
    }

    public void disconnectSimulatedPort(String portId, IndentingPrintWriter pw) {
        synchronized (mLock) {
            final RawPortInfo portInfo = mSimulatedPorts.get(portId);
            if (portInfo == null) {
                pw.println("Cannot disconnect simulated port which does not exist.");
                return;
            }

            pw.println("Disconnecting simulated port: portId=" + portId);
            portInfo.currentMode = 0;
            portInfo.canChangeMode = false;
            portInfo.currentPowerRole = 0;
            portInfo.canChangePowerRole = false;
            portInfo.currentDataRole = 0;
            portInfo.canChangeDataRole = false;
            updatePortsLocked(pw, null);
        }
    }

    public void removeSimulatedPort(String portId, IndentingPrintWriter pw) {
        synchronized (mLock) {
            final int index = mSimulatedPorts.indexOfKey(portId);
            if (index < 0) {
                pw.println("Cannot remove simulated port which does not exist.");
                return;
            }

            pw.println("Disconnecting simulated port: portId=" + portId);
            mSimulatedPorts.removeAt(index);
            updatePortsLocked(pw, null);
        }
    }

    public void resetSimulation(IndentingPrintWriter pw) {
        synchronized (mLock) {
            pw.println("Removing all simulated ports and ending simulation.");
            if (!mSimulatedPorts.isEmpty()) {
                mSimulatedPorts.clear();
                updatePortsLocked(pw, null);
            }
        }
    }

    /**
     * Dump the USB port state.
     */
    public void dump(DualDumpOutputStream dump, String idName, long id) {
        long token = dump.start(idName, id);

        synchronized (mLock) {
            dump.write("is_simulation_active", UsbPortManagerProto.IS_SIMULATION_ACTIVE,
                    !mSimulatedPorts.isEmpty());

            for (PortInfo portInfo : mPorts.values()) {
                portInfo.dump(dump, "usb_ports", UsbPortManagerProto.USB_PORTS);
            }
        }

        dump.end(token);
    }

    private static class HALCallback extends IUsbCallback.Stub {
        public IndentingPrintWriter pw;
        public UsbPortManager portManager;

        HALCallback(IndentingPrintWriter pw, UsbPortManager portManager) {
            this.pw = pw;
            this.portManager = portManager;
        }

        public void notifyPortStatusChange(
                ArrayList<android.hardware.usb.V1_0.PortStatus> currentPortStatus, int retval) {
            if (!portManager.mSystemReady) {
                return;
            }

            if (retval != Status.SUCCESS) {
                logAndPrint(Log.ERROR, pw, "port status enquiry failed");
                return;
            }

            ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();

            for (android.hardware.usb.V1_0.PortStatus current : currentPortStatus) {
                RawPortInfo temp = new RawPortInfo(current.portName,
                        current.supportedModes, CONTAMINANT_PROTECTION_NONE,
                        current.currentMode,
                        current.canChangeMode, current.currentPowerRole,
                        current.canChangePowerRole,
                        current.currentDataRole, current.canChangeDataRole,
                        false, CONTAMINANT_PROTECTION_NONE,
                        false, CONTAMINANT_DETECTION_NOT_SUPPORTED);
                newPortInfo.add(temp);
                logAndPrint(Log.INFO, pw, "ClientCallback V1_0: " + current.portName);
            }

            Message message = portManager.mHandler.obtainMessage();
            Bundle bundle = new Bundle();
            bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
            message.what = MSG_UPDATE_PORTS;
            message.setData(bundle);
            portManager.mHandler.sendMessage(message);
        }


        public void notifyPortStatusChange_1_1(ArrayList<PortStatus_1_1> currentPortStatus,
                int retval) {
            if (!portManager.mSystemReady) {
                return;
            }

            if (retval != Status.SUCCESS) {
                logAndPrint(Log.ERROR, pw, "port status enquiry failed");
                return;
            }

            ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();

            int numStatus = currentPortStatus.size();
            for (int i = 0; i < numStatus; i++) {
                PortStatus_1_1 current = currentPortStatus.get(i);
                RawPortInfo temp = new RawPortInfo(current.status.portName,
                        current.supportedModes, CONTAMINANT_PROTECTION_NONE,
                        current.currentMode,
                        current.status.canChangeMode, current.status.currentPowerRole,
                        current.status.canChangePowerRole,
                        current.status.currentDataRole, current.status.canChangeDataRole,
                        false, CONTAMINANT_PROTECTION_NONE,
                        false, CONTAMINANT_DETECTION_NOT_SUPPORTED);
                newPortInfo.add(temp);
                logAndPrint(Log.INFO, pw, "ClientCallback V1_1: " + current.status.portName);
            }

            Message message = portManager.mHandler.obtainMessage();
            Bundle bundle = new Bundle();
            bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
            message.what = MSG_UPDATE_PORTS;
            message.setData(bundle);
            portManager.mHandler.sendMessage(message);
        }

        public void notifyPortStatusChange_1_2(
                ArrayList<PortStatus> currentPortStatus, int retval) {
            if (!portManager.mSystemReady) {
                return;
            }

            if (retval != Status.SUCCESS) {
                logAndPrint(Log.ERROR, pw, "port status enquiry failed");
                return;
            }

            ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();

            int numStatus = currentPortStatus.size();
            for (int i = 0; i < numStatus; i++) {
                PortStatus current = currentPortStatus.get(i);
                RawPortInfo temp = new RawPortInfo(current.status_1_1.status.portName,
                        current.status_1_1.supportedModes,
                        current.supportedContaminantProtectionModes,
                        current.status_1_1.currentMode,
                        current.status_1_1.status.canChangeMode,
                        current.status_1_1.status.currentPowerRole,
                        current.status_1_1.status.canChangePowerRole,
                        current.status_1_1.status.currentDataRole,
                        current.status_1_1.status.canChangeDataRole,
                        current.supportsEnableContaminantPresenceProtection,
                        current.contaminantProtectionStatus,
                        current.supportsEnableContaminantPresenceDetection,
                        current.contaminantDetectionStatus);
                newPortInfo.add(temp);
                logAndPrint(Log.INFO, pw, "ClientCallback V1_2: "
                        + current.status_1_1.status.portName);
            }

            Message message = portManager.mHandler.obtainMessage();
            Bundle bundle = new Bundle();
            bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
            message.what = MSG_UPDATE_PORTS;
            message.setData(bundle);
            portManager.mHandler.sendMessage(message);
        }

        public void notifyRoleSwitchStatus(String portName, PortRole role, int retval) {
            if (retval == Status.SUCCESS) {
                logAndPrint(Log.INFO, pw, portName + " role switch successful");
            } else {
                logAndPrint(Log.ERROR, pw, portName + " role switch failed");
            }
        }
    }

    final class DeathRecipient implements HwBinder.DeathRecipient {
        public IndentingPrintWriter pw;

        DeathRecipient(IndentingPrintWriter pw) {
            this.pw = pw;
        }

        @Override
        public void serviceDied(long cookie) {
            if (cookie == USB_HAL_DEATH_COOKIE) {
                logAndPrint(Log.ERROR, pw, "Usb hal service died cookie: " + cookie);
                synchronized (mLock) {
                    mProxy = null;
                }
            }
        }
    }

    final class ServiceNotification extends IServiceNotification.Stub {
        @Override
        public void onRegistration(String fqName, String name, boolean preexisting) {
            logAndPrint(Log.INFO, null, "Usb hal service started " + fqName + " " + name);
            connectToProxy(null);
        }
    }

    private void connectToProxy(IndentingPrintWriter pw) {
        synchronized (mLock) {
            if (mProxy != null) {
                return;
            }

            try {
                mProxy = IUsb.getService();
                mProxy.linkToDeath(new DeathRecipient(pw), USB_HAL_DEATH_COOKIE);
                mProxy.setCallback(mHALCallback);
                mProxy.queryPortStatus();
            } catch (NoSuchElementException e) {
                logAndPrintException(pw, "connectToProxy: usb hal service not found."
                        + " Did the service fail to start?", e);
            } catch (RemoteException e) {
                logAndPrintException(pw, "connectToProxy: usb hal service not responding", e);
            }
        }
    }

    /**
     * Simulated ports directly add the new roles to mSimulatedPorts before calling.
     * USB hal callback populates and sends the newPortInfo.
     */
    private void updatePortsLocked(IndentingPrintWriter pw, ArrayList<RawPortInfo> newPortInfo) {
        for (int i = mPorts.size(); i-- > 0; ) {
            mPorts.valueAt(i).mDisposition = PortInfo.DISPOSITION_REMOVED;
        }

        // Enumerate all extant ports.
        if (!mSimulatedPorts.isEmpty()) {
            final int count = mSimulatedPorts.size();
            for (int i = 0; i < count; i++) {
                final RawPortInfo portInfo = mSimulatedPorts.valueAt(i);
                addOrUpdatePortLocked(portInfo.portId, portInfo.supportedModes,
                        portInfo.supportedContaminantProtectionModes,
                        portInfo.currentMode, portInfo.canChangeMode,
                        portInfo.currentPowerRole, portInfo.canChangePowerRole,
                        portInfo.currentDataRole, portInfo.canChangeDataRole,
                        portInfo.supportsEnableContaminantPresenceProtection,
                        portInfo.contaminantProtectionStatus,
                        portInfo.supportsEnableContaminantPresenceDetection,
                        portInfo.contaminantDetectionStatus, pw);
            }
        } else {
            for (RawPortInfo currentPortInfo : newPortInfo) {
                addOrUpdatePortLocked(currentPortInfo.portId, currentPortInfo.supportedModes,
                        currentPortInfo.supportedContaminantProtectionModes,
                        currentPortInfo.currentMode, currentPortInfo.canChangeMode,
                        currentPortInfo.currentPowerRole, currentPortInfo.canChangePowerRole,
                        currentPortInfo.currentDataRole, currentPortInfo.canChangeDataRole,
                        currentPortInfo.supportsEnableContaminantPresenceProtection,
                        currentPortInfo.contaminantProtectionStatus,
                        currentPortInfo.supportsEnableContaminantPresenceDetection,
                        currentPortInfo.contaminantDetectionStatus, pw);
            }
        }

        // Process the updates.
        // Once finished, the list of ports will only contain ports in DISPOSITION_READY.
        for (int i = mPorts.size(); i-- > 0; ) {
            final PortInfo portInfo = mPorts.valueAt(i);
            switch (portInfo.mDisposition) {
                case PortInfo.DISPOSITION_ADDED:
                    handlePortAddedLocked(portInfo, pw);
                    portInfo.mDisposition = PortInfo.DISPOSITION_READY;
                    break;
                case PortInfo.DISPOSITION_CHANGED:
                    handlePortChangedLocked(portInfo, pw);
                    portInfo.mDisposition = PortInfo.DISPOSITION_READY;
                    break;
                case PortInfo.DISPOSITION_REMOVED:
                    mPorts.removeAt(i);
                    portInfo.mUsbPortStatus = null; // must do this early
                    handlePortRemovedLocked(portInfo, pw);
                    break;
            }
        }
    }

    // Must only be called by updatePortsLocked.
    private void addOrUpdatePortLocked(String portId, int supportedModes,
            int supportedContaminantProtectionModes,
            int currentMode, boolean canChangeMode,
            int currentPowerRole, boolean canChangePowerRole,
            int currentDataRole, boolean canChangeDataRole,
            boolean supportsEnableContaminantPresenceProtection,
            int contaminantProtectionStatus,
            boolean supportsEnableContaminantPresenceDetection,
            int contaminantDetectionStatus,
            IndentingPrintWriter pw) {
        // Only allow mode switch capability for dual role ports.
        // Validate that the current mode matches the supported modes we expect.
        if ((supportedModes & MODE_DUAL) != MODE_DUAL) {
            canChangeMode = false;
            if (currentMode != 0 && currentMode != supportedModes) {
                logAndPrint(Log.WARN, pw, "Ignoring inconsistent current mode from USB "
                        + "port driver: supportedModes=" + UsbPort.modeToString(supportedModes)
                        + ", currentMode=" + UsbPort.modeToString(currentMode));
                currentMode = 0;
            }
        }

        // Determine the supported role combinations.
        // Note that the policy is designed to prefer setting the power and data
        // role independently rather than changing the mode.
        int supportedRoleCombinations = UsbPort.combineRolesAsBit(
                currentPowerRole, currentDataRole);
        if (currentMode != 0 && currentPowerRole != 0 && currentDataRole != 0) {
            if (canChangePowerRole && canChangeDataRole) {
                // Can change both power and data role independently.
                // Assume all combinations are possible.
                supportedRoleCombinations |=
                        COMBO_SOURCE_HOST | COMBO_SOURCE_DEVICE
                                | COMBO_SINK_HOST | COMBO_SINK_DEVICE;
            } else if (canChangePowerRole) {
                // Can only change power role.
                // Assume data role must remain at its current value.
                supportedRoleCombinations |= UsbPort.combineRolesAsBit(
                        POWER_ROLE_SOURCE, currentDataRole);
                supportedRoleCombinations |= UsbPort.combineRolesAsBit(
                        POWER_ROLE_SINK, currentDataRole);
            } else if (canChangeDataRole) {
                // Can only change data role.
                // Assume power role must remain at its current value.
                supportedRoleCombinations |= UsbPort.combineRolesAsBit(
                        currentPowerRole, DATA_ROLE_HOST);
                supportedRoleCombinations |= UsbPort.combineRolesAsBit(
                        currentPowerRole, DATA_ROLE_DEVICE);
            } else if (canChangeMode) {
                // Can only change the mode.
                // Assume both standard UFP and DFP configurations will become available
                // when this happens.
                supportedRoleCombinations |= COMBO_SOURCE_HOST | COMBO_SINK_DEVICE;
            }
        }

        // Update the port data structures.
        PortInfo portInfo = mPorts.get(portId);
        if (portInfo == null) {
            portInfo = new PortInfo(mContext.getSystemService(UsbManager.class),
                portId, supportedModes, supportedContaminantProtectionModes,
                supportsEnableContaminantPresenceProtection,
                supportsEnableContaminantPresenceDetection);
            portInfo.setStatus(currentMode, canChangeMode,
                    currentPowerRole, canChangePowerRole,
                    currentDataRole, canChangeDataRole,
                    supportedRoleCombinations, contaminantProtectionStatus,
                    contaminantDetectionStatus);
            mPorts.put(portId, portInfo);
        } else {
            // Validate that ports aren't changing definition out from under us.
            if (supportedModes != portInfo.mUsbPort.getSupportedModes()) {
                logAndPrint(Log.WARN, pw, "Ignoring inconsistent list of supported modes from "
                        + "USB port driver (should be immutable): "
                        + "previous=" + UsbPort.modeToString(
                        portInfo.mUsbPort.getSupportedModes())
                        + ", current=" + UsbPort.modeToString(supportedModes));
            }

            if (supportsEnableContaminantPresenceProtection
                    != portInfo.mUsbPort.supportsEnableContaminantPresenceProtection()) {
                logAndPrint(Log.WARN, pw,
                        "Ignoring inconsistent supportsEnableContaminantPresenceProtection"
                        + "USB port driver (should be immutable): "
                        + "previous="
                        + portInfo.mUsbPort.supportsEnableContaminantPresenceProtection()
                        + ", current=" + supportsEnableContaminantPresenceProtection);
            }

            if (supportsEnableContaminantPresenceDetection
                    != portInfo.mUsbPort.supportsEnableContaminantPresenceDetection()) {
                logAndPrint(Log.WARN, pw,
                        "Ignoring inconsistent supportsEnableContaminantPresenceDetection "
                        + "USB port driver (should be immutable): "
                        + "previous="
                        + portInfo.mUsbPort.supportsEnableContaminantPresenceDetection()
                        + ", current=" + supportsEnableContaminantPresenceDetection);
            }


            if (portInfo.setStatus(currentMode, canChangeMode,
                    currentPowerRole, canChangePowerRole,
                    currentDataRole, canChangeDataRole,
                    supportedRoleCombinations, contaminantProtectionStatus,
                    contaminantDetectionStatus)) {
                portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
            } else {
                portInfo.mDisposition = PortInfo.DISPOSITION_READY;
            }
        }
    }

    private void handlePortLocked(PortInfo portInfo, IndentingPrintWriter pw) {
        sendPortChangedBroadcastLocked(portInfo);
        logToStatsd(portInfo, pw);
        updateContaminantNotification();
    }

    private void handlePortAddedLocked(PortInfo portInfo, IndentingPrintWriter pw) {
        logAndPrint(Log.INFO, pw, "USB port added: " + portInfo);
        handlePortLocked(portInfo, pw);
    }

    private void handlePortChangedLocked(PortInfo portInfo, IndentingPrintWriter pw) {
        logAndPrint(Log.INFO, pw, "USB port changed: " + portInfo);
        enableContaminantDetectionIfNeeded(portInfo, pw);
        handlePortLocked(portInfo, pw);
    }

    private void handlePortRemovedLocked(PortInfo portInfo, IndentingPrintWriter pw) {
        logAndPrint(Log.INFO, pw, "USB port removed: " + portInfo);
        handlePortLocked(portInfo, pw);
    }

    // Constants have to be converted between USB HAL V1.2 ContaminantDetectionStatus
    // to usb.proto as proto guidelines recommends 0 to be UNKNOWN/UNSUPPORTTED
    // whereas HAL policy is against a loosely defined constant.
    private static int convertContaminantDetectionStatusToProto(int contaminantDetectionStatus) {
        switch (contaminantDetectionStatus) {
            case UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED:
                return UsbServiceProto.CONTAMINANT_STATUS_NOT_SUPPORTED;
            case UsbPortStatus.CONTAMINANT_DETECTION_DISABLED:
                return UsbServiceProto.CONTAMINANT_STATUS_DISABLED;
            case UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED:
                return UsbServiceProto.CONTAMINANT_STATUS_NOT_DETECTED;
            case UsbPortStatus.CONTAMINANT_DETECTION_DETECTED:
                return UsbServiceProto.CONTAMINANT_STATUS_DETECTED;
            default:
                return UsbServiceProto.CONTAMINANT_STATUS_UNKNOWN;
        }
    }

    private void sendPortChangedBroadcastLocked(PortInfo portInfo) {
        final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_CHANGED);
        intent.addFlags(
                Intent.FLAG_RECEIVER_FOREGROUND |
                        Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        intent.putExtra(UsbManager.EXTRA_PORT, ParcelableUsbPort.of(portInfo.mUsbPort));
        intent.putExtra(UsbManager.EXTRA_PORT_STATUS, portInfo.mUsbPortStatus);

        // Guard against possible reentrance by posting the broadcast from the handler
        // instead of from within the critical section.
        mHandler.post(() -> mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                Manifest.permission.MANAGE_USB));
    }

    private void enableContaminantDetectionIfNeeded(PortInfo portInfo, IndentingPrintWriter pw) {
        if (!mConnected.containsKey(portInfo.mUsbPort.getId())) {
            return;
        }

        if (mConnected.get(portInfo.mUsbPort.getId())
                && !portInfo.mUsbPortStatus.isConnected()
                && portInfo.mUsbPortStatus.getContaminantDetectionStatus()
                == UsbPortStatus.CONTAMINANT_DETECTION_DISABLED) {
            // Contaminant detection might have been temporarily disabled by the user
            // through SystemUI.
            // Re-enable contaminant detection when the accessory is unplugged.
            enableContaminantDetection(portInfo.mUsbPort.getId(), true, pw);
        }
    }

    private void logToStatsd(PortInfo portInfo, IndentingPrintWriter pw) {
        // Port is removed
        if (portInfo.mUsbPortStatus == null) {
            if (mConnected.containsKey(portInfo.mUsbPort.getId())) {
                //Previous logged a connected. Set it to disconnected.
                if (mConnected.get(portInfo.mUsbPort.getId())) {
                    FrameworkStatsLog.write(FrameworkStatsLog.USB_CONNECTOR_STATE_CHANGED,
                            FrameworkStatsLog
                                    .USB_CONNECTOR_STATE_CHANGED__STATE__STATE_DISCONNECTED,
                            portInfo.mUsbPort.getId(), portInfo.mLastConnectDurationMillis);
                }
                mConnected.remove(portInfo.mUsbPort.getId());
            }

            if (mContaminantStatus.containsKey(portInfo.mUsbPort.getId())) {
                //Previous logged a contaminant detected. Set it to not detected.
                if ((mContaminantStatus.get(portInfo.mUsbPort.getId())
                        == UsbPortStatus.CONTAMINANT_DETECTION_DETECTED)) {
                    FrameworkStatsLog.write(FrameworkStatsLog.USB_CONTAMINANT_REPORTED,
                            portInfo.mUsbPort.getId(),
                            convertContaminantDetectionStatusToProto(
                                    UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED));
                }
                mContaminantStatus.remove(portInfo.mUsbPort.getId());
            }
            return;
        }

        if (!mConnected.containsKey(portInfo.mUsbPort.getId())
                || (mConnected.get(portInfo.mUsbPort.getId())
                != portInfo.mUsbPortStatus.isConnected())) {
            mConnected.put(portInfo.mUsbPort.getId(), portInfo.mUsbPortStatus.isConnected());
            FrameworkStatsLog.write(FrameworkStatsLog.USB_CONNECTOR_STATE_CHANGED,
                    portInfo.mUsbPortStatus.isConnected()
                    ? FrameworkStatsLog.USB_CONNECTOR_STATE_CHANGED__STATE__STATE_CONNECTED :
                    FrameworkStatsLog.USB_CONNECTOR_STATE_CHANGED__STATE__STATE_DISCONNECTED,
                    portInfo.mUsbPort.getId(), portInfo.mLastConnectDurationMillis);
        }

        if (!mContaminantStatus.containsKey(portInfo.mUsbPort.getId())
                || (mContaminantStatus.get(portInfo.mUsbPort.getId())
                != portInfo.mUsbPortStatus.getContaminantDetectionStatus())) {
            mContaminantStatus.put(portInfo.mUsbPort.getId(),
                    portInfo.mUsbPortStatus.getContaminantDetectionStatus());
            FrameworkStatsLog.write(FrameworkStatsLog.USB_CONTAMINANT_REPORTED,
                    portInfo.mUsbPort.getId(),
                    convertContaminantDetectionStatusToProto(
                            portInfo.mUsbPortStatus.getContaminantDetectionStatus()));
        }
    }

    private static void logAndPrint(int priority, IndentingPrintWriter pw, String msg) {
        Slog.println(priority, TAG, msg);
        if (pw != null) {
            pw.println(msg);
        }
    }

    private static void logAndPrintException(IndentingPrintWriter pw, String msg, Exception e) {
        Slog.e(TAG, msg, e);
        if (pw != null) {
            pw.println(msg + e);
        }
    }

    private final Handler mHandler = new Handler(FgThread.get().getLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_PORTS: {
                    Bundle b = msg.getData();
                    ArrayList<RawPortInfo> PortInfo = b.getParcelableArrayList(PORT_INFO);
                    synchronized (mLock) {
                        updatePortsLocked(null, PortInfo);
                    }
                    break;
                }
                case MSG_SYSTEM_READY: {
                    mNotificationManager = (NotificationManager)
                            mContext.getSystemService(Context.NOTIFICATION_SERVICE);
                    break;
                }
            }
        }
    };

    /**
     * Describes a USB port.
     */
    private static final class PortInfo {
        public static final int DISPOSITION_ADDED = 0;
        public static final int DISPOSITION_CHANGED = 1;
        public static final int DISPOSITION_READY = 2;
        public static final int DISPOSITION_REMOVED = 3;

        public final UsbPort mUsbPort;
        public UsbPortStatus mUsbPortStatus;
        public boolean mCanChangeMode;
        public boolean mCanChangePowerRole;
        public boolean mCanChangeDataRole;
        // default initialized to 0 which means added
        public int mDisposition;
        // Tracks elapsedRealtime() of when the port was connected
        public long mConnectedAtMillis;
        // 0 when port is connected. Else reports the last connected duration
        public long mLastConnectDurationMillis;

        PortInfo(@NonNull UsbManager usbManager, @NonNull String portId, int supportedModes,
                int supportedContaminantProtectionModes,
                boolean supportsEnableContaminantPresenceDetection,
                boolean supportsEnableContaminantPresenceProtection) {
            mUsbPort = new UsbPort(usbManager, portId, supportedModes,
                    supportedContaminantProtectionModes,
                    supportsEnableContaminantPresenceDetection,
                    supportsEnableContaminantPresenceProtection);
        }

        public boolean setStatus(int currentMode, boolean canChangeMode,
                int currentPowerRole, boolean canChangePowerRole,
                int currentDataRole, boolean canChangeDataRole,
                int supportedRoleCombinations) {
            boolean dispositionChanged = false;

            mCanChangeMode = canChangeMode;
            mCanChangePowerRole = canChangePowerRole;
            mCanChangeDataRole = canChangeDataRole;
            if (mUsbPortStatus == null
                    || mUsbPortStatus.getCurrentMode() != currentMode
                    || mUsbPortStatus.getCurrentPowerRole() != currentPowerRole
                    || mUsbPortStatus.getCurrentDataRole() != currentDataRole
                    || mUsbPortStatus.getSupportedRoleCombinations()
                    != supportedRoleCombinations) {
                mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
                        supportedRoleCombinations, UsbPortStatus.CONTAMINANT_PROTECTION_NONE,
                        UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED);
                dispositionChanged = true;
            }

            if (mUsbPortStatus.isConnected() && mConnectedAtMillis == 0) {
                mConnectedAtMillis = SystemClock.elapsedRealtime();
                mLastConnectDurationMillis = 0;
            } else if (!mUsbPortStatus.isConnected() && mConnectedAtMillis != 0) {
                mLastConnectDurationMillis = SystemClock.elapsedRealtime() - mConnectedAtMillis;
                mConnectedAtMillis = 0;
            }

            return dispositionChanged;
        }

        public boolean setStatus(int currentMode, boolean canChangeMode,
                int currentPowerRole, boolean canChangePowerRole,
                int currentDataRole, boolean canChangeDataRole,
                int supportedRoleCombinations, int contaminantProtectionStatus,
                int contaminantDetectionStatus) {
            boolean dispositionChanged = false;

            mCanChangeMode = canChangeMode;
            mCanChangePowerRole = canChangePowerRole;
            mCanChangeDataRole = canChangeDataRole;
            if (mUsbPortStatus == null
                    || mUsbPortStatus.getCurrentMode() != currentMode
                    || mUsbPortStatus.getCurrentPowerRole() != currentPowerRole
                    || mUsbPortStatus.getCurrentDataRole() != currentDataRole
                    || mUsbPortStatus.getSupportedRoleCombinations()
                    != supportedRoleCombinations
                    || mUsbPortStatus.getContaminantProtectionStatus()
                    != contaminantProtectionStatus
                    || mUsbPortStatus.getContaminantDetectionStatus()
                    != contaminantDetectionStatus) {
                mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
                        supportedRoleCombinations, contaminantProtectionStatus,
                        contaminantDetectionStatus);
                dispositionChanged = true;
            }

            if (mUsbPortStatus.isConnected() && mConnectedAtMillis == 0) {
                mConnectedAtMillis = SystemClock.elapsedRealtime();
                mLastConnectDurationMillis = 0;
            } else if (!mUsbPortStatus.isConnected() && mConnectedAtMillis != 0) {
                mLastConnectDurationMillis = SystemClock.elapsedRealtime() - mConnectedAtMillis;
                mConnectedAtMillis = 0;
            }

            return dispositionChanged;
        }

        void dump(@NonNull DualDumpOutputStream dump, @NonNull String idName, long id) {
            long token = dump.start(idName, id);

            writePort(dump, "port", UsbPortInfoProto.PORT, mUsbPort);
            writePortStatus(dump, "status", UsbPortInfoProto.STATUS, mUsbPortStatus);
            dump.write("can_change_mode", UsbPortInfoProto.CAN_CHANGE_MODE, mCanChangeMode);
            dump.write("can_change_power_role", UsbPortInfoProto.CAN_CHANGE_POWER_ROLE,
                    mCanChangePowerRole);
            dump.write("can_change_data_role", UsbPortInfoProto.CAN_CHANGE_DATA_ROLE,
                    mCanChangeDataRole);
            dump.write("connected_at_millis",
                    UsbPortInfoProto.CONNECTED_AT_MILLIS, mConnectedAtMillis);
            dump.write("last_connect_duration_millis",
                    UsbPortInfoProto.LAST_CONNECT_DURATION_MILLIS, mLastConnectDurationMillis);

            dump.end(token);
        }

        @Override
        public String toString() {
            return "port=" + mUsbPort + ", status=" + mUsbPortStatus
                    + ", canChangeMode=" + mCanChangeMode
                    + ", canChangePowerRole=" + mCanChangePowerRole
                    + ", canChangeDataRole=" + mCanChangeDataRole
                    + ", connectedAtMillis=" + mConnectedAtMillis
                    + ", lastConnectDurationMillis=" + mLastConnectDurationMillis;
        }
    }

    /**
     * Used for storing the raw data from the kernel
     * Values of the member variables mocked directly incase of emulation.
     */
    private static final class RawPortInfo implements Parcelable {
        public final String portId;
        public final int supportedModes;
        public final int supportedContaminantProtectionModes;
        public int currentMode;
        public boolean canChangeMode;
        public int currentPowerRole;
        public boolean canChangePowerRole;
        public int currentDataRole;
        public boolean canChangeDataRole;
        public boolean supportsEnableContaminantPresenceProtection;
        public int contaminantProtectionStatus;
        public boolean supportsEnableContaminantPresenceDetection;
        public int contaminantDetectionStatus;

        RawPortInfo(String portId, int supportedModes) {
            this.portId = portId;
            this.supportedModes = supportedModes;
            this.supportedContaminantProtectionModes = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
            this.supportsEnableContaminantPresenceProtection = false;
            this.contaminantProtectionStatus = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
            this.supportsEnableContaminantPresenceDetection = false;
            this.contaminantDetectionStatus = UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
        }

        RawPortInfo(String portId, int supportedModes, int supportedContaminantProtectionModes,
                int currentMode, boolean canChangeMode,
                int currentPowerRole, boolean canChangePowerRole,
                int currentDataRole, boolean canChangeDataRole,
                boolean supportsEnableContaminantPresenceProtection,
                int contaminantProtectionStatus,
                boolean supportsEnableContaminantPresenceDetection,
                int contaminantDetectionStatus) {
            this.portId = portId;
            this.supportedModes = supportedModes;
            this.supportedContaminantProtectionModes = supportedContaminantProtectionModes;
            this.currentMode = currentMode;
            this.canChangeMode = canChangeMode;
            this.currentPowerRole = currentPowerRole;
            this.canChangePowerRole = canChangePowerRole;
            this.currentDataRole = currentDataRole;
            this.canChangeDataRole = canChangeDataRole;
            this.supportsEnableContaminantPresenceProtection =
                    supportsEnableContaminantPresenceProtection;
            this.contaminantProtectionStatus = contaminantProtectionStatus;
            this.supportsEnableContaminantPresenceDetection =
                    supportsEnableContaminantPresenceDetection;
            this.contaminantDetectionStatus = contaminantDetectionStatus;
        }


        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(portId);
            dest.writeInt(supportedModes);
            dest.writeInt(supportedContaminantProtectionModes);
            dest.writeInt(currentMode);
            dest.writeByte((byte) (canChangeMode ? 1 : 0));
            dest.writeInt(currentPowerRole);
            dest.writeByte((byte) (canChangePowerRole ? 1 : 0));
            dest.writeInt(currentDataRole);
            dest.writeByte((byte) (canChangeDataRole ? 1 : 0));
            dest.writeBoolean(supportsEnableContaminantPresenceProtection);
            dest.writeInt(contaminantProtectionStatus);
            dest.writeBoolean(supportsEnableContaminantPresenceDetection);
            dest.writeInt(contaminantDetectionStatus);
        }

        public static final Parcelable.Creator<RawPortInfo> CREATOR =
                new Parcelable.Creator<RawPortInfo>() {
            @Override
            public RawPortInfo createFromParcel(Parcel in) {
                String id = in.readString();
                int supportedModes = in.readInt();
                int supportedContaminantProtectionModes = in.readInt();
                int currentMode = in.readInt();
                boolean canChangeMode = in.readByte() != 0;
                int currentPowerRole = in.readInt();
                boolean canChangePowerRole = in.readByte() != 0;
                int currentDataRole = in.readInt();
                boolean canChangeDataRole = in.readByte() != 0;
                boolean supportsEnableContaminantPresenceProtection = in.readBoolean();
                int contaminantProtectionStatus = in.readInt();
                boolean supportsEnableContaminantPresenceDetection = in.readBoolean();
                int contaminantDetectionStatus = in.readInt();
                return new RawPortInfo(id, supportedModes,
                        supportedContaminantProtectionModes, currentMode, canChangeMode,
                        currentPowerRole, canChangePowerRole,
                        currentDataRole, canChangeDataRole,
                        supportsEnableContaminantPresenceProtection,
                        contaminantProtectionStatus,
                        supportsEnableContaminantPresenceDetection,
                        contaminantDetectionStatus);
            }

            @Override
            public RawPortInfo[] newArray(int size) {
                return new RawPortInfo[size];
            }
        };
    }
}
