private void setSelectedRouteLocked(IMediaRouterClient client,
            String routeId, boolean explicit) {
        ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
        if (clientRecord != null) {
            final String oldRouteId = clientRecord.mSelectedRouteId;
            if (!Objects.equals(routeId, oldRouteId)) {
                if (DEBUG) {
                    Slog.d(TAG, clientRecord + ": Set selected route, routeId=" + routeId
                            + ", oldRouteId=" + oldRouteId
                            + ", explicit=" + explicit);
                }

                clientRecord.mSelectedRouteId = routeId;
                if (explicit) {
                    // Any app can disconnect from the globally selected route.
                    if (oldRouteId != null) {
                        clientRecord.mUserRecord.mHandler.obtainMessage(
                                UserHandler.MSG_UNSELECT_ROUTE, oldRouteId).sendToTarget();
                    }
                    // Only let the system connect to new global routes for now.
                    // A similar check exists in the display manager for wifi display.
                    if (routeId != null && clientRecord.mTrusted) {
                        clientRecord.mUserRecord.mHandler.obtainMessage(
                                UserHandler.MSG_SELECT_ROUTE, routeId).sendToTarget();
                    }
                }
            }
        }
    }
 private MediaRouterClientState getStateLocked(IMediaRouterClient client) {
     ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
     if (clientRecord != null) {
         return clientRecord.getState();
     }
     return null;
 }
예제 #3
0
  /**
   * Remove process record for voice extension service.
   *
   * @param pid process id
   * @param uid user id
   */
  public void removeProcessRecordLocked(int pid, int uid) {
    ProcessRecord record = mProcessRecords.get(pid);

    if (record != null && record.getUid() == uid) {
      mProcessRecords.remove(pid);
    }
  }
  @Override
  public Cursor querySearchDocuments(String rootId, String query, String[] projection)
      throws FileNotFoundException {
    final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));

    final File parent;
    synchronized (mRootsLock) {
      parent = mRoots.get(rootId).path;
    }

    final LinkedList<File> pending = new LinkedList<File>();
    pending.add(parent);
    while (!pending.isEmpty() && result.getCount() < 24) {
      final File file = pending.removeFirst();
      if (file.isDirectory()) {
        for (File child : file.listFiles()) {
          pending.add(child);
        }
      }
      if (file.getName().toLowerCase().contains(query)) {
        includeFile(result, null, file);
      }
    }
    return result;
  }
  private File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
    final int splitIndex = docId.indexOf(':', 1);
    final String tag = docId.substring(0, splitIndex);
    final String path = docId.substring(splitIndex + 1);

    RootInfo root;
    synchronized (mRootsLock) {
      root = mRoots.get(tag);
    }
    if (root == null) {
      throw new FileNotFoundException("No root for " + tag);
    }

    File target = visible ? root.visiblePath : root.path;
    if (target == null) {
      return null;
    }
    if (!target.exists()) {
      target.mkdirs();
    }
    target = new File(target, path);
    if (!target.exists()) {
      throw new FileNotFoundException("Missing file for " + docId + " at " + target);
    }
    return target;
  }
 private final void remove_all_objects(ArrayMap<String, F[]> map, String name, Object object) {
   F[] array = map.get(name);
   if (array != null) {
     int LAST = array.length - 1;
     while (LAST >= 0 && array[LAST] == null) {
       LAST--;
     }
     for (int idx = LAST; idx >= 0; idx--) {
       if (array[idx] == object) {
         final int remain = LAST - idx;
         if (remain > 0) {
           System.arraycopy(array, idx + 1, array, idx, remain);
         }
         array[LAST] = null;
         LAST--;
       }
     }
     if (LAST < 0) {
       map.remove(name);
     } else if (LAST < (array.length / 2)) {
       F[] newa = newArray(LAST + 2);
       System.arraycopy(array, 0, newa, 0, LAST + 1);
       map.put(name, newa);
     }
   }
 }
    private void registerClientLocked(IMediaRouterClient client,
            int pid, String packageName, int userId, boolean trusted) {
        final IBinder binder = client.asBinder();
        ClientRecord clientRecord = mAllClientRecords.get(binder);
        if (clientRecord == null) {
            boolean newUser = false;
            UserRecord userRecord = mUserRecords.get(userId);
            if (userRecord == null) {
                userRecord = new UserRecord(userId);
                newUser = true;
            }
            clientRecord = new ClientRecord(userRecord, client, pid, packageName, trusted);
            try {
                binder.linkToDeath(clientRecord, 0);
            } catch (RemoteException ex) {
                throw new RuntimeException("Media router client died prematurely.", ex);
            }

            if (newUser) {
                mUserRecords.put(userId, userRecord);
                initializeUserLocked(userRecord);
            }

            userRecord.mClientRecords.add(clientRecord);
            mAllClientRecords.put(binder, clientRecord);
            initializeClientLocked(clientRecord);
        }
    }
예제 #8
0
 public <T extends RxViewDispatch> void unregisterRxError(final T object) {
   String tag = object.getClass().getSimpleName() + "_error";
   Subscription subscription = mRxActionMap.get(tag);
   if (subscription != null && !subscription.isUnsubscribed()) {
     subscription.unsubscribe();
     mRxActionMap.remove(tag);
   }
 }
 /**
  * Put an int value into the meta data. Custom keys may be used, but if the METADATA_KEYs
  * defined in this class are used they may only be one of the following:
  *
  * <ul>
  *   <li>{@link #METADATA_KEY_RDS_PTY}
  *   <li>{@link #METADATA_KEY_RBDS_PTY}
  * </ul>
  *
  * @param key The key for referencing this value
  * @param value The int value to store
  * @return the same Builder instance
  */
 public Builder putInt(String key, int value) {
   if (!METADATA_KEYS_TYPE.containsKey(key)
       || METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_INT) {
     throw new IllegalArgumentException("The " + key + " key cannot be used to put a long");
   }
   mBundle.putInt(key, value);
   return this;
 }
 /**
  * Put a {@link Bitmap} into the meta data. Custom keys may be used, but if the METADATA_KEYs
  * defined in this class are used they may only be one of the following:
  *
  * <ul>
  *   <li>{@link #METADATA_KEY_ICON}
  *   <li>{@link #METADATA_KEY_ART}
  * </ul>
  *
  * <p>
  *
  * @param key The key for referencing this value
  * @param value The Bitmap to store
  * @return the same Builder instance
  */
 public Builder putBitmap(String key, Bitmap value) {
   if (!METADATA_KEYS_TYPE.containsKey(key)
       || METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
     throw new IllegalArgumentException("The " + key + " key cannot be used to put a Bitmap");
   }
   mBundle.putParcelable(key, value);
   return this;
 }
 int putStringFromNative(int nativeKey, String value) {
   String key = getKeyFromNativeKey(nativeKey);
   if (!METADATA_KEYS_TYPE.containsKey(key) || METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
     return -1;
   }
   mBundle.putString(key, value);
   return 0;
 }
예제 #12
0
  /**
   * Get the process record with the same pid & uid.
   *
   * @param pid process id
   * @param uid user id
   * @return process record
   */
  public ProcessRecord getProcessRecordLocked(int pid, int uid) {
    ProcessRecord record = mProcessRecords.get(pid);

    if (record != null && record.getUid() != uid) {
      record = null;
      // mProcessRecords.remove(pid);
    }
    return record;
  }
 Request removeRequest(IBinder reqInterface) {
   synchronized (this) {
     Request req = mActiveRequests.get(reqInterface);
     if (req != null) {
       mActiveRequests.remove(req);
     }
     return req;
   }
 }
 private void requestUpdateVolumeLocked(IMediaRouterClient client,
         String routeId, int direction) {
     final IBinder binder = client.asBinder();
     ClientRecord clientRecord = mAllClientRecords.get(binder);
     if (clientRecord != null) {
         clientRecord.mUserRecord.mHandler.obtainMessage(
                 UserHandler.MSG_REQUEST_UPDATE_VOLUME, direction, 0, routeId).sendToTarget();
     }
 }
 /**
  * Returns the Transition for the given scene being entered. The result depends not only on the
  * given scene, but also the scene which the {@link Scene#getSceneRoot() sceneRoot} of the Scene
  * is currently in.
  *
  * @param scene The scene being entered
  * @return The Transition to be used for the given scene change. If no Transition was specified
  *     for this scene change, the default transition will be used instead.
  */
 private Transition getTransition(Scene scene) {
   Transition transition = null;
   ViewGroup sceneRoot = scene.getSceneRoot();
   if (sceneRoot != null) {
     // TODO: cached in Scene instead? long-term, cache in View itself
     Scene currScene = Scene.getCurrentScene(sceneRoot);
     if (currScene != null) {
       ArrayMap<Scene, Transition> sceneTransitionMap = mScenePairTransitions.get(scene);
       if (sceneTransitionMap != null) {
         transition = sceneTransitionMap.get(currScene);
         if (transition != null) {
           return transition;
         }
       }
     }
   }
   transition = mSceneTransitions.get(scene);
   return (transition != null) ? transition : sDefaultTransition;
 }
 public boolean isSnoozed(String packageName) {
   final String key = snoozeKey(packageName, mUser);
   Long snoozedUntil = mSnoozedPackages.get(key);
   if (snoozedUntil != null) {
     if (snoozedUntil > SystemClock.elapsedRealtime()) {
       if (DEBUG) Log.v(TAG, key + " snoozed");
       return true;
     }
     mSnoozedPackages.remove(packageName);
   }
   return false;
 }
  private void startObserving(File file, Uri notifyUri) {
    synchronized (mObservers) {
      DirectoryObserver observer = mObservers.get(file);
      if (observer == null) {
        observer = new DirectoryObserver(file, getContext().getContentResolver(), notifyUri);
        observer.startWatching();
        mObservers.put(file, observer);
      }
      observer.mRefCount++;

      if (LOG_INOTIFY) Log.d(TAG, "after start: " + observer);
    }
  }
  public void connectSimulatedPort(
      String portId,
      int mode,
      boolean canChangeMode,
      int powerRole,
      boolean canChangePowerRole,
      int dataRole,
      boolean canChangeDataRole,
      IndentingPrintWriter pw) {
    synchronized (mLock) {
      final SimulatedPortInfo 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.mSupportedModes & 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.mCurrentMode = mode;
      portInfo.mCanChangeMode = canChangeMode;
      portInfo.mCurrentPowerRole = powerRole;
      portInfo.mCanChangePowerRole = canChangePowerRole;
      portInfo.mCurrentDataRole = dataRole;
      portInfo.mCanChangeDataRole = canChangeDataRole;
      updatePortsLocked(pw);
    }
  }
  private void stopObserving(File file) {
    synchronized (mObservers) {
      DirectoryObserver observer = mObservers.get(file);
      if (observer == null) return;

      observer.mRefCount--;
      if (observer.mRefCount == 0) {
        mObservers.remove(file);
        observer.stopWatching();
      }

      if (LOG_INOTIFY) Log.d(TAG, "after stop: " + observer);
    }
  }
  public void disconnectSimulatedPort(String portId, IndentingPrintWriter pw) {
    synchronized (mLock) {
      final SimulatedPortInfo 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.mCurrentMode = 0;
      portInfo.mCanChangeMode = false;
      portInfo.mCurrentPowerRole = 0;
      portInfo.mCanChangePowerRole = false;
      portInfo.mCurrentDataRole = 0;
      portInfo.mCanChangeDataRole = false;
      updatePortsLocked(pw);
    }
  }
 int putBitmapFromNative(int nativeKey, byte[] value) {
   String key = getKeyFromNativeKey(nativeKey);
   if (!METADATA_KEYS_TYPE.containsKey(key)
       || METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
     return -1;
   }
   Bitmap bmp = null;
   try {
     bmp = BitmapFactory.decodeByteArray(value, 0, value.length);
   } catch (Exception e) {
   } finally {
     if (bmp == null) {
       return -1;
     }
     mBundle.putParcelable(key, bmp);
     return 0;
   }
 }
 private void createPkgMap(
     ArrayList<ProcStatsEntry> procEntries,
     ProcessDataCollection bgTotals,
     ProcessDataCollection runTotals) {
   // Combine processes into packages.
   ArrayMap<String, ProcStatsPackageEntry> pkgMap = new ArrayMap<>();
   for (int i = procEntries.size() - 1; i >= 0; i--) {
     ProcStatsEntry proc = procEntries.get(i);
     proc.evaluateTargetPackage(mPm, mStats, bgTotals, runTotals, sEntryCompare, mUseUss);
     ProcStatsPackageEntry pkg = pkgMap.get(proc.mBestTargetPackage);
     if (pkg == null) {
       pkg = new ProcStatsPackageEntry(proc.mBestTargetPackage, memTotalTime);
       pkgMap.put(proc.mBestTargetPackage, pkg);
       pkgEntries.add(pkg);
     }
     pkg.addEntry(proc);
   }
 }
 private Transition getTransition(Scene scene) {
   Transition transition;
   ViewGroup sceneRoot = scene.getSceneRoot();
   if (sceneRoot != null) {
     Scene currScene = Scene.getCurrentScene(sceneRoot);
     if (currScene != null) {
       ArrayMap<Scene, Transition> sceneTransitionMap =
           (ArrayMap) this.mScenePairTransitions.get(scene);
       if (sceneTransitionMap != null) {
         transition = (Transition) sceneTransitionMap.get(currScene);
         if (transition != null) {
           return transition;
         }
       }
     }
   }
   transition = (Transition) this.mSceneTransitions.get(scene);
   return transition != null ? transition : sDefaultTransition;
 }
 private final void addFilter(ArrayMap<String, F[]> map, String name, F filter) {
   F[] array = map.get(name);
   if (array == null) {
     array = newArray(2);
     map.put(name, array);
     array[0] = filter;
   } else {
     final int N = array.length;
     int i = N;
     while (i > 0 && array[i - 1] == null) {
       i--;
     }
     if (i < N) {
       array[i] = filter;
     } else {
       F[] newa = newArray((N * 3) / 2);
       System.arraycopy(array, 0, newa, 0, N);
       newa[N] = filter;
       map.put(name, newa);
     }
   }
 }
예제 #25
0
  /**
   * Get running process information from AMS and get the same pid , uid process.
   *
   * @param pid process id
   * @param uid user id
   * @return process record
   */
  private ProcessRecord createProcessRecordLocked(int pid, int uid) {

    ProcessRecord record = mProcessRecords.get(pid);
    if (record == null) {
      try {
        List<RunningAppProcessInfo> procInfos = mActivityManager.getRunningAppProcesses();
        if (procInfos != null && procInfos.size() > 0) {
          for (RunningAppProcessInfo info : procInfos) {
            if (info.pid == pid && info.uid == uid) {
              record = new ProcessRecord(info.pid, info.uid, info.processName);
              mProcessRecords.put(pid, record);
              break;
            }
          }
        }
      } catch (RemoteException e) {
        // TODO Auto-generated catch block
        Log.e(TAG, "IPC Exception while get process info from AMS " + e.toString());
      }
    }

    return record;
  }
예제 #26
0
 public <T extends RxViewDispatch> void registerRxError(final T object) {
   String tag = object.getClass().getSimpleName() + "_error";
   Subscription subscription = mRxActionMap.get(tag);
   if (subscription == null || subscription.isUnsubscribed()) {
     mRxActionMap.put(
         tag,
         mBus.get()
             .filter(
                 new Func1<Object, Boolean>() {
                   @Override
                   public Boolean call(Object obj) {
                     return obj instanceof RxError;
                   }
                 })
             .subscribe(
                 new Action1<Object>() {
                   @Override
                   public void call(Object obj) {
                     object.onRxError((RxError) obj);
                   }
                 }));
   }
 }
    private void setDiscoveryRequestLocked(IMediaRouterClient client,
            int routeTypes, boolean activeScan) {
        final IBinder binder = client.asBinder();
        ClientRecord clientRecord = mAllClientRecords.get(binder);
        if (clientRecord != null) {
            // Only let the system discover remote display routes for now.
            if (!clientRecord.mTrusted) {
                routeTypes &= ~MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
            }

            if (clientRecord.mRouteTypes != routeTypes
                    || clientRecord.mActiveScan != activeScan) {
                if (DEBUG) {
                    Slog.d(TAG, clientRecord + ": Set discovery request, routeTypes=0x"
                            + Integer.toHexString(routeTypes) + ", activeScan=" + activeScan);
                }
                clientRecord.mRouteTypes = routeTypes;
                clientRecord.mActiveScan = activeScan;
                clientRecord.mUserRecord.mHandler.sendEmptyMessage(
                        UserHandler.MSG_UPDATE_DISCOVERY_REQUEST);
            }
        }
    }
 public UsbPortStatus getPortStatus(String portId) {
   synchronized (mLock) {
     final PortInfo portInfo = mPorts.get(portId);
     return portInfo != null ? portInfo.mUsbPortStatus : null;
   }
 }
  // Must only be called by updatePortsLocked.
  private void addOrUpdatePortLocked(
      String portId,
      int supportedModes,
      int currentMode,
      boolean canChangeMode,
      int currentPowerRole,
      boolean canChangePowerRole,
      int currentDataRole,
      boolean canChangeDataRole,
      IndentingPrintWriter pw) {
    // Only allow mode switch capability for dual role ports.
    // Validate that the current mode matches the supported modes we expect.
    if (supportedModes != UsbPort.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(UsbPort.POWER_ROLE_SOURCE, currentDataRole);
        supportedRoleCombinations |=
            UsbPort.combineRolesAsBit(UsbPort.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, UsbPort.DATA_ROLE_HOST);
        supportedRoleCombinations |=
            UsbPort.combineRolesAsBit(currentPowerRole, UsbPort.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(portId, supportedModes);
      portInfo.setStatus(
          currentMode,
          canChangeMode,
          currentPowerRole,
          canChangePowerRole,
          currentDataRole,
          canChangeDataRole,
          supportedRoleCombinations);
      mPorts.put(portId, portInfo);
    } else {
      // Sanity check 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 (portInfo.setStatus(
          currentMode,
          canChangeMode,
          currentPowerRole,
          canChangePowerRole,
          currentDataRole,
          canChangeDataRole,
          supportedRoleCombinations)) {
        portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
      } else {
        portInfo.mDisposition = PortInfo.DISPOSITION_READY;
      }
    }
  }
  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 == UsbPort.POWER_ROLE_SOURCE
            && newDataRole == UsbPort.DATA_ROLE_HOST) {
          newMode = UsbPort.MODE_DFP;
        } else if (canChangeMode
            && newPowerRole == UsbPort.POWER_ROLE_SINK
            && newDataRole == UsbPort.DATA_ROLE_DEVICE) {
          newMode = UsbPort.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));

      SimulatedPortInfo sim = mSimulatedPorts.get(portId);
      if (sim != null) {
        // Change simulated state.
        sim.mCurrentMode = newMode;
        sim.mCurrentPowerRole = newPowerRole;
        sim.mCurrentDataRole = newDataRole;
      } else if (mHaveKernelSupport) {
        // Change actual state.
        final File portDir = new File(SYSFS_CLASS, portId);
        if (!portDir.exists()) {
          logAndPrint(Log.ERROR, pw, "USB port not found: portId=" + portId);
          return;
        }

        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.
          if (!writeFile(
              portDir,
              SYSFS_PORT_MODE,
              newMode == UsbPort.MODE_DFP ? PORT_MODE_DFP : PORT_MODE_UFP)) {
            logAndPrint(
                Log.ERROR,
                pw,
                "Failed to set the USB port mode: "
                    + "portId="
                    + portId
                    + ", newMode="
                    + UsbPort.modeToString(newMode));
            return;
          }
        } else {
          // Change power and data role independently as needed.
          if (currentPowerRole != newPowerRole) {
            if (!writeFile(
                portDir,
                SYSFS_PORT_POWER_ROLE,
                newPowerRole == UsbPort.POWER_ROLE_SOURCE
                    ? PORT_POWER_ROLE_SOURCE
                    : PORT_POWER_ROLE_SINK)) {
              logAndPrint(
                  Log.ERROR,
                  pw,
                  "Failed to set the USB port power role: "
                      + "portId="
                      + portId
                      + ", newPowerRole="
                      + UsbPort.powerRoleToString(newPowerRole));
              return;
            }
          }
          if (currentDataRole != newDataRole) {
            if (!writeFile(
                portDir,
                SYSFS_PORT_DATA_ROLE,
                newDataRole == UsbPort.DATA_ROLE_HOST
                    ? PORT_DATA_ROLE_HOST
                    : PORT_DATA_ROLE_DEVICE)) {
              logAndPrint(
                  Log.ERROR,
                  pw,
                  "Failed to set the USB port data role: "
                      + "portId="
                      + portId
                      + ", newDataRole="
                      + UsbPort.dataRoleToString(newDataRole));
              return;
            }
          }
        }
      }
      updatePortsLocked(pw);
    }
  }