11package com .android .server .policy .keyguard ;
22
33import android .annotation .Nullable ;
4+ import android .app .ActivityThread ;
45import android .content .BroadcastReceiver ;
56import android .content .Context ;
67import android .content .Intent ;
1516import android .os .Process ;
1617import android .os .SystemProperties ;
1718import android .os .UserHandle ;
19+ import android .util .ArraySet ;
1820import android .util .Log ;
1921import android .util .Slog ;
2022
2325import com .android .server .utils .Slogf ;
2426
2527import java .util .ArrayList ;
28+ import java .util .Arrays ;
2629import java .util .Objects ;
2730
2831public class UsbPortSecurityHooks {
@@ -45,6 +48,10 @@ private UsbPortSecurityHooks(Context ctx) {
4548
4649 private static volatile int isSupportedCached ;
4750
51+ public static boolean isSupported () {
52+ return isSupported (ActivityThread .currentSystemContext ());
53+ }
54+
4855 public static boolean isSupported (Context ctx ) {
4956 int cache = isSupportedCached ;
5057 if (cache != 0 ) {
@@ -67,11 +74,11 @@ public static void setInitialMode(Context ctx) {
6774 switch (initialMode ) {
6875 case UsbPortSecurity .MODE_CHARGING_ONLY :
6976 case UsbPortSecurity .MODE_CHARGING_ONLY_WHEN_LOCKED :
70- setSecurityStateForAllPorts (ctx , PortSecurityState .CHARGING_ONLY_IMMEDIATE );
77+ setSecurityStateForAllPortsInner (ctx , PortSecurityState .CHARGING_ONLY_IMMEDIATE );
7178 break ;
7279 case UsbPortSecurity .MODE_CHARGING_ONLY_WHEN_LOCKED_AFU :
73- case UsbPortSecurity .MODE_ENABLED :
74- setSecurityStateForAllPorts (ctx , PortSecurityState .PORTS_ENABLED );
80+ case UsbPortSecurity .MODE_ALL_PORTS_ENABLED :
81+ setSecurityStateForAllPortsInner (ctx , PortSecurityState .PORTS_ENABLED );
7582 break ;
7683 }
7784 }
@@ -124,6 +131,70 @@ public void onReceive(Context context, Intent intent) {
124131 context .registerReceiver (receiver , filter , null , handler );
125132 }
126133
134+ private ArraySet <String > halEnabledPorts = new ArraySet <>();
135+ private ArraySet <String > halDisabledPorts = new ArraySet <>();
136+
137+ // implementation of the standard android.hardware.usb.IUsb.enableUsbDataSignal() API
138+ public static boolean onHalEnableUsbDataSignal (String portName , boolean enable ) {
139+ if (!isSupported ()) {
140+ return false ;
141+ }
142+ Slog .d (TAG , "onHalEnableUsbDataSignal: portName: " + portName + ", enable: " + enable );
143+
144+ if (INSTANCE == null ) {
145+ throw new IllegalStateException ("UsbPortSecurityHooks is not initialized" );
146+ }
147+
148+ INSTANCE .handler .post (() -> INSTANCE .onHalEnableUsbDataSignalInner (portName , enable ));
149+ return true ;
150+ }
151+
152+ public void onHalEnableUsbDataSignalInner (String portName , boolean enable ) {
153+ Slog .d (TAG , "onHalEnableUsbDataSignalInner: portName: " + portName + ", enable: " + enable );
154+
155+ if (enable ) {
156+ if (!halDisabledPorts .remove (portName )) {
157+ Slog .d (TAG , "port not found in halDisabledPorts" );
158+ }
159+ if (!halEnabledPorts .add (portName )) {
160+ Slog .d (TAG , "port already in halEnabledPorts" );
161+ }
162+ } else {
163+ if (!halEnabledPorts .remove (portName )) {
164+ Slog .d (TAG , "port not found in halEnabledPorts" );
165+ }
166+ if (!halDisabledPorts .add (portName )) {
167+ Slog .d (TAG , "port already in halDisabledPorts" );
168+ }
169+ }
170+
171+ Slog .d (TAG , "halDisabledPorts: " + Arrays .toString (halDisabledPorts .toArray ()) + ", halEnabledPorts: " + Arrays .toString (halEnabledPorts .toArray ()));
172+
173+ int setting = UsbPortSecurity .MODE_SETTING .get ();
174+
175+ if (!halDisabledPorts .isEmpty ()) {
176+ switch (setting ) {
177+ case UsbPortSecurity .MODE_CHARGING_ONLY_WHEN_LOCKED :
178+ case UsbPortSecurity .MODE_CHARGING_ONLY_WHEN_LOCKED_AFU :
179+ case UsbPortSecurity .MODE_ALL_PORTS_ENABLED :
180+ setSecurityStateForAllPorts (PortSecurityState .CHARGING_ONLY_IMMEDIATE );
181+ break ;
182+ }
183+ } else {
184+ switch (setting ) {
185+ case UsbPortSecurity .MODE_CHARGING_ONLY_WHEN_LOCKED :
186+ case UsbPortSecurity .MODE_CHARGING_ONLY_WHEN_LOCKED_AFU :
187+ if (prevKeyguardShowing != null && !prevKeyguardShowing .booleanValue ()) {
188+ setSecurityStateForAllPorts (PortSecurityState .PORTS_ENABLED );
189+ }
190+ break ;
191+ case UsbPortSecurity .MODE_ALL_PORTS_ENABLED :
192+ setSecurityStateForAllPorts (PortSecurityState .PORTS_ENABLED );
193+ break ;
194+ }
195+ }
196+ }
197+
127198 private static final ArrayList <Runnable > pendingCallbacks = new ArrayList <>();
128199
129200 public static void onKeyguardShowingStateChanged (Context ctx , boolean showing , int userId ) {
@@ -224,10 +295,19 @@ private interface PortSecurityState {
224295 }
225296
226297 private void setSecurityStateForAllPorts (String state ) {
227- setSecurityStateForAllPorts (context , state );
298+ if (!handler .getLooper ().isCurrentThread ()) {
299+ throw new IllegalStateException ("setSecurityStateForAllPorts() must be called on the handler thread" );
300+ }
301+
302+ if (PortSecurityState .PORTS_ENABLED .equals (state ) && !halDisabledPorts .isEmpty ()) {
303+ Slogf .d (TAG , "setSecurityStateForAllPorts: ignoring enable request since halDisabledPorts is %s" , Arrays .toString (halDisabledPorts .toArray ()));
304+ return ;
305+ }
306+
307+ setSecurityStateForAllPortsInner (context , state );
228308 }
229309
230- private static void setSecurityStateForAllPorts (Context ctx , String state ) {
310+ private static void setSecurityStateForAllPortsInner (Context ctx , String state ) {
231311 Slog .d (TAG , "setSecurityStateForAllPorts: " + state );
232312
233313 setDenyNewUsb2 (ctx , !state .equals (PortSecurityState .PORTS_ENABLED ));
@@ -263,11 +343,15 @@ public static void updateSetting(int newValue) {
263343 if (instance == null ) {
264344 throw new IllegalStateException ("no UsbPortSecurityHooks instance" );
265345 }
346+ instance .handler .post (() -> instance .updateSettingInner (newValue ));
347+ }
266348
267- if (!Boolean .FALSE .equals (instance .prevKeyguardShowing )) {
349+ private void updateSettingInner (int newValue ) {
350+ if (!Boolean .FALSE .equals (prevKeyguardShowing )) {
268351 // not strictly necessary, but allows to simplify the logic in code that changes port
269352 // security state below
270- throw new SecurityException ("keyguard has to be dismissed before calling this method" );
353+ Slog .e (TAG , "keyguard has to be dismissed before calling updateSetting()" );
354+ return ;
271355 }
272356
273357 int prevValue = UsbPortSecurity .MODE_SETTING .get ();
@@ -280,36 +364,36 @@ public static void updateSetting(int newValue) {
280364 // Turn USB ports off first to trigger reconnection of devices that were connected
281365 // in charging-only state. Simply enabling the data path is not enough in some
282366 // advanced scenarios, e.g. when port alt mode or port role switching are used.
283- instance . setSecurityStateForAllPorts (PortSecurityState .PORTS_DISABLED );
367+ setSecurityStateForAllPorts (PortSecurityState .PORTS_DISABLED );
284368 delayStateUpdate = true ;
285369 }
286370
287371 String state = switch (newValue ) {
288- case UsbPortSecurity .MODE_DISABLED ->
372+ case UsbPortSecurity .MODE_ALL_PORTS_DISABLED ->
289373 PortSecurityState .PORTS_DISABLED ;
290374 case UsbPortSecurity .MODE_CHARGING_ONLY ->
291375 PortSecurityState .CHARGING_ONLY_IMMEDIATE ;
292376 case UsbPortSecurity .MODE_CHARGING_ONLY_WHEN_LOCKED ,
293377 UsbPortSecurity .MODE_CHARGING_ONLY_WHEN_LOCKED_AFU ,
294- UsbPortSecurity .MODE_ENABLED ->
378+ UsbPortSecurity .MODE_ALL_PORTS_ENABLED ->
295379 PortSecurityState .PORTS_ENABLED ;
296380 default -> throw new IllegalArgumentException (Integer .toString (newValue ));
297381 };
298382
299383 if (delayStateUpdate ) {
300- final long curShowingChangeCount = instance . keyguardShowingChangeCount ;
384+ final long curShowingChangeCount = keyguardShowingChangeCount ;
301385 // it's hard to setup a proper callback to avoid this hardcoded delay, would need to
302386 // modify init and kernel
303387 final long delayMs = 1500 ;
304- instance . handler .postDelayed (() -> {
305- if (instance . keyguardShowingChangeCount == curShowingChangeCount ) {
306- instance . setSecurityStateForAllPorts (state );
388+ handler .postDelayed (() -> {
389+ if (keyguardShowingChangeCount == curShowingChangeCount ) {
390+ setSecurityStateForAllPorts (state );
307391 } else {
308392 Slog .d (TAG , "updateSetting: showingChangeCount changed, skipping delayed state change" );
309393 }
310394 }, delayMs );
311395 } else {
312- instance . setSecurityStateForAllPorts (state );
396+ setSecurityStateForAllPorts (state );
313397 }
314398 }
315399
0 commit comments