• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.hardware.usb;
18 
19 import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL;
20 import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_NOT_SUPPORTED;
21 import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_PORT_MISMATCH;
22 import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_SUCCESS;
23 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DETECTED;
24 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DISABLED;
25 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED;
26 import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
27 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
28 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
29 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
30 import static android.hardware.usb.UsbPortStatus.MODE_AUDIO_ACCESSORY;
31 import static android.hardware.usb.UsbPortStatus.MODE_DEBUG_ACCESSORY;
32 import static android.hardware.usb.UsbPortStatus.MODE_DFP;
33 import static android.hardware.usb.UsbPortStatus.MODE_DUAL;
34 import static android.hardware.usb.UsbPortStatus.MODE_NONE;
35 import static android.hardware.usb.UsbPortStatus.MODE_UFP;
36 import static android.hardware.usb.UsbPortStatus.POWER_BRICK_STATUS_DISCONNECTED;
37 import static android.hardware.usb.UsbPortStatus.POWER_BRICK_STATUS_UNKNOWN;
38 import static android.hardware.usb.UsbPortStatus.POWER_BRICK_STATUS_CONNECTED;
39 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
40 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
41 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
42 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_UNKNOWN;
43 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_ENABLED;
44 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_OVERHEAT;
45 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_CONTAMINANT;
46 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DOCK;
47 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_FORCE;
48 import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_DEBUG;
49 
50 import android.Manifest;
51 import android.annotation.CallbackExecutor;
52 import android.annotation.CheckResult;
53 import android.annotation.IntDef;
54 import android.annotation.NonNull;
55 import android.annotation.Nullable;
56 import android.annotation.RequiresPermission;
57 import android.annotation.SystemApi;
58 import android.hardware.usb.UsbOperationInternal;
59 import android.hardware.usb.V1_0.Constants;
60 import android.os.Binder;
61 import android.util.Log;
62 
63 import com.android.internal.util.Preconditions;
64 
65 import java.lang.annotation.Retention;
66 import java.lang.annotation.RetentionPolicy;
67 import java.util.Objects;
68 import java.util.concurrent.atomic.AtomicInteger;
69 import java.util.concurrent.Executor;
70 import java.util.function.Consumer;
71 
72 /**
73  * Represents a physical USB port and describes its characteristics.
74  *
75  * @hide
76  */
77 @SystemApi
78 public final class UsbPort {
79     private static final String TAG = "UsbPort";
80     private final String mId;
81     private final int mSupportedModes;
82     private final UsbManager mUsbManager;
83     private final int mSupportedContaminantProtectionModes;
84     private final boolean mSupportsEnableContaminantPresenceProtection;
85     private final boolean mSupportsEnableContaminantPresenceDetection;
86 
87     private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES;
88     /**
89      * Points to the first power role in the IUsb HAL.
90      */
91     private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE;
92 
93     /**
94      * Counter for tracking UsbOperation operations.
95      */
96     private static final AtomicInteger sUsbOperationCount = new AtomicInteger();
97 
98     /**
99      * The {@link #enableUsbData} request was successfully completed.
100      */
101     public static final int ENABLE_USB_DATA_SUCCESS = 0;
102 
103     /**
104      * The {@link #enableUsbData} request failed due to internal error.
105      */
106     public static final int ENABLE_USB_DATA_ERROR_INTERNAL = 1;
107 
108     /**
109      * The {@link #enableUsbData} request failed as it's not supported.
110      */
111     public static final int ENABLE_USB_DATA_ERROR_NOT_SUPPORTED = 2;
112 
113     /**
114      * The {@link #enableUsbData} request failed as port id mismatched.
115      */
116     public static final int ENABLE_USB_DATA_ERROR_PORT_MISMATCH = 3;
117 
118     /**
119      * The {@link #enableUsbData} request failed due to other reasons.
120      */
121     public static final int ENABLE_USB_DATA_ERROR_OTHER = 4;
122 
123     /** @hide */
124     @IntDef(prefix = { "ENABLE_USB_DATA_" }, value = {
125             ENABLE_USB_DATA_SUCCESS,
126             ENABLE_USB_DATA_ERROR_INTERNAL,
127             ENABLE_USB_DATA_ERROR_NOT_SUPPORTED,
128             ENABLE_USB_DATA_ERROR_PORT_MISMATCH,
129             ENABLE_USB_DATA_ERROR_OTHER
130     })
131     @Retention(RetentionPolicy.SOURCE)
132     @interface EnableUsbDataStatus{}
133 
134     /**
135      * The {@link #enableLimitPowerTransfer} request was successfully completed.
136      */
137     public static final int ENABLE_LIMIT_POWER_TRANSFER_SUCCESS = 0;
138 
139     /**
140      * The {@link #enableLimitPowerTransfer} request failed due to internal error.
141      */
142     public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL = 1;
143 
144     /**
145      * The {@link #enableLimitPowerTransfer} request failed as it's not supported.
146      */
147     public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED = 2;
148 
149     /**
150      * The {@link #enableLimitPowerTransfer} request failed as port id mismatched.
151      */
152     public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH = 3;
153 
154     /**
155      * The {@link #enableLimitPowerTransfer} request failed due to other reasons.
156      */
157     public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER = 4;
158 
159     /** @hide */
160     @IntDef(prefix = { "ENABLE_LIMIT_POWER_TRANSFER_" }, value = {
161             ENABLE_LIMIT_POWER_TRANSFER_SUCCESS,
162             ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL,
163             ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED,
164             ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH,
165             ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER
166     })
167     @Retention(RetentionPolicy.SOURCE)
168     @interface EnableLimitPowerTransferStatus{}
169 
170     /**
171      * The {@link #enableUsbDataWhileDocked} request was successfully completed.
172      */
173     public static final int ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS = 0;
174 
175     /**
176      * The {@link #enableUsbDataWhileDocked} request failed due to internal error.
177      */
178     public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL = 1;
179 
180     /**
181      * The {@link #enableUsbDataWhileDocked} request failed as it's not supported.
182      */
183     public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED = 2;
184 
185     /**
186      * The {@link #enableUsbDataWhileDocked} request failed as port id mismatched.
187      */
188     public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH = 3;
189 
190     /**
191      * The {@link #enableUsbDataWhileDocked} request failed as data is still enabled.
192      */
193     public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED = 4;
194 
195     /**
196      * The {@link #enableUsbDataWhileDocked} request failed due to other reasons.
197      */
198     public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER = 5;
199 
200     /**
201      * The {@link #resetUsbPort} request was successfully completed.
202      */
203     public static final int RESET_USB_PORT_SUCCESS = 0;
204 
205     /**
206      * The {@link #resetUsbPort} request failed due to internal error.
207      */
208     public static final int RESET_USB_PORT_ERROR_INTERNAL = 1;
209 
210     /**
211      * The {@link #resetUsbPort} request failed as it's not supported.
212      */
213     public static final int RESET_USB_PORT_ERROR_NOT_SUPPORTED = 2;
214 
215     /**
216      * The {@link #resetUsbPort} request failed as port id mismatched.
217      */
218     public static final int RESET_USB_PORT_ERROR_PORT_MISMATCH = 3;
219 
220     /**
221      * The {@link #resetUsbPort} request failed due to other reasons.
222      */
223     public static final int RESET_USB_PORT_ERROR_OTHER = 4;
224 
225     /** @hide */
226     @IntDef(prefix = { "RESET_USB_PORT_" }, value = {
227             RESET_USB_PORT_SUCCESS,
228             RESET_USB_PORT_ERROR_INTERNAL,
229             RESET_USB_PORT_ERROR_NOT_SUPPORTED,
230             RESET_USB_PORT_ERROR_PORT_MISMATCH,
231             RESET_USB_PORT_ERROR_OTHER
232     })
233     @Retention(RetentionPolicy.SOURCE)
234     @interface ResetUsbPortStatus{}
235 
236     /** @hide */
237     @IntDef(prefix = { "ENABLE_USB_DATA_WHILE_DOCKED_" }, value = {
238             ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS,
239             ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL,
240             ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED,
241             ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH,
242             ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED,
243             ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER
244     })
245     @Retention(RetentionPolicy.SOURCE)
246     @interface EnableUsbDataWhileDockedStatus{}
247 
248     /** @hide */
UsbPort(@onNull UsbManager usbManager, @NonNull String id, int supportedModes, int supportedContaminantProtectionModes, boolean supportsEnableContaminantPresenceProtection, boolean supportsEnableContaminantPresenceDetection)249     public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes,
250             int supportedContaminantProtectionModes,
251             boolean supportsEnableContaminantPresenceProtection,
252             boolean supportsEnableContaminantPresenceDetection) {
253         Objects.requireNonNull(id);
254         Preconditions.checkFlagsArgument(supportedModes,
255                 MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY);
256 
257         mUsbManager = usbManager;
258         mId = id;
259         mSupportedModes = supportedModes;
260         mSupportedContaminantProtectionModes = supportedContaminantProtectionModes;
261         mSupportsEnableContaminantPresenceProtection =
262                 supportsEnableContaminantPresenceProtection;
263         mSupportsEnableContaminantPresenceDetection =
264                 supportsEnableContaminantPresenceDetection;
265     }
266 
267     /**
268      * Gets the unique id of the port.
269      *
270      * @return The unique id of the port; not intended for display.
271      *
272      * @hide
273      */
getId()274     public String getId() {
275         return mId;
276     }
277 
278     /**
279      * Gets the supported modes of the port.
280      * <p>
281      * The actual mode of the port may vary depending on what is plugged into it.
282      * </p>
283      *
284      * @return The supported modes: one of {@link UsbPortStatus#MODE_DFP},
285      * {@link UsbPortStatus#MODE_UFP}, or {@link UsbPortStatus#MODE_DUAL}.
286      *
287      * @hide
288      */
getSupportedModes()289     public int getSupportedModes() {
290         return mSupportedModes;
291     }
292 
293    /**
294      * Gets the supported port proctection modes when the port is contaminated.
295      * <p>
296      * The actual mode of the port is decided by the hardware
297      * </p>
298      *
299      * @hide
300      */
getSupportedContaminantProtectionModes()301     public int getSupportedContaminantProtectionModes() {
302         return mSupportedContaminantProtectionModes;
303     }
304 
305    /**
306      * Tells if UsbService can enable/disable contaminant presence protection.
307      *
308      * @hide
309      */
supportsEnableContaminantPresenceProtection()310     public boolean supportsEnableContaminantPresenceProtection() {
311         return mSupportsEnableContaminantPresenceProtection;
312     }
313 
314    /**
315      * Tells if UsbService can enable/disable contaminant presence detection.
316      *
317      * @hide
318      */
supportsEnableContaminantPresenceDetection()319     public boolean supportsEnableContaminantPresenceDetection() {
320         return mSupportsEnableContaminantPresenceDetection;
321     }
322 
323     /**
324      * Gets the status of this USB port.
325      *
326      * @return The status of the this port, or {@code null} if port is unknown.
327      */
328     @RequiresPermission(Manifest.permission.MANAGE_USB)
getStatus()329     public @Nullable UsbPortStatus getStatus() {
330         return mUsbManager.getPortStatus(this);
331     }
332 
333     /**
334      * Sets the desired role combination of the port.
335      * <p>
336      * The supported role combinations depend on what is connected to the port and may be
337      * determined by consulting
338      * {@link UsbPortStatus#isRoleCombinationSupported UsbPortStatus.isRoleCombinationSupported}.
339      * </p><p>
340      * Note: This function is asynchronous and may fail silently without applying
341      * the operationed changes.  If this function does cause a status change to occur then
342      * a {@link UsbManager#ACTION_USB_PORT_CHANGED} broadcast will be sent.
343      * </p>
344      *
345      * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE} or
346      *                  {@link UsbPortStatus#POWER_ROLE_SINK}, or
347      *                  {@link UsbPortStatus#POWER_ROLE_NONE} if no power role.
348      * @param dataRole The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST} or
349      *                 {@link UsbPortStatus#DATA_ROLE_DEVICE}, or
350      *                 {@link UsbPortStatus#DATA_ROLE_NONE} if no data role.
351      */
352     @RequiresPermission(Manifest.permission.MANAGE_USB)
setRoles(@sbPortStatus.UsbPowerRole int powerRole, @UsbPortStatus.UsbDataRole int dataRole)353     public void setRoles(@UsbPortStatus.UsbPowerRole int powerRole,
354             @UsbPortStatus.UsbDataRole int dataRole) {
355         UsbPort.checkRoles(powerRole, dataRole);
356 
357         mUsbManager.setPortRoles(this, powerRole, dataRole);
358     }
359 
360     /**
361      * Reset Usb data on the port.
362      *
363      * @param executor Executor for the callback.
364      * @param consumer A consumer that consumes the reset result.
365      *                 {@link #RESET_USB_PORT_SUCCESS} when request completes
366      *                 successfully or
367      *                 {@link #RESET_USB_PORT_ERROR_INTERNAL} when request
368      *                 fails due to internal error or
369      *                 {@link RESET_USB_PORT_ERROR_NOT_SUPPORTED} when not
370      *                 supported or
371      *                 {@link RESET_USB_PORT_ERROR_PORT_MISMATCH} when request
372      *                 fails due to port id mismatch or
373      *                 {@link RESET_USB_PORT_ERROR_OTHER} when fails due to
374      *                  other reasons.
375      */
376     @CheckResult
377     @RequiresPermission(Manifest.permission.MANAGE_USB)
resetUsbPort(@onNull @allbackExecutor Executor executor, @NonNull @ResetUsbPortStatus Consumer<Integer> consumer)378     public void resetUsbPort(@NonNull @CallbackExecutor Executor executor,
379             @NonNull @ResetUsbPortStatus Consumer<Integer> consumer) {
380         // UID is added To minimize operationID overlap between two different packages.
381         int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
382         Log.i(TAG, "resetUsbPort opId:" + operationId);
383         UsbOperationInternal opCallback =
384                 new UsbOperationInternal(operationId, mId, executor, consumer);
385         mUsbManager.resetUsbPort(this, operationId, opCallback);
386     }
387 
388     /**
389      * Enables/Disables Usb data on the port.
390      *
391      * @param enable When true enables USB data if disabled.
392      *               When false disables USB data if enabled.
393      * @return       {@link #ENABLE_USB_DATA_SUCCESS} when request completes successfully or
394      *               {@link #ENABLE_USB_DATA_ERROR_INTERNAL} when request fails due to internal
395      *               error or
396      *               {@link ENABLE_USB_DATA_ERROR_NOT_SUPPORTED} when not supported or
397      *               {@link ENABLE_USB_DATA_ERROR_PORT_MISMATCH} when request fails due to port id
398      *               mismatch or
399      *               {@link ENABLE_USB_DATA_ERROR_OTHER} when fails due to other reasons.
400      */
401     @CheckResult
402     @RequiresPermission(Manifest.permission.MANAGE_USB)
enableUsbData(boolean enable)403     public @EnableUsbDataStatus int enableUsbData(boolean enable) {
404         // UID is added To minimize operationID overlap between two different packages.
405         int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
406         Log.i(TAG, "enableUsbData opId:" + operationId
407                 + " callingUid:" + Binder.getCallingUid());
408         UsbOperationInternal opCallback =
409                 new UsbOperationInternal(operationId, mId);
410         if (mUsbManager.enableUsbData(this, enable, operationId, opCallback) == true) {
411             opCallback.waitForOperationComplete();
412         }
413 
414         int result = opCallback.getStatus();
415         switch (result) {
416             case USB_OPERATION_SUCCESS:
417                 return ENABLE_USB_DATA_SUCCESS;
418             case USB_OPERATION_ERROR_INTERNAL:
419                 return ENABLE_USB_DATA_ERROR_INTERNAL;
420             case USB_OPERATION_ERROR_NOT_SUPPORTED:
421                 return ENABLE_USB_DATA_ERROR_NOT_SUPPORTED;
422             case USB_OPERATION_ERROR_PORT_MISMATCH:
423                 return ENABLE_USB_DATA_ERROR_PORT_MISMATCH;
424             default:
425                 return ENABLE_USB_DATA_ERROR_OTHER;
426         }
427     }
428 
429     /**
430      * Enables Usb data when disabled due to {@link UsbPort#DATA_STATUS_DISABLED_DOCK}
431      *
432      * @return {@link #ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS} when request completes successfully or
433      *         {@link #ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL} when request fails due to
434      *         internal error or
435      *         {@link ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED} when not supported or
436      *         {@link ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH} when request fails due to
437      *         port id mismatch or
438      *         {@link ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED} when request fails as data
439      *         is still enabled or
440      *         {@link ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER} when fails due to other reasons.
441      */
442     @CheckResult
443     @RequiresPermission(Manifest.permission.MANAGE_USB)
enableUsbDataWhileDocked()444     public @EnableUsbDataWhileDockedStatus int enableUsbDataWhileDocked() {
445         // UID is added To minimize operationID overlap between two different packages.
446         int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
447         Log.i(TAG, "enableUsbData opId:" + operationId
448                 + " callingUid:" + Binder.getCallingUid());
449         UsbPortStatus portStatus = getStatus();
450         if (portStatus != null &&
451                 (portStatus.getUsbDataStatus() & DATA_STATUS_DISABLED_DOCK) !=
452                  DATA_STATUS_DISABLED_DOCK) {
453             return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_DATA_ENABLED;
454         }
455 
456         UsbOperationInternal opCallback =
457                 new UsbOperationInternal(operationId, mId);
458         mUsbManager.enableUsbDataWhileDocked(this, operationId, opCallback);
459                 opCallback.waitForOperationComplete();
460         int result = opCallback.getStatus();
461         switch (result) {
462             case USB_OPERATION_SUCCESS:
463                 return ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS;
464             case USB_OPERATION_ERROR_INTERNAL:
465                 return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_INTERNAL;
466             case USB_OPERATION_ERROR_NOT_SUPPORTED:
467                 return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_NOT_SUPPORTED;
468             case USB_OPERATION_ERROR_PORT_MISMATCH:
469                 return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH;
470             default:
471                 return ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER;
472         }
473     }
474 
475     /**
476      * Limits power transfer In and out of the port.
477      * <p>
478      * Disables charging and limits sourcing power(when permitted by the USB spec) until
479      * port disconnect event.
480      * </p>
481      * @param enable limits power transfer when true.
482      * @return {@link #ENABLE_LIMIT_POWER_TRANSFER_SUCCESS} when request completes successfully or
483      *         {@link #ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL} when request fails due to
484      *         internal error or
485      *         {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED} when not supported or
486      *         {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH} when request fails due to
487      *         port id mismatch or
488      *         {@link ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER} when fails due to other reasons.
489      */
490     @CheckResult
491     @RequiresPermission(Manifest.permission.MANAGE_USB)
enableLimitPowerTransfer(boolean enable)492     public @EnableLimitPowerTransferStatus int enableLimitPowerTransfer(boolean enable) {
493         // UID is added To minimize operationID overlap between two different packages.
494         int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
495         Log.i(TAG, "enableLimitPowerTransfer opId:" + operationId
496                 + " callingUid:" + Binder.getCallingUid());
497         UsbOperationInternal opCallback =
498                 new UsbOperationInternal(operationId, mId);
499         mUsbManager.enableLimitPowerTransfer(this, enable, operationId, opCallback);
500         opCallback.waitForOperationComplete();
501         int result = opCallback.getStatus();
502         switch (result) {
503             case USB_OPERATION_SUCCESS:
504                 return ENABLE_LIMIT_POWER_TRANSFER_SUCCESS;
505             case USB_OPERATION_ERROR_INTERNAL:
506                 return ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL;
507             case USB_OPERATION_ERROR_NOT_SUPPORTED:
508                 return ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED;
509             case USB_OPERATION_ERROR_PORT_MISMATCH:
510                 return ENABLE_LIMIT_POWER_TRANSFER_ERROR_PORT_MISMATCH;
511             default:
512                 return ENABLE_LIMIT_POWER_TRANSFER_ERROR_OTHER;
513         }
514     }
515 
516     /**
517      * @hide
518      **/
enableContaminantDetection(boolean enable)519     public void enableContaminantDetection(boolean enable) {
520         mUsbManager.enableContaminantDetection(this, enable);
521     }
522     /**
523      * Combines one power and one data role together into a unique value with
524      * exactly one bit set.  This can be used to efficiently determine whether
525      * a combination of roles is supported by testing whether that bit is present
526      * in a bit-field.
527      *
528      * @param powerRole The desired power role: {@link UsbPortStatus#POWER_ROLE_SOURCE}
529      *                  or {@link UsbPortStatus#POWER_ROLE_SINK}, or 0 if no power role.
530      * @param dataRole  The desired data role: {@link UsbPortStatus#DATA_ROLE_HOST}
531      *                  or {@link UsbPortStatus#DATA_ROLE_DEVICE}, or 0 if no data role.
532      * @hide
533      */
combineRolesAsBit(int powerRole, int dataRole)534     public static int combineRolesAsBit(int powerRole, int dataRole) {
535         checkRoles(powerRole, dataRole);
536         final int index = ((powerRole - POWER_ROLE_OFFSET) * NUM_DATA_ROLES) + dataRole;
537         return 1 << index;
538     }
539 
540     /** @hide */
modeToString(int mode)541     public static String modeToString(int mode) {
542         StringBuilder modeString = new StringBuilder();
543         if (mode == MODE_NONE) {
544             return "none";
545         }
546 
547         if ((mode & MODE_DUAL) == MODE_DUAL) {
548             modeString.append("dual, ");
549         } else {
550             if ((mode & MODE_DFP) == MODE_DFP) {
551                 modeString.append("dfp, ");
552             } else if ((mode & MODE_UFP) == MODE_UFP) {
553                 modeString.append("ufp, ");
554             }
555         }
556         if ((mode & MODE_AUDIO_ACCESSORY) == MODE_AUDIO_ACCESSORY) {
557             modeString.append("audio_acc, ");
558         }
559         if ((mode & MODE_DEBUG_ACCESSORY) == MODE_DEBUG_ACCESSORY) {
560             modeString.append("debug_acc, ");
561         }
562 
563         if (modeString.length() == 0) {
564             return Integer.toString(mode);
565         }
566         return modeString.substring(0, modeString.length() - 2);
567     }
568 
569     /** @hide */
powerRoleToString(int role)570     public static String powerRoleToString(int role) {
571         switch (role) {
572             case POWER_ROLE_NONE:
573                 return "no-power";
574             case POWER_ROLE_SOURCE:
575                 return "source";
576             case POWER_ROLE_SINK:
577                 return "sink";
578             default:
579                 return Integer.toString(role);
580         }
581     }
582 
583     /** @hide */
dataRoleToString(int role)584     public static String dataRoleToString(int role) {
585         switch (role) {
586             case DATA_ROLE_NONE:
587                 return "no-data";
588             case DATA_ROLE_HOST:
589                 return "host";
590             case DATA_ROLE_DEVICE:
591                 return "device";
592             default:
593                 return Integer.toString(role);
594         }
595     }
596 
597     /** @hide */
contaminantPresenceStatusToString(int contaminantPresenceStatus)598     public static String contaminantPresenceStatusToString(int contaminantPresenceStatus) {
599         switch (contaminantPresenceStatus) {
600             case CONTAMINANT_DETECTION_NOT_SUPPORTED:
601                 return "not-supported";
602             case CONTAMINANT_DETECTION_DISABLED:
603                 return "disabled";
604             case CONTAMINANT_DETECTION_DETECTED:
605                 return "detected";
606             case CONTAMINANT_DETECTION_NOT_DETECTED:
607                 return "not detected";
608             default:
609                 return Integer.toString(contaminantPresenceStatus);
610         }
611     }
612 
613     /** @hide */
usbDataStatusToString(int usbDataStatus)614     public static String usbDataStatusToString(int usbDataStatus) {
615         StringBuilder statusString = new StringBuilder();
616 
617         if (usbDataStatus == DATA_STATUS_UNKNOWN) {
618             return "unknown";
619         }
620 
621         if ((usbDataStatus & DATA_STATUS_ENABLED) == DATA_STATUS_ENABLED) {
622             return "enabled";
623         }
624 
625         if ((usbDataStatus & DATA_STATUS_DISABLED_OVERHEAT) == DATA_STATUS_DISABLED_OVERHEAT) {
626             statusString.append("disabled-overheat, ");
627         }
628 
629         if ((usbDataStatus & DATA_STATUS_DISABLED_CONTAMINANT)
630                 == DATA_STATUS_DISABLED_CONTAMINANT) {
631             statusString.append("disabled-contaminant, ");
632         }
633 
634         if ((usbDataStatus & DATA_STATUS_DISABLED_DOCK) == DATA_STATUS_DISABLED_DOCK) {
635             statusString.append("disabled-dock, ");
636         }
637 
638         if ((usbDataStatus & DATA_STATUS_DISABLED_FORCE) == DATA_STATUS_DISABLED_FORCE) {
639             statusString.append("disabled-force, ");
640         }
641 
642         if ((usbDataStatus & DATA_STATUS_DISABLED_DEBUG) == DATA_STATUS_DISABLED_DEBUG) {
643             statusString.append("disabled-debug, ");
644         }
645 
646         return statusString.toString().replaceAll(", $", "");
647     }
648 
649     /** @hide */
powerBrickConnectionStatusToString(int powerBrickConnectionStatus)650     public static String powerBrickConnectionStatusToString(int powerBrickConnectionStatus) {
651         switch (powerBrickConnectionStatus) {
652             case POWER_BRICK_STATUS_UNKNOWN:
653                 return "unknown";
654             case POWER_BRICK_STATUS_CONNECTED:
655                 return "connected";
656             case POWER_BRICK_STATUS_DISCONNECTED:
657                 return "disconnected";
658             default:
659                 return Integer.toString(powerBrickConnectionStatus);
660         }
661     }
662 
663     /** @hide */
roleCombinationsToString(int combo)664     public static String roleCombinationsToString(int combo) {
665         StringBuilder result = new StringBuilder();
666         result.append("[");
667 
668         boolean first = true;
669         while (combo != 0) {
670             final int index = Integer.numberOfTrailingZeros(combo);
671             combo &= ~(1 << index);
672             final int powerRole = (index / NUM_DATA_ROLES + POWER_ROLE_OFFSET);
673             final int dataRole = index % NUM_DATA_ROLES;
674             if (first) {
675                 first = false;
676             } else {
677                 result.append(", ");
678             }
679             result.append(powerRoleToString(powerRole));
680             result.append(':');
681             result.append(dataRoleToString(dataRole));
682         }
683 
684         result.append("]");
685         return result.toString();
686     }
687 
688     /** @hide */
checkMode(int powerRole)689     public static void checkMode(int powerRole) {
690         Preconditions.checkArgumentInRange(powerRole, Constants.PortMode.NONE,
691                 Constants.PortMode.NUM_MODES - 1, "portMode");
692     }
693 
694     /** @hide */
checkPowerRole(int dataRole)695     public static void checkPowerRole(int dataRole) {
696         Preconditions.checkArgumentInRange(dataRole, Constants.PortPowerRole.NONE,
697                 Constants.PortPowerRole.NUM_POWER_ROLES - 1, "powerRole");
698     }
699 
700     /** @hide */
checkDataRole(int mode)701     public static void checkDataRole(int mode) {
702         Preconditions.checkArgumentInRange(mode, Constants.PortDataRole.NONE,
703                 Constants.PortDataRole.NUM_DATA_ROLES - 1, "powerRole");
704     }
705 
706     /** @hide */
checkRoles(int powerRole, int dataRole)707     public static void checkRoles(int powerRole, int dataRole) {
708         Preconditions.checkArgumentInRange(powerRole, POWER_ROLE_NONE, POWER_ROLE_SINK,
709                 "powerRole");
710         Preconditions.checkArgumentInRange(dataRole, DATA_ROLE_NONE, DATA_ROLE_DEVICE, "dataRole");
711     }
712 
713     /** @hide */
isModeSupported(int mode)714     public boolean isModeSupported(int mode) {
715         if ((mSupportedModes & mode) == mode) return true;
716         return false;
717     }
718 
719     @NonNull
720     @Override
toString()721     public String toString() {
722         return "UsbPort{id=" + mId + ", supportedModes=" + modeToString(mSupportedModes)
723                 + "supportedContaminantProtectionModes=" + mSupportedContaminantProtectionModes
724                 + "supportsEnableContaminantPresenceProtection="
725                 + mSupportsEnableContaminantPresenceProtection
726                 + "supportsEnableContaminantPresenceDetection="
727                 + mSupportsEnableContaminantPresenceDetection;
728     }
729 }
730