3535import android .content .Context ;
3636import android .content .Intent ;
3737import android .content .IntentFilter ;
38+ import android .hardware .usb .UsbAccessory ;
39+ import android .hardware .usb .UsbManager ;
3840import android .os .Build ;
3941import android .os .ParcelFileDescriptor ;
4042
4749import java .io .OutputStream ;
4850import java .util .Collection ;
4951
50- import ioio .lib .android .UsbManagerAdapter .UsbAccessoryInterface ;
5152import ioio .lib .api .IOIOConnection ;
5253import ioio .lib .api .exception .ConnectionLostException ;
5354import ioio .lib .impl .FixedReadBufferedInputStream ;
5960public class AccessoryConnectionBootstrap extends BroadcastReceiver implements IOIOConnectionBootstrap , IOIOConnectionFactory {
6061 private static final String TAG = AccessoryConnectionBootstrap .class .getSimpleName ();
6162 private static final String ACTION_USB_PERMISSION = "ioio.lib.accessory.action.USB_PERMISSION" ;
63+ private static final String EXTRA_PERMISSION_GRANTED = UsbManager .EXTRA_PERMISSION_GRANTED ;
6264
6365 private final Context activity ;
64- private final UsbManagerAdapter . AbstractUsbManager usbManager ;
66+ private final UsbManager usbManager ;
6567 private boolean shouldTryOpen = false ;
6668 private PendingIntent pendingIntent ;
6769 private ParcelFileDescriptor fileDescriptor ;
6870 private InputStream inputStream ;
6971 private OutputStream outputStream ;
7072
73+ private enum InstanceState {
74+ INIT , CONNECTED , DEAD
75+ }
76+
7177 public AccessoryConnectionBootstrap () throws NoRuntimeSupportException {
7278 Log .d (TAG , "creating AccessoryConnectionBootstrap" );
73- UsbManagerAdapter usbManagerAdapter = new UsbManagerAdapter ();
74- activity = IOIOLoader .getContext ();
75- usbManager = usbManagerAdapter .getManager (activity );
79+ this .activity = IOIOLoader .getContext ();
80+ this .usbManager = (UsbManager ) activity .getSystemService (Context .USB_SERVICE );
7681 registerReceiver ();
7782 }
7883
84+ @ Override
85+ public IOIOConnection createConnection () {
86+ return new Connection ();
87+ }
88+
89+ @ Override
90+ public Object getExtra () {
91+ return null ;
92+ }
93+
94+ @ Override
95+ public void getFactories (Collection <IOIOConnectionFactory > result ) {
96+ result .add (this );
97+ }
98+
99+ @ Override
100+ public String getType () {
101+ return Connection .class .getCanonicalName ();
102+ }
103+
79104 //@Override
80105 public void onDestroy () {
81106 activity .unregisterReceiver (this );
@@ -86,7 +111,7 @@ public synchronized void onReceive(Context context, Intent intent) {
86111 final String action = intent .getAction ();
87112 if (ACTION_USB_PERMISSION .equals (action )) {
88113 pendingIntent = null ;
89- if (intent .getBooleanExtra (usbManager . EXTRA_PERMISSION_GRANTED , false )) {
114+ if (intent .getBooleanExtra (EXTRA_PERMISSION_GRANTED , false )) {
90115 notifyAll ();
91116 } else {
92117 Log .e (TAG , "Permission denied" );
@@ -127,46 +152,6 @@ private synchronized void disconnect() {
127152 Log .d (TAG , "leaving private disconnect" );
128153 }
129154
130- @ Override
131- public IOIOConnection createConnection () {
132- return new Connection ();
133- }
134-
135- @ Override
136- public void getFactories (Collection <IOIOConnectionFactory > result ) {
137- result .add (this );
138- }
139-
140- @ Override
141- public String getType () {
142- return Connection .class .getCanonicalName ();
143- }
144-
145- @ Override
146- public Object getExtra () {
147- return null ;
148- }
149-
150- private synchronized void waitForConnect (Connection connection ) throws ConnectionLostException {
151- // In order to simplify the connection process in face of many different sequences of events
152- // that might occur, we collapsed the entire sequence into one non-blocking method,
153- // tryOpen(), which tries the entire process from the beginning, undoes everything if
154- // something along the way fails and always returns immediately.
155- // This method, simply calls tryOpen() in a loop until it succeeds or until we're no longer
156- // interested. Between attempts, it waits until "something interesting" has happened, which
157- // may be permission granted, the client telling us to try again (via reopen()) or stop
158- // trying, etc.
159- shouldTryOpen = true ;
160- while (shouldTryOpen ) {
161- if (tryOpen ()) {
162- // Success!
163- return ;
164- }
165- forceWait ();
166- }
167- throw new ConnectionLostException ();
168- }
169-
170155 private void forceWait () {
171156 try {
172157 wait ();
@@ -175,10 +160,18 @@ private void forceWait() {
175160 }
176161 }
177162
163+ @ TargetApi (Build .VERSION_CODES .TIRAMISU )
164+ private void registerReceiver () {
165+ IntentFilter filter = new IntentFilter (ACTION_USB_PERMISSION );
166+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
167+ activity .registerReceiver (this , filter , Context .RECEIVER_NOT_EXPORTED );
168+ }
169+ }
170+
178171 private boolean tryOpen () {
179172 // Find the accessory.
180- UsbAccessoryInterface [] accessories = usbManager .getAccessoryList ();
181- UsbAccessoryInterface accessory = (accessories == null ? null : accessories [0 ]);
173+ UsbAccessory [] accessories = usbManager .getAccessoryList ();
174+ UsbAccessory accessory = (accessories == null ? null : accessories [0 ]);
182175
183176 if (accessory == null ) {
184177 Log .v (TAG , "No accessory found." );
@@ -251,14 +244,6 @@ private boolean tryOpen() {
251244 }
252245 }
253246
254- @ TargetApi (Build .VERSION_CODES .TIRAMISU )
255- private void registerReceiver () {
256- IntentFilter filter = new IntentFilter (ACTION_USB_PERMISSION );
257- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
258- activity .registerReceiver (this , filter , Context .RECEIVER_NOT_EXPORTED );
259- }
260- }
261-
262247 private void trySleep () {
263248 synchronized (AccessoryConnectionBootstrap .this ) {
264249 try {
@@ -269,13 +254,45 @@ private void trySleep() {
269254 }
270255 }
271256
272- private enum InstanceState {
273- INIT , CONNECTED , DEAD
257+ private synchronized void waitForConnect (Connection connection ) throws ConnectionLostException {
258+ // In order to simplify the connection process in face of many different sequences of events
259+ // that might occur, we collapsed the entire sequence into one non-blocking method,
260+ // tryOpen(), which tries the entire process from the beginning, undoes everything if
261+ // something along the way fails and always returns immediately.
262+ // This method, simply calls tryOpen() in a loop until it succeeds or until we're no longer
263+ // interested. Between attempts, it waits until "something interesting" has happened, which
264+ // may be permission granted, the client telling us to try again (via reopen()) or stop
265+ // trying, etc.
266+ shouldTryOpen = true ;
267+ while (shouldTryOpen ) {
268+ if (tryOpen ()) {
269+ // Success!
270+ return ;
271+ }
272+ forceWait ();
273+ }
274+ throw new ConnectionLostException ();
274275 }
275276
276277 private class Connection implements IOIOConnection {
277278 private InstanceState instanceState_ = InstanceState .INIT ;
278279
280+ @ Override
281+ public boolean canClose () {
282+ return false ;
283+ }
284+
285+ @ Override
286+ public void disconnect () {
287+ Log .d (TAG , "disconnect" );
288+ synchronized (AccessoryConnectionBootstrap .this ) {
289+ if (instanceState_ != InstanceState .DEAD ) {
290+ AccessoryConnectionBootstrap .this .disconnect ();
291+ instanceState_ = InstanceState .DEAD ;
292+ }
293+ }
294+ }
295+
279296 @ Override
280297 public InputStream getInputStream () {
281298 return inputStream ;
@@ -286,11 +303,6 @@ public OutputStream getOutputStream() {
286303 return outputStream ;
287304 }
288305
289- @ Override
290- public boolean canClose () {
291- return false ;
292- }
293-
294306 @ Override
295307 public void waitForConnect () throws ConnectionLostException {
296308 synchronized (AccessoryConnectionBootstrap .this ) {
@@ -309,18 +321,7 @@ public void waitForConnect() throws ConnectionLostException {
309321 }
310322
311323 @ Override
312- public void disconnect () {
313- Log .d (TAG , "disconnect" );
314- synchronized (AccessoryConnectionBootstrap .this ) {
315- if (instanceState_ != InstanceState .DEAD ) {
316- AccessoryConnectionBootstrap .this .disconnect ();
317- instanceState_ = InstanceState .DEAD ;
318- }
319- }
320- }
321-
322- @ Override
323- protected void finalize () throws Throwable {
324+ protected void finalize () {
324325 disconnect ();
325326 }
326327 }
0 commit comments